From a00031e2154472f85be4622e7cee39f9589ab933 Mon Sep 17 00:00:00 2001 From: "matthias.ringwald@gmail.com" Date: Fri, 17 Jan 2014 10:37:42 +0000 Subject: [PATCH] successfully enable encryption if security level 2 is requested for l2cap service --- include/btstack/hci_cmds.h | 6 +++--- src/hci.c | 39 ++++++++++++++++++++++++-------------- src/hci.h | 1 + src/l2cap.c | 29 +++++++++++++--------------- src/l2cap.h | 2 +- 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/include/btstack/hci_cmds.h b/include/btstack/hci_cmds.h index df47516fd..12e65bc1b 100644 --- a/include/btstack/hci_cmds.h +++ b/include/btstack/hci_cmds.h @@ -246,14 +246,14 @@ extern "C" { // GAP SECURITY - // data: event(8), len(8), status (8), hci_handle (16), security_level (8) - #define GAP_AUTHENTICATION_RESULT 0xc0 + // data: event(8), len(8), hci_handle (16), security_level (8) + #define GAP_SECURITY_LEVEL 0xc0 // Error Code #define ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 #define ERROR_CODE_PAIRING_NOT_ALLOWED 0x18 #define ERROR_CODE_INSUFFICIENT_SECURITY 0x2F - + // last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors #define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED 0x50 #define BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH 0x51 diff --git a/src/hci.c b/src/hci.c index bf7cbe6df..ee3d4f914 100644 --- a/src/hci.c +++ b/src/hci.c @@ -70,6 +70,7 @@ #endif static void hci_update_scan_enable(void); +static gap_security_level_t gap_security_level_for_connection(hci_connection_t * connection); // the STACK is here static hci_stack_t hci_stack; @@ -703,16 +704,13 @@ static void event_handler(uint8_t *packet, int size){ } else { conn->authentication_flags &= ~CONNECTION_ENCRYPTED; } + hci_emit_security_level(handle, gap_security_level_for_connection(conn)); break; // case HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT: // 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 @@ -1740,13 +1738,12 @@ void hci_emit_discoverable_enabled(uint8_t enabled){ hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); } -void hci_emit_security_level(hci_con_handle_t con_handle, uint8_t status, gap_security_level_t level){ - uint8_t event[6]; +void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){ + uint8_t event[5]; int pos = 0; - event[pos++] = GAP_AUTHENTICATION_RESULT; + event[pos++] = GAP_SECURITY_LEVEL; event[pos++] = sizeof(event) - 2; - event[pos++] = status; - bt_store_16(event, 3, con_handle); + bt_store_16(event, 2, con_handle); pos += 2; event[pos++] = level; hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); @@ -1784,7 +1781,7 @@ gap_security_level_t gap_security_level_for_link_key_type(link_key_type_t link_k } } -gap_security_level_t gap_security_level_for_connection(hci_connection_t * connection){ +static 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); @@ -1807,16 +1804,30 @@ 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 requested_level){ hci_connection_t * connection = hci_connection_for_handle(con_handle); if (!connection){ - hci_emit_security_level(con_handle, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, LEVEL_0); + hci_emit_security_level(con_handle, LEVEL_0); return; } gap_security_level_t current_level = gap_security_level(con_handle); log_info("gap_request_security_level %u, current level %u", requested_level, current_level); if (current_level >= requested_level){ - hci_emit_security_level(con_handle, 0, current_level); + hci_emit_security_level(con_handle, current_level); return; } + connection->requested_security_level = requested_level; - connection->bonding_flags |= BONDING_REQUESTED; - connection->bonding_flags |= BONDING_SEND_AUTHENTICATE_REQUEST; + + // would enabling ecnryption suffice? + if (hci_stack.remote_device_db){ + link_key_type_t link_key_type; + link_key_t link_key; + if (hci_stack.remote_device_db->get_link_key( &connection->address, &link_key, &link_key_type)){ + if (gap_security_level_for_link_key_type(link_key_type) >= requested_level){ + connection->bonding_flags |= BONDING_SEND_ENCRYPTION_REQUEST; + return; + } + } + } + + // connection->bonding_flags |= BONDING_REQUESTED; + // connection->bonding_flags |= BONDING_SEND_AUTHENTICATE_REQUEST; } diff --git a/src/hci.h b/src/hci.h index fe68fcb0e..f7e5f1858 100644 --- a/src/hci.h +++ b/src/hci.h @@ -401,6 +401,7 @@ void hci_emit_btstack_version(void); void hci_emit_system_bluetooth_enabled(uint8_t enabled); void hci_emit_remote_name_cached(bd_addr_t *addr, device_name_t *name); void hci_emit_discoverable_enabled(uint8_t enabled); +void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level); // query if remote side supports SSP // query if the local side supports SSP diff --git a/src/l2cap.c b/src/l2cap.c index b9eaa3ba9..7da64562b 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -495,10 +495,11 @@ void l2cap_run(void){ switch (channel->state){ + case L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE: case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT: - if (channel->state_var & L2CAP_STATE_WAIT_AUTHENTICATION_RESULT) { + if (channel->state_var & 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, channel->local_cid, channel->remote_cid, 1, 0); } break; @@ -770,22 +771,18 @@ void l2cap_event_handler( uint8_t *packet, uint16_t size ){ } break; - case GAP_AUTHENTICATION_RESULT: - handle = READ_BT_16(packet, 3); + case GAP_SECURITY_LEVEL: + handle = READ_BT_16(packet, 2); for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){ channel = (l2cap_channel_t *) it; if (channel->handle != handle) continue; - if (channel->state != L2CAP_STATE_WAIT_AUTHENTICATION_RESULT) continue; - if (packet[2]){ - // fail - channel->reason = 0x03; // security block - channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; - } else { - // success - // @todo check sercurity level again - channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; - l2cap_emit_connection_request(channel); - } + if (channel->state != L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE) continue; + // @todo check security level again + // channel->reason = 0x03; // security block + // channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; + // success + channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; + l2cap_emit_connection_request(channel); } break; @@ -872,7 +869,7 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig } // set initial state - channel->state = L2CAP_STATE_WAIT_AUTHENTICATION_RESULT; + channel->state = L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE; channel->state_var = L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND; // add to connections list diff --git a/src/l2cap.h b/src/l2cap.h index 6183ee8e5..44fb39b39 100644 --- a/src/l2cap.h +++ b/src/l2cap.h @@ -93,7 +93,7 @@ typedef enum { L2CAP_STATE_CLOSED = 1, // no baseband L2CAP_STATE_WILL_SEND_CREATE_CONNECTION, L2CAP_STATE_WAIT_CONNECTION_COMPLETE, - L2CAP_STATE_WAIT_AUTHENTICATION_RESULT, + L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE, L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT, L2CAP_STATE_WAIT_CONNECT_RSP, // from peer L2CAP_STATE_CONFIG,