Bluetooth: Cache LE Address Type with LTK, and use for reconnections

LE-Only devices require that an Address Type (Public or Random) be
included in Connection Requests. This info is available at Pairing
but must be cached so that it is available at reconnection time.
This change includes the Address type with the Pairing data.

Change-Id: I50c78ad31d8be70f5c3f49a0529039e4a26daaac
Signed-off-by: Brian Gix <bgix@codeaurora.org>
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d0da174..74e14fb 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -91,7 +91,8 @@
 
 struct link_key_data {
 	bdaddr_t bdaddr;
-	u8 type;
+	u8 addr_type;
+	u8 key_type;
 	u8 val[16];
 	u8 pin_len;
 	u8 auth;
@@ -102,7 +103,8 @@
 struct link_key {
 	struct list_head list;
 	bdaddr_t bdaddr;
-	u8 type;
+	u8 addr_type;
+	u8 key_type;
 	u8 val[16];
 	u8 pin_len;
 	u8 auth;
@@ -689,7 +691,7 @@
 struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
 struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
 					bdaddr_t *bdaddr, u8 type);
-int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
+int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, u8 type,
 		u8 auth, u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 208c157..127c7ca 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -100,7 +100,8 @@
 
 struct mgmt_key_info {
 	bdaddr_t bdaddr;
-	u8 type;
+	u8 addr_type;
+	u8 key_type;
 	u8 val[16];
 	u8 pin_len;
 	u8 auth;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 733e9d2..5e67829 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -631,6 +631,7 @@
 
 	if (type == LE_LINK) {
 		struct adv_entry *entry;
+		struct link_key *key;
 
 		le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
 		if (le) {
@@ -638,11 +639,17 @@
 			return le;
 		}
 
-		entry = hci_find_adv_entry(hdev, dst);
-		if (!entry)
-			le = hci_le_conn_add(hdev, dst, 0);
-		else
-			le = hci_le_conn_add(hdev, dst, entry->bdaddr_type);
+		key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
+		if (!key) {
+			entry = hci_find_adv_entry(hdev, dst);
+			if (entry)
+				le = hci_le_conn_add(hdev, dst,
+						entry->bdaddr_type);
+			else
+				le = hci_le_conn_add(hdev, dst, 0);
+		} else {
+			le = hci_le_conn_add(hdev, dst, key->addr_type);
+		}
 
 		if (!le)
 			return ERR_PTR(-ENOMEM);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 699284a..0fa1262 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1065,7 +1065,7 @@
 
 		k = list_entry(p, struct link_key, list);
 
-		if (k->type != KEY_TYPE_LTK)
+		if (k->key_type != KEY_TYPE_LTK)
 			continue;
 
 		if (k->dlen != sizeof(*id))
@@ -1091,7 +1091,7 @@
 
 		k = list_entry(p, struct link_key, list);
 
-		if ((k->type == type) && (bacmp(bdaddr, &k->bdaddr) == 0))
+		if ((k->key_type == type) && (bacmp(bdaddr, &k->bdaddr) == 0))
 			return k;
 	}
 
@@ -1109,7 +1109,7 @@
 
 	old_key = hci_find_link_key(hdev, bdaddr);
 	if (old_key) {
-		old_key_type = old_key->type;
+		old_key_type = old_key->key_type;
 		key = old_key;
 	} else {
 		old_key_type = 0xff;
@@ -1124,7 +1124,7 @@
 	bacpy(&key->bdaddr, bdaddr);
 	memcpy(key->val, val, 16);
 	key->auth = 0x01;
-	key->type = type;
+	key->key_type = type;
 	key->pin_len = pin_len;
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
@@ -1142,8 +1142,8 @@
 	if (conn) {
 		if ((conn->remote_auth > 0x01) ||
 			(conn->auth_initiator && conn->auth_type > 0x01) ||
-			(key->type < 0x03) ||
-			(key->type == 0x06 && old_key_type != 0xff))
+			(key->key_type < 0x03) ||
+			(key->key_type == 0x06 && old_key_type != 0xff))
 			bonded = 1;
 	}
 
@@ -1151,19 +1151,20 @@
 		mgmt_new_key(hdev->id, key, bonded);
 
 	if (type == 0x06)
-		key->type = old_key_type;
+		key->key_type = old_key_type;
 
 	return 0;
 }
 
 int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
-			u8 key_size, u8 auth, __le16 ediv, u8 rand[8],
-			u8 ltk[16])
+			u8 addr_type, u8 key_size, u8 auth,
+			__le16 ediv, u8 rand[8], u8 ltk[16])
 {
 	struct link_key *key, *old_key;
 	struct key_master_id *id;
 
-	BT_DBG("%s Auth: %2.2X addr %s", hdev->name, auth, batostr(bdaddr));
+	BT_DBG("%s Auth: %2.2X addr %s type: %d", hdev->name, auth,
+						batostr(bdaddr), addr_type);
 
 	old_key = hci_find_link_key_type(hdev, bdaddr, KEY_TYPE_LTK);
 	if (old_key) {
@@ -1178,8 +1179,9 @@
 	key->dlen = sizeof(*id);
 
 	bacpy(&key->bdaddr, bdaddr);
+	key->addr_type = addr_type;
 	memcpy(key->val, ltk, sizeof(key->val));
-	key->type = KEY_TYPE_LTK;
+	key->key_type = KEY_TYPE_LTK;
 	key->pin_len = key_size;
 	key->auth = auth;
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index da8b780..75c3e04 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2486,10 +2486,10 @@
 		goto not_found;
 	}
 
-	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
+	BT_DBG("%s found key type %u for %s", hdev->name, key->key_type,
 							batostr(&ev->bdaddr));
 
-	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
+	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->key_type == 0x03) {
 		BT_DBG("%s ignoring debug key", hdev->name);
 		goto not_found;
 	}
@@ -2507,7 +2507,7 @@
 		goto not_found;
 	}
 
-	if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
+	if (key->key_type == 0x04 && conn && conn->auth_type != 0xff &&
 						(conn->auth_type & 0x01)) {
 		BT_DBG("%s ignoring unauthenticated key", hdev->name);
 		goto not_found;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ea72708..77845f2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1099,19 +1099,20 @@
 
 		i += sizeof(*key);
 
-		if (key->type == KEY_TYPE_LTK) {
+		if (key->key_type == KEY_TYPE_LTK) {
 			struct key_master_id *id = (void *) key->data;
 
 			if (key->dlen != sizeof(struct key_master_id))
 				continue;
 
-			hci_add_ltk(hdev, 0, &key->bdaddr, key->pin_len,
-				key->auth, id->ediv, id->rand, key->val);
+			hci_add_ltk(hdev, 0, &key->bdaddr, key->addr_type,
+					key->pin_len, key->auth, id->ediv,
+					id->rand, key->val);
 
 			continue;
 		}
 
-		hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
+		hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->key_type,
 								key->pin_len);
 	}
 
@@ -2393,7 +2394,8 @@
 		return -ENOMEM;
 
 	bacpy(&ev->key.bdaddr, &key->bdaddr);
-	ev->key.type = key->type;
+	ev->key.addr_type = key->addr_type;
+	ev->key.key_type = key->key_type;
 	memcpy(ev->key.val, key->val, 16);
 	ev->key.pin_len = key->pin_len;
 	ev->key.auth = key->auth;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 742d520..e725148 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -637,8 +637,8 @@
 		memset(stk + hcon->smp_key_size, 0,
 				SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
 
-		hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->smp_key_size,
-						hcon->auth, ediv, rand, stk);
+		hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
+			hcon->smp_key_size, hcon->auth, ediv, rand, stk);
 	}
 
 	return 0;
@@ -797,8 +797,8 @@
 
 	memset(rand, 0, sizeof(rand));
 
-	err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
-							rand, rp->ltk);
+	err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
+						0, 0, 0, rand, rp->ltk);
 	if (err)
 		return SMP_UNSPECIFIED;
 
@@ -826,8 +826,9 @@
 
 	BT_DBG("keydist 0x%x", *keydist);
 
-	hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
-				hcon->auth, rp->ediv, rp->rand, key->val);
+	hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
+			hcon->smp_key_size, hcon->auth, rp->ediv,
+			rp->rand, key->val);
 
 	*keydist &= ~SMP_DIST_ENC_KEY;
 	if (hcon->out) {
@@ -964,8 +965,9 @@
 
 		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
 
-		hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
-					hcon->auth, ediv, ident.rand, enc.ltk);
+		hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
+				hcon->smp_key_size, hcon->auth, ediv,
+				ident.rand, enc.ltk);
 
 		ident.ediv = cpu_to_le16(ediv);