Bluetooth: Use unresolvable private address for active scanning
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 24 Feb 2014 04:25:54 +0000 (20:25 -0800)
committerJohan Hedberg <johan.hedberg@intel.com>
Mon, 24 Feb 2014 06:45:58 +0000 (08:45 +0200)
When running active scanning during LE discovery, do not reveal the own
identity to the peer devices. In case LE privacy has been enabled, then
a resolvable private address is used. If the LE privacy option is off,
then use an unresolvable private address.

The public address or static random address is never used in active
scanning anymore. This ensures that scan request are send using a
random address.

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

index 43b6d1131c4d75ec82ed2f0af38328d600c4a41a..0ee9cd11b3ef2f518576ffe5424961c7920b9001 100644 (file)
@@ -1256,7 +1256,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
                                                        __u8 ltk[16]);
 
-int hci_update_random_address(struct hci_request *req, u8 *own_addr_type);
+int hci_update_random_address(struct hci_request *req, bool require_privacy,
+                             u8 *own_addr_type);
 
 #define SCO_AIRMODE_MASK       0x0003
 #define SCO_AIRMODE_CVSD       0x0000
index a1efa1c62de88130aa0f09a4c11b2d444cd929f6..3d6b1cf07d234a9a606612e411f7909287a703de 100644 (file)
@@ -563,7 +563,10 @@ static int hci_create_le_conn(struct hci_conn *conn)
 
        memset(&cp, 0, sizeof(cp));
 
-       err = hci_update_random_address(&req, &own_addr_type);
+       /* Update random address, but set require_privacy to false so
+        * that we never connect with an unresolvable address.
+        */
+       err = hci_update_random_address(&req, false, &own_addr_type);
        if (err < 0)
                return err;
 
index 80462a126ebdeedcd7fe5dad93f339543efa712b..31e68ade309dc5e92c086f5e0fb5cc00878c8271 100644 (file)
@@ -3332,7 +3332,8 @@ static void le_scan_disable_work(struct work_struct *work)
                BT_ERR("Disable LE scanning request failed: err %d", err);
 }
 
-int hci_update_random_address(struct hci_request *req, u8 *own_addr_type)
+int hci_update_random_address(struct hci_request *req, bool require_privacy,
+                             u8 *own_addr_type)
 {
        struct hci_dev *hdev = req->hdev;
        int err;
@@ -3365,6 +3366,21 @@ int hci_update_random_address(struct hci_request *req, u8 *own_addr_type)
                return 0;
        }
 
+       /* In case of required privacy without resolvable private address,
+        * use an unresolvable private address. This is useful for active
+        * scanning and non-connectable advertising.
+        */
+       if (require_privacy) {
+               bdaddr_t urpa;
+
+               get_random_bytes(&urpa, 6);
+               urpa.b[5] &= 0x3f;      /* Clear two most significant bits */
+
+               *own_addr_type = ADDR_LE_DEV_RANDOM;
+               hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, &urpa);
+               return 0;
+       }
+
        /* If forcing static address is in use or there is no public
         * address use the static address as random address (but skip
         * the HCI command if the current random address is already the
index 37305facf4d6f9c310caad3f132dde6af874130d..5d309d4ab527ebc98944d553adbc3cb3c73d0199 100644 (file)
@@ -844,7 +844,7 @@ static void enable_advertising(struct hci_request *req)
 
        memset(&cp, 0, sizeof(cp));
 
-       if (hci_update_random_address(req, &own_addr_type) < 0)
+       if (hci_update_random_address(req, false, &own_addr_type) < 0)
                return;
 
        cp.min_interval = __constant_cpu_to_le16(0x0800);
@@ -3389,7 +3389,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 
                memset(&param_cp, 0, sizeof(param_cp));
 
-               err = hci_update_random_address(&req, &own_addr_type);
+               /* All active scans will be done with either a resolvable
+                * private address (when privacy feature has been enabled)
+                * or unresolvable private address.
+                */
+               err = hci_update_random_address(&req, true, &own_addr_type);
                if (err < 0) {
                        err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
                                         MGMT_STATUS_FAILED);