diff options
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r-- | net/bluetooth/hci_core.c | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 07d0ba35b9a5..5f55aef63e20 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) | |||
1022 | return NULL; | 1022 | return NULL; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, | 1025 | static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, |
1026 | u8 *val, u8 type, u8 pin_len) | 1026 | u8 key_type, u8 old_key_type) |
1027 | { | ||
1028 | /* Legacy key */ | ||
1029 | if (key_type < 0x03) | ||
1030 | return 1; | ||
1031 | |||
1032 | /* Debug keys are insecure so don't store them persistently */ | ||
1033 | if (key_type == HCI_LK_DEBUG_COMBINATION) | ||
1034 | return 0; | ||
1035 | |||
1036 | /* Changed combination key and there's no previous one */ | ||
1037 | if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) | ||
1038 | return 0; | ||
1039 | |||
1040 | /* Security mode 3 case */ | ||
1041 | if (!conn) | ||
1042 | return 1; | ||
1043 | |||
1044 | /* Neither local nor remote side had no-bonding as requirement */ | ||
1045 | if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) | ||
1046 | return 1; | ||
1047 | |||
1048 | /* Local side had dedicated bonding as requirement */ | ||
1049 | if (conn->auth_type == 0x02 || conn->auth_type == 0x03) | ||
1050 | return 1; | ||
1051 | |||
1052 | /* Remote side had dedicated bonding as requirement */ | ||
1053 | if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) | ||
1054 | return 1; | ||
1055 | |||
1056 | /* If none of the above criteria match, then don't store the key | ||
1057 | * persistently */ | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | ||
1062 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) | ||
1027 | { | 1063 | { |
1028 | struct link_key *key, *old_key; | 1064 | struct link_key *key, *old_key; |
1029 | u8 old_key_type; | 1065 | u8 old_key_type; |
@@ -1042,6 +1078,20 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, | |||
1042 | 1078 | ||
1043 | BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); | 1079 | BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); |
1044 | 1080 | ||
1081 | /* Some buggy controller combinations generate a changed | ||
1082 | * combination key for legacy pairing even when there's no | ||
1083 | * previous key */ | ||
1084 | if (type == HCI_LK_CHANGED_COMBINATION && | ||
1085 | (!conn || conn->remote_auth == 0xff) && | ||
1086 | old_key_type == 0xff) | ||
1087 | type = HCI_LK_COMBINATION; | ||
1088 | |||
1089 | if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { | ||
1090 | list_del(&key->list); | ||
1091 | kfree(key); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1045 | bacpy(&key->bdaddr, bdaddr); | 1095 | bacpy(&key->bdaddr, bdaddr); |
1046 | memcpy(key->val, val, 16); | 1096 | memcpy(key->val, val, 16); |
1047 | key->type = type; | 1097 | key->type = type; |