From b6020ba055c7f1ca901dc8751ecc7c9de58164db Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 28 Apr 2011 12:07:53 +0200 Subject: Bluetooth: Add definitions for link key types Introduce the link key types defs and use them instead of magic numbers. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/hci_core.c') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 98aa24b92c5..07d0ba35b9a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1050,7 +1050,7 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, if (new_key) mgmt_new_key(hdev->id, key, old_key_type); - if (type == 0x06) + if (type == HCI_LK_CHANGED_COMBINATION) key->type = old_key_type; return 0; -- cgit v1.2.3 From d25e28abe58d2bcedf6025a6ccc532c29a19046f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:28:59 -0700 Subject: Bluetooth: Fix link key persistent storage criteria Link keys should only be stored if very specific criteria of the authentication process are fulfilled. This patch essentially copies the criteria that user space has so far been using to the kernel side so that the management interface works properly. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'net/bluetooth/hci_core.c') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 07d0ba35b9a..5f55aef63e2 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1022,8 +1022,44 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) return NULL; } -int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, - u8 *val, u8 type, u8 pin_len) +static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, + u8 key_type, u8 old_key_type) +{ + /* Legacy key */ + if (key_type < 0x03) + return 1; + + /* Debug keys are insecure so don't store them persistently */ + if (key_type == HCI_LK_DEBUG_COMBINATION) + return 0; + + /* Changed combination key and there's no previous one */ + if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) + return 0; + + /* Security mode 3 case */ + if (!conn) + return 1; + + /* Neither local nor remote side had no-bonding as requirement */ + if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) + return 1; + + /* Local side had dedicated bonding as requirement */ + if (conn->auth_type == 0x02 || conn->auth_type == 0x03) + return 1; + + /* Remote side had dedicated bonding as requirement */ + if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) + return 1; + + /* If none of the above criteria match, then don't store the key + * persistently */ + return 0; +} + +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) { struct link_key *key, *old_key; u8 old_key_type; @@ -1042,6 +1078,20 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); + /* Some buggy controller combinations generate a changed + * combination key for legacy pairing even when there's no + * previous key */ + if (type == HCI_LK_CHANGED_COMBINATION && + (!conn || conn->remote_auth == 0xff) && + old_key_type == 0xff) + type = HCI_LK_COMBINATION; + + if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { + list_del(&key->list); + kfree(key); + return 0; + } + bacpy(&key->bdaddr, bdaddr); memcpy(key->val, val, 16); key->type = type; -- cgit v1.2.3 From 12adcf3a953c3aa4006d855aa638133bf018ceac Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:00 -0700 Subject: Bluetooth: Fix old_key_type logic for non-persistent keys Even if there's no previous key stored the connection might still be secured with a non-persistent key and in that case the key type in the hci_conn struct should be checked. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/hci_core.c') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5f55aef63e2..2ac6036b70c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1069,7 +1069,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, old_key_type = old_key->type; key = old_key; } else { - old_key_type = 0xff; + old_key_type = conn ? conn->key_type : 0xff; key = kzalloc(sizeof(*key), GFP_ATOMIC); if (!key) return -ENOMEM; -- cgit v1.2.3 From 655fe6ece7e71b37c17577ae485d11bf701c95f7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:01 -0700 Subject: Bluetooth: Fix connection key type updating for buggy controllers If a controller generates a changed combination key as its first key the connection key type will not be correctly set. In these situations make sure the update the connection key type when such a buggy controller is detected. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/bluetooth/hci_core.c') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2ac6036b70c..59ca4755b6b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1083,8 +1083,11 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, * previous key */ if (type == HCI_LK_CHANGED_COMBINATION && (!conn || conn->remote_auth == 0xff) && - old_key_type == 0xff) + old_key_type == 0xff) { type = HCI_LK_COMBINATION; + if (conn) + conn->key_type = type; + } if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { list_del(&key->list); -- cgit v1.2.3 From 4748fed2d1a2a7a816277754498b8aa70850e051 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:02 -0700 Subject: Bluetooth: Remove old_key_type from mgmt_ev_new_key User space shouldn't have any need for the old key type so remove it from the corresponding Management interface event. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/hci_core.c') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 59ca4755b6b..60260cae3a0 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1097,14 +1097,15 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bacpy(&key->bdaddr, bdaddr); memcpy(key->val, val, 16); - key->type = type; key->pin_len = pin_len; - if (new_key) - mgmt_new_key(hdev->id, key, old_key_type); - if (type == HCI_LK_CHANGED_COMBINATION) key->type = old_key_type; + else + key->type = type; + + if (new_key) + mgmt_new_key(hdev->id, key); return 0; } -- cgit v1.2.3 From 4df378a10e31698df1679f3329301d773a654b61 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 28 Apr 2011 11:29:03 -0700 Subject: Bluetooth: Add store_hint parameter to mgmt_new_key Even for keys that shouldn't be stored some use cases require the knowledge of a new key having been created so that the conclusion of a successful pairing can be made. Therefore, always send the mgmt_new_key event but add a store_hint parameter to it to indicate to user space whether the key should be stored or not. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'net/bluetooth/hci_core.c') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 60260cae3a0..b6bda3fac10 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1062,7 +1062,7 @@ 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) { struct link_key *key, *old_key; - u8 old_key_type; + u8 old_key_type, persistent; old_key = hci_find_link_key(hdev, bdaddr); if (old_key) { @@ -1089,12 +1089,6 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, conn->key_type = type; } - if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { - list_del(&key->list); - kfree(key); - return 0; - } - bacpy(&key->bdaddr, bdaddr); memcpy(key->val, val, 16); key->pin_len = pin_len; @@ -1104,8 +1098,17 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, else key->type = type; - if (new_key) - mgmt_new_key(hdev->id, key); + if (!new_key) + return 0; + + persistent = hci_persistent_key(hdev, conn, type, old_key_type); + + mgmt_new_key(hdev->id, key, persistent); + + if (!persistent) { + list_del(&key->list); + kfree(key); + } return 0; } -- cgit v1.2.3