mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-28 18:32:41 +00:00
fix sending of Connection Result - Pending, request authentication if security level isn't enough
This commit is contained in:
parent
ea8b28d601
commit
34d2123c9e
@ -80,7 +80,11 @@ typedef enum {
|
|||||||
* @praram enabled
|
* @praram enabled
|
||||||
*/
|
*/
|
||||||
void gap_set_bondable_mode(int enabled);
|
void gap_set_bondable_mode(int enabled);
|
||||||
|
|
||||||
|
gap_security_level_t gap_security_level_for_link_key_type(link_key_type_t link_key_type);
|
||||||
|
gap_security_level_t gap_security_level_for_connection(hci_connection_t * connection);
|
||||||
gap_security_level_t gap_security_level(hci_con_handle_t con_handle);
|
gap_security_level_t gap_security_level(hci_con_handle_t con_handle);
|
||||||
|
|
||||||
void gap_request_security_level(hci_con_handle_t con_handle, gap_security_level_t level);
|
void gap_request_security_level(hci_con_handle_t con_handle, gap_security_level_t level);
|
||||||
|
|
||||||
#if defined __cplusplus
|
#if defined __cplusplus
|
||||||
|
94
src/hci.c
94
src/hci.c
@ -130,6 +130,7 @@ static hci_connection_t * create_connection_for_addr(bd_addr_t addr){
|
|||||||
conn->con_handle = 0xffff;
|
conn->con_handle = 0xffff;
|
||||||
conn->authentication_flags = AUTH_FLAGS_NONE;
|
conn->authentication_flags = AUTH_FLAGS_NONE;
|
||||||
conn->bonding_flags = 0;
|
conn->bonding_flags = 0;
|
||||||
|
conn->requested_security_level = LEVEL_0;
|
||||||
linked_item_set_user(&conn->timeout.item, conn);
|
linked_item_set_user(&conn->timeout.item, conn);
|
||||||
conn->timeout.process = hci_connection_timeout_handler;
|
conn->timeout.process = hci_connection_timeout_handler;
|
||||||
hci_connection_timestamp(conn);
|
hci_connection_timestamp(conn);
|
||||||
@ -704,6 +705,16 @@ static void event_handler(uint8_t *packet, int size){
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HCI_EVENT_AUTHENTICATION_COMPLETE:
|
||||||
|
handle = READ_BT_16(packet, 3);
|
||||||
|
conn = hci_connection_for_handle(handle);
|
||||||
|
if (!conn) break;
|
||||||
|
if (conn->bonding_flags->BONDING_REQUESTED){
|
||||||
|
gap_security_level_t level = gap_security_level_for_connection(conn);
|
||||||
|
hci_emit_security_level(handle, packet[2], level);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#ifndef EMBEDDED
|
#ifndef EMBEDDED
|
||||||
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
|
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
|
||||||
if (!hci_stack.remote_device_db) break;
|
if (!hci_stack.remote_device_db) break;
|
||||||
@ -1220,63 +1231,70 @@ void hci_run(){
|
|||||||
|
|
||||||
if (connection->state == RECEIVED_CONNECTION_REQUEST){
|
if (connection->state == RECEIVED_CONNECTION_REQUEST){
|
||||||
log_info("sending hci_accept_connection_request\n");
|
log_info("sending hci_accept_connection_request\n");
|
||||||
hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
|
|
||||||
connection->state = ACCEPTED_CONNECTION_REQUEST;
|
connection->state = ACCEPTED_CONNECTION_REQUEST;
|
||||||
|
hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->authentication_flags & HANDLE_LINK_KEY_REQUEST){
|
if (connection->authentication_flags & HANDLE_LINK_KEY_REQUEST){
|
||||||
|
log_info("responding to link key request\n");
|
||||||
|
connectionClearAuthenticationFlags(connection, HANDLE_LINK_KEY_REQUEST);
|
||||||
link_key_t link_key;
|
link_key_t link_key;
|
||||||
link_key_type_t link_key_type;
|
link_key_type_t link_key_type;
|
||||||
log_info("responding to link key request\n");
|
if ( hci_stack.remote_device_db
|
||||||
if ( hci_stack.bondable && hci_stack.remote_device_db && hci_stack.remote_device_db->get_link_key( &connection->address, &link_key, &link_key_type)){
|
&& hci_stack.remote_device_db->get_link_key( &connection->address, &link_key, &link_key_type)
|
||||||
|
&& gap_security_level_for_link_key_type(link_key_type) >= connection->requested_security_level){
|
||||||
connection->link_key_type = link_key_type;
|
connection->link_key_type = link_key_type;
|
||||||
hci_send_cmd(&hci_link_key_request_reply, connection->address, &link_key);
|
hci_send_cmd(&hci_link_key_request_reply, connection->address, &link_key);
|
||||||
} else {
|
} else {
|
||||||
hci_send_cmd(&hci_link_key_request_negative_reply, connection->address);
|
hci_send_cmd(&hci_link_key_request_negative_reply, connection->address);
|
||||||
}
|
}
|
||||||
connectionClearAuthenticationFlags(connection, HANDLE_LINK_KEY_REQUEST);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->authentication_flags & HANDLE_PIN_CODE_REQUEST){
|
if (connection->authentication_flags & HANDLE_PIN_CODE_REQUEST){
|
||||||
log_info("denying to pin request\n");
|
log_info("denying to pin request\n");
|
||||||
hci_send_cmd(&hci_pin_code_request_negative_reply, connection->address);
|
|
||||||
connectionClearAuthenticationFlags(connection, HANDLE_PIN_CODE_REQUEST);
|
connectionClearAuthenticationFlags(connection, HANDLE_PIN_CODE_REQUEST);
|
||||||
|
hci_send_cmd(&hci_pin_code_request_negative_reply, connection->address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->authentication_flags & SEND_IO_CAPABILITIES_REPLY){
|
if (connection->authentication_flags & SEND_IO_CAPABILITIES_REPLY){
|
||||||
|
connectionClearAuthenticationFlags(connection, SEND_IO_CAPABILITIES_REPLY);
|
||||||
if (hci_stack.bondable && hci_stack.ssp_io_capability != SSP_IO_CAPABILITY_UNKNOWN){
|
if (hci_stack.bondable && hci_stack.ssp_io_capability != SSP_IO_CAPABILITY_UNKNOWN){
|
||||||
hci_send_cmd(&hci_io_capability_request_reply, &connection->address, hci_stack.ssp_io_capability, NULL, hci_stack.ssp_authentication_requirement);
|
hci_send_cmd(&hci_io_capability_request_reply, &connection->address, hci_stack.ssp_io_capability, NULL, hci_stack.ssp_authentication_requirement);
|
||||||
} else {
|
} else {
|
||||||
hci_send_cmd(&hci_io_capability_request_negative_reply, &connection->address, ERROR_CODE_PAIRING_NOT_ALLOWED);
|
hci_send_cmd(&hci_io_capability_request_negative_reply, &connection->address, ERROR_CODE_PAIRING_NOT_ALLOWED);
|
||||||
}
|
}
|
||||||
connectionClearAuthenticationFlags(connection, SEND_IO_CAPABILITIES_REPLY);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->authentication_flags & SEND_USER_CONFIRM_REPLY){
|
if (connection->authentication_flags & SEND_USER_CONFIRM_REPLY){
|
||||||
hci_send_cmd(&hci_user_confirmation_request_reply, &connection->address);
|
|
||||||
connectionClearAuthenticationFlags(connection, SEND_USER_CONFIRM_REPLY);
|
connectionClearAuthenticationFlags(connection, SEND_USER_CONFIRM_REPLY);
|
||||||
|
hci_send_cmd(&hci_user_confirmation_request_reply, &connection->address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->authentication_flags & SEND_USER_PASSKEY_REPLY){
|
if (connection->authentication_flags & SEND_USER_PASSKEY_REPLY){
|
||||||
hci_send_cmd(&hci_user_passkey_request_reply, &connection->address, 000000);
|
|
||||||
connectionClearAuthenticationFlags(connection, SEND_USER_PASSKEY_REPLY);
|
connectionClearAuthenticationFlags(connection, SEND_USER_PASSKEY_REPLY);
|
||||||
|
hci_send_cmd(&hci_user_passkey_request_reply, &connection->address, 000000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->bonding_flags & BONDING_REQUEST_REMOTE_FEATURES){
|
if (connection->bonding_flags & BONDING_REQUEST_REMOTE_FEATURES){
|
||||||
hci_send_cmd(&hci_read_remote_supported_features_command, connection->con_handle);
|
|
||||||
connection->bonding_flags &= ~BONDING_REQUEST_REMOTE_FEATURES;
|
connection->bonding_flags &= ~BONDING_REQUEST_REMOTE_FEATURES;
|
||||||
|
hci_send_cmd(&hci_read_remote_supported_features_command, connection->con_handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->bonding_flags & BONDING_DISCONNECT_SECURITY_BLOCK){
|
if (connection->bonding_flags & BONDING_DISCONNECT_SECURITY_BLOCK){
|
||||||
hci_send_cmd(&hci_disconnect, connection->con_handle, 0x0005); // authentication failure
|
|
||||||
connection->bonding_flags &= ~BONDING_DISCONNECT_SECURITY_BLOCK;
|
connection->bonding_flags &= ~BONDING_DISCONNECT_SECURITY_BLOCK;
|
||||||
|
hci_send_cmd(&hci_disconnect, connection->con_handle, 0x0005); // authentication failure
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (connection->bonding_flags & BONDING_SEND_AUTHENTICATE_REQUEST){
|
||||||
|
connection->bonding_flags &= ~BONDING_SEND_AUTHENTICATE_REQUEST;
|
||||||
|
hci_send_cmd(&hci_authentication_requested, connection->con_handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1747,41 +1765,53 @@ void gap_set_bondable_mode(int enable){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get current security level
|
* @brief map link keys to security levels
|
||||||
*/
|
*/
|
||||||
gap_security_level_t gap_security_level(hci_con_handle_t con_handle){
|
gap_security_level_t gap_security_level_for_link_key_type(link_key_type_t link_key_type){
|
||||||
hci_connection_t * connection = hci_connection_for_handle(con_handle);
|
switch (link_key_type){
|
||||||
if (!connection) return LEVEL_0;
|
|
||||||
if ((connection->authentication_flags & CONNECTION_ENCRYPTED) == 0) return LEVEL_0;
|
|
||||||
switch (connection->link_key_type){
|
|
||||||
case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256:
|
case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256:
|
||||||
return LEVEL_4;
|
return LEVEL_4;
|
||||||
case COMBINATION_KEY:
|
case COMBINATION_KEY:
|
||||||
case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P192:
|
case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P192:
|
||||||
return LEVEL_3;
|
return LEVEL_3;
|
||||||
case DEBUG_COMBINATION_KEY:
|
|
||||||
default:
|
default:
|
||||||
return LEVEL_2;
|
return LEVEL_2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gap_security_level_t gap_security_level_for_connection(hci_connection_t * connection){
|
||||||
|
if (!connection) return LEVEL_0;
|
||||||
|
if ((connection->authentication_flags & CONNECTION_ENCRYPTED) == 0) return LEVEL_0;
|
||||||
|
return gap_security_level_for_link_key_type(connection->link_key_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get current security level
|
||||||
|
*/
|
||||||
|
gap_security_level_t gap_security_level(hci_con_handle_t con_handle){
|
||||||
|
hci_connection_t * connection = hci_connection_for_handle(con_handle);
|
||||||
|
if (!connection) return LEVEL_0;
|
||||||
|
return gap_security_level_for_connection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief request connection to device to
|
* @brief request connection to device to
|
||||||
* @result GAP_AUTHENTICATION_RESULT
|
* @result GAP_AUTHENTICATION_RESULT
|
||||||
*/
|
*/
|
||||||
void gap_request_security_level(hci_con_handle_t con_handle, gap_security_level_t level){
|
void gap_request_security_level(hci_con_handle_t con_handle, gap_security_level_t requested_level){
|
||||||
// hci_connection_t * connection = hci_connection_for_handle(con_handle);
|
hci_connection_t * connection = hci_connection_for_handle(con_handle);
|
||||||
// if (!connection){
|
if (!connection){
|
||||||
// hci_emit_security_level(con_handle, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, LEVEL_0);
|
hci_emit_security_level(con_handle, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, LEVEL_0);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// gap_security_level_t current_level = gap_security_level(con_handle);
|
gap_security_level_t current_level = gap_security_level(con_handle);
|
||||||
// if (ggap_security_level_t >= level){
|
log_info("gap_request_security_level %u, current level %u", requested_level, current_level);
|
||||||
// hci_emit_security_level(con_handle, 0, gap_security_level_t);
|
if (current_level >= requested_level){
|
||||||
// return;
|
hci_emit_security_level(con_handle, 0, current_level);
|
||||||
// }
|
return;
|
||||||
// connection->bonding_flags |=
|
}
|
||||||
|
connection->requested_security_level = requested_level;
|
||||||
// magic!
|
connection->bonding_flags |= BONDING_REQUESTED;
|
||||||
hci_emit_security_level(con_handle, 0, level);
|
connection->bonding_flags |= BONDING_SEND_AUTHENTICATE_REQUEST;
|
||||||
}
|
}
|
||||||
|
11
src/hci.h
11
src/hci.h
@ -233,10 +233,12 @@ typedef enum {
|
|||||||
} CONNECTION_STATE;
|
} CONNECTION_STATE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BONDING_REQUEST_REMOTE_FEATURES = 0x01,
|
BONDING_REQUEST_REMOTE_FEATURES = 0x01,
|
||||||
BONDING_RECEIVED_REMOTE_FEATURES = 0x02,
|
BONDING_RECEIVED_REMOTE_FEATURES = 0x02,
|
||||||
BONDING_REMOTE_SUPPORTS_SSP = 0x04,
|
BONDING_REMOTE_SUPPORTS_SSP = 0x04,
|
||||||
BONDING_DISCONNECT_SECURITY_BLOCK = 0x08,
|
BONDING_DISCONNECT_SECURITY_BLOCK = 0x08,
|
||||||
|
BONDING_REQUESTED = 0x10,
|
||||||
|
BONDING_SEND_AUTHENTICATE_REQUEST = 0x20,
|
||||||
} bonding_flags_t;
|
} bonding_flags_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -261,6 +263,9 @@ typedef struct {
|
|||||||
// bonding
|
// bonding
|
||||||
bonding_flags_t bonding_flags;
|
bonding_flags_t bonding_flags;
|
||||||
|
|
||||||
|
// requested security level
|
||||||
|
gap_security_level_t requested_security_level;
|
||||||
|
|
||||||
//
|
//
|
||||||
link_key_type_t link_key_type;
|
link_key_type_t link_key_type;
|
||||||
|
|
||||||
|
@ -496,7 +496,7 @@ void l2cap_run(void){
|
|||||||
switch (channel->state){
|
switch (channel->state){
|
||||||
|
|
||||||
case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT:
|
case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT:
|
||||||
if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND) {
|
if (channel->state_var & L2CAP_STATE_WAIT_AUTHENTICATION_RESULT) {
|
||||||
channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND);
|
channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND);
|
||||||
l2cap_send_signaling_packet(channel->handle, CONNECTION_RESPONSE, channel->remote_sig_id, 0, 0, 1, 0);
|
l2cap_send_signaling_packet(channel->handle, CONNECTION_RESPONSE, channel->remote_sig_id, 0, 0, 1, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user