Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6

This commit is contained in:
John W. Linville
2011-04-29 15:28:49 -04:00
15 changed files with 906 additions and 503 deletions

View File

@@ -1020,18 +1020,54 @@ 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;
u8 old_key_type, persistent;
old_key = hci_find_link_key(hdev, bdaddr);
if (old_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;
@@ -1040,16 +1076,37 @@ 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 (conn)
conn->key_type = type;
}
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 == 0x06)
if (type == HCI_LK_CHANGED_COMBINATION)
key->type = old_key_type;
else
key->type = type;
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;
}