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>
This commit is contained in:
parent
99780a7b63
commit
970c4e4603
2 changed files with 86 additions and 0 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue