瀏覽代碼

Bluetooth: Add basic IRK management support

This patch adds the initial IRK storage and management functions to the
HCI core. This includes storing a list of IRKs per HCI device and the
ability to add, remove and lookup entries in that list.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Johan Hedberg 11 年之前
父節點
當前提交
970c4e4603
共有 2 個文件被更改,包括 86 次插入0 次删除
  1. 16 0
      include/net/bluetooth/hci_core.h
  2. 70 0
      net/bluetooth/hci_core.c

+ 16 - 0
include/net/bluetooth/hci_core.h

@@ -103,6 +103,14 @@ struct smp_ltk {
 	u8 val[16];
 	u8 val[16];
 };
 };
 
 
+struct smp_irk {
+	struct list_head list;
+	bdaddr_t rpa;
+	bdaddr_t bdaddr;
+	u8 addr_type;
+	u8 val[16];
+};
+
 struct link_key {
 struct link_key {
 	struct list_head list;
 	struct list_head list;
 	bdaddr_t bdaddr;
 	bdaddr_t bdaddr;
@@ -269,6 +277,7 @@ struct hci_dev {
 	struct list_head	uuids;
 	struct list_head	uuids;
 	struct list_head	link_keys;
 	struct list_head	link_keys;
 	struct list_head	long_term_keys;
 	struct list_head	long_term_keys;
+	struct list_head	identity_resolving_keys;
 	struct list_head	remote_oob_data;
 	struct list_head	remote_oob_data;
 	struct list_head	le_conn_params;
 	struct list_head	le_conn_params;
 
 
@@ -787,6 +796,13 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_smp_ltks_clear(struct hci_dev *hdev);
 int hci_smp_ltks_clear(struct hci_dev *hdev);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 
+struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa);
+struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 addr_type);
+int hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type,
+		u8 val[16], bdaddr_t *rpa);
+void hci_smp_irks_clear(struct hci_dev *hdev);
+
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
 					  bdaddr_t *bdaddr);
 					  bdaddr_t *bdaddr);

+ 70 - 0
net/bluetooth/hci_core.c

@@ -35,6 +35,8 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/hci_core.h>
 
 
+#include "smp.h"
+
 static void hci_rx_work(struct work_struct *work);
 static void hci_rx_work(struct work_struct *work);
 static void hci_cmd_work(struct work_struct *work);
 static void hci_cmd_work(struct work_struct *work);
 static void hci_tx_work(struct work_struct *work);
 static void hci_tx_work(struct work_struct *work);
@@ -2544,6 +2546,16 @@ int hci_smp_ltks_clear(struct hci_dev *hdev)
 	return 0;
 	return 0;
 }
 }
 
 
+void hci_smp_irks_clear(struct hci_dev *hdev)
+{
+	struct smp_irk *k, *tmp;
+
+	list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
+		list_del(&k->list);
+		kfree(k);
+	}
+}
+
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 {
 	struct link_key *k;
 	struct link_key *k;
@@ -2632,6 +2644,39 @@ struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
 	return NULL;
 	return NULL;
 }
 }
 
 
+struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
+{
+	struct smp_irk *irk;
+
+	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
+		if (!bacmp(&irk->rpa, rpa))
+			return irk;
+	}
+
+	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
+		if (smp_irk_matches(hdev->tfm_aes, irk->val, rpa)) {
+			bacpy(&irk->rpa, rpa);
+			return irk;
+		}
+	}
+
+	return NULL;
+}
+
+struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 addr_type)
+{
+	struct smp_irk *irk;
+
+	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
+		if (addr_type == irk->addr_type &&
+		    bacmp(bdaddr, &irk->bdaddr) == 0)
+			return irk;
+	}
+
+	return NULL;
+}
+
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 		     bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 		     bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
 {
@@ -2726,6 +2771,29 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type,
 	return 0;
 	return 0;
 }
 }
 
 
+int hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type,
+		u8 val[16], bdaddr_t *rpa)
+{
+	struct smp_irk *irk;
+
+	irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type);
+	if (!irk) {
+		irk = kzalloc(sizeof(*irk), GFP_KERNEL);
+		if (!irk)
+			return -ENOMEM;
+
+		bacpy(&irk->bdaddr, bdaddr);
+		irk->addr_type = addr_type;
+
+		list_add(&irk->list, &hdev->identity_resolving_keys);
+	}
+
+	memcpy(irk->val, val, 16);
+	bacpy(&irk->rpa, rpa);
+
+	return 0;
+}
+
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 {
 	struct link_key *key;
 	struct link_key *key;
@@ -3120,6 +3188,7 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_LIST_HEAD(&hdev->uuids);
 	INIT_LIST_HEAD(&hdev->uuids);
 	INIT_LIST_HEAD(&hdev->link_keys);
 	INIT_LIST_HEAD(&hdev->link_keys);
 	INIT_LIST_HEAD(&hdev->long_term_keys);
 	INIT_LIST_HEAD(&hdev->long_term_keys);
+	INIT_LIST_HEAD(&hdev->identity_resolving_keys);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
 	INIT_LIST_HEAD(&hdev->le_conn_params);
 	INIT_LIST_HEAD(&hdev->le_conn_params);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
@@ -3320,6 +3389,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
 	hci_uuids_clear(hdev);
 	hci_uuids_clear(hdev);
 	hci_link_keys_clear(hdev);
 	hci_link_keys_clear(hdev);
 	hci_smp_ltks_clear(hdev);
 	hci_smp_ltks_clear(hdev);
+	hci_smp_irks_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
 	hci_conn_params_clear(hdev);
 	hci_conn_params_clear(hdev);
 	hci_dev_unlock(hdev);
 	hci_dev_unlock(hdev);