From 7ee4ea3692f20b87b0e0d3884d5b2d22ec1a2df0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 9 Mar 2014 12:19:17 -0700 Subject: Bluetooth: Add support for handling signature resolving keys The connection signature resolving key (CSRK) is used for attribute protocol signed write procedures. This change generates a new local key during pairing and requests the peer key as well. Newly generated key and received key will be provided to userspace using the New Signature Resolving Key management event. The Master CSRK can be used for verification of remote signed write PDUs and the Slave CSRK can be used for sending signed write PDUs to the remote device. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 8 ++++++++ include/net/bluetooth/mgmt.h | 12 ++++++++++++ 2 files changed, 20 insertions(+) (limited to 'include/net') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index dbb788e4f265..e869884fbfa9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -91,6 +91,13 @@ struct bt_uuid { u8 svc_hint; }; +struct smp_csrk { + bdaddr_t bdaddr; + u8 bdaddr_type; + u8 master; + u8 val[16]; +}; + struct smp_ltk { struct list_head list; bdaddr_t bdaddr; @@ -1265,6 +1272,7 @@ int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key); void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk); +void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk); void mgmt_reenable_advertising(struct hci_dev *hdev); void mgmt_smp_complete(struct hci_conn *conn, bool complete); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 0326648fd799..d4b571c2f9fd 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -551,3 +551,15 @@ struct mgmt_ev_new_irk { bdaddr_t rpa; struct mgmt_irk_info irk; } __packed; + +struct mgmt_csrk_info { + struct mgmt_addr_info addr; + __u8 master; + __u8 val[16]; +} __packed; + +#define MGMT_EV_NEW_CSRK 0x0019 +struct mgmt_ev_new_csrk { + __u8 store_hint; + struct mgmt_csrk_info key; +} __packed; -- cgit v1.2.3-55-g7522 From 53ac6ab612456a13bf0f6bad89c1503616e4de3b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 9 Mar 2014 23:38:42 -0700 Subject: Bluetooth: Make LTK and CSRK only persisent when bonding In case the pairable option has been disabled, the pairing procedure does not create keys for bonding. This means that these generated keys should not be stored persistently. For LTK and CSRK this is important to tell userspace to not store these new keys. They will be available for the lifetime of the device, but after the next power cycle they should not be used anymore. Inform userspace to actually store the keys persistently only if both sides request bonding. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 5 +++-- net/bluetooth/mgmt.c | 9 +++++---- net/bluetooth/smp.c | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) (limited to 'include/net') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e869884fbfa9..b8cc39a4a9a5 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1270,9 +1270,10 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); -void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key); +void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent); void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk); -void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk); +void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, + bool persistent); void mgmt_reenable_advertising(struct hci_dev *hdev); void mgmt_smp_complete(struct hci_conn *conn, bool complete); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9c7788914b4e..fbcf9d4f130b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5005,7 +5005,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); } -void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key) +void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) { struct mgmt_ev_new_long_term_key ev; @@ -5026,7 +5026,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key) (key->bdaddr.b[5] & 0xc0) != 0xc0) ev.store_hint = 0x00; else - ev.store_hint = 0x01; + ev.store_hint = persistent; bacpy(&ev.key.addr.bdaddr, &key->bdaddr); ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type); @@ -5073,7 +5073,8 @@ void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk) mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL); } -void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk) +void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, + bool persistent) { struct mgmt_ev_new_csrk ev; @@ -5092,7 +5093,7 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk) (csrk->bdaddr.b[5] & 0xc0) != 0xc0) ev.store_hint = 0x00; else - ev.store_hint = 0x01; + ev.store_hint = persistent; bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr); ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index fc652592daf6..7f25dda9c770 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -1209,32 +1209,40 @@ static void smp_notify_keys(struct l2cap_conn *conn) struct smp_chan *smp = conn->smp_chan; struct hci_conn *hcon = conn->hcon; struct hci_dev *hdev = hcon->hdev; + struct smp_cmd_pairing *req = (void *) &smp->preq[1]; + struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1]; + bool persistent; if (smp->remote_irk) mgmt_new_irk(hdev, smp->remote_irk); + /* The LTKs and CSRKs should be persistent only if both sides + * had the bonding bit set in their authentication requests. + */ + persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING); + if (smp->csrk) { smp->csrk->bdaddr_type = hcon->dst_type; bacpy(&smp->csrk->bdaddr, &hcon->dst); - mgmt_new_csrk(hdev, smp->csrk); + mgmt_new_csrk(hdev, smp->csrk, persistent); } if (smp->slave_csrk) { smp->slave_csrk->bdaddr_type = hcon->dst_type; bacpy(&smp->slave_csrk->bdaddr, &hcon->dst); - mgmt_new_csrk(hdev, smp->slave_csrk); + mgmt_new_csrk(hdev, smp->slave_csrk, persistent); } if (smp->ltk) { smp->ltk->bdaddr_type = hcon->dst_type; bacpy(&smp->ltk->bdaddr, &hcon->dst); - mgmt_new_ltk(hdev, smp->ltk); + mgmt_new_ltk(hdev, smp->ltk, persistent); } if (smp->slave_ltk) { smp->slave_ltk->bdaddr_type = hcon->dst_type; bacpy(&smp->slave_ltk->bdaddr, &hcon->dst); - mgmt_new_ltk(hdev, smp->slave_ltk); + mgmt_new_ltk(hdev, smp->slave_ltk, persistent); } } -- cgit v1.2.3-55-g7522