if both devices support SSP, initiator shall setup unauthenticated link unless connecting to SDP

This commit is contained in:
matthias.ringwald@gmail.com 2014-01-17 16:30:31 +00:00
parent f01ad3fb0d
commit df3354fc67
5 changed files with 72 additions and 26 deletions

View File

@ -31,7 +31,7 @@ static char* service_name[10];
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); // printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET) return;
uint8_t event = packet[0]; uint8_t event = packet[0];
@ -53,7 +53,7 @@ static void btstack_setup(){
btstack_memory_init(); btstack_memory_init();
run_loop_init(RUN_LOOP_POSIX); run_loop_init(RUN_LOOP_POSIX);
hci_dump_open("/tmp/hci_dump_sdp_rfcomm_query.pklg", HCI_DUMP_PACKETLOGGER); hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
hci_transport_t * transport = hci_transport_usb_instance(); hci_transport_t * transport = hci_transport_usb_instance();
hci_uart_config_t * config = NULL; hci_uart_config_t * config = NULL;

View File

@ -1746,6 +1746,7 @@ void hci_emit_discoverable_enabled(uint8_t enabled){
} }
void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){ void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){
log_info("hci_emit_security_level %u for handle %x", level, con_handle);
uint8_t event[5]; uint8_t event[5];
int pos = 0; int pos = 0;
event[pos++] = GAP_SECURITY_LEVEL; event[pos++] = GAP_SECURITY_LEVEL;
@ -1764,6 +1765,10 @@ int hci_remote_ssp_supported(hci_con_handle_t con_handle){
return (connection->bonding_flags & BONDING_REMOTE_SUPPORTS_SSP) ? 1 : 0; return (connection->bonding_flags & BONDING_REMOTE_SUPPORTS_SSP) ? 1 : 0;
} }
int hci_ssp_supported_on_both_sides(hci_con_handle_t handle){
return hci_local_ssp_activated() && hci_remote_ssp_supported(handle);
}
// GAP API // GAP API
/** /**
* @bbrief enable/disable bonding. default is enabled * @bbrief enable/disable bonding. default is enabled

View File

@ -409,6 +409,10 @@ int hci_local_ssp_activated();
// query if the remote side supports SSP // query if the remote side supports SSP
int hci_remote_ssp_supported(hci_con_handle_t con_handle); int hci_remote_ssp_supported(hci_con_handle_t con_handle);
// query if both sides support SSP
int hci_ssp_supported_on_both_sides(hci_con_handle_t handle);
// disconnect because of security block // disconnect because of security block
void hci_disconnect_security_block(hci_con_handle_t con_handle); void hci_disconnect_security_block(hci_con_handle_t con_handle);

View File

@ -286,6 +286,10 @@ static void l2cap_start_ertx(l2cap_channel_t * channel){
run_loop_add_timer(&channel->rtx); run_loop_add_timer(&channel->rtx);
} }
static int l2cap_security_level_0_allowed_for_PSM(uint16_t psm){
// return 0; // TESTING!
return psm != PSM_SDP;
}
int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){ int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
@ -495,7 +499,7 @@ void l2cap_run(void){
switch (channel->state){ switch (channel->state){
case L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE: case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE:
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_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND) {
channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND); channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND);
@ -670,9 +674,10 @@ static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_
if ( ! BD_ADDR_CMP( channel->address, address) ){ if ( ! BD_ADDR_CMP( channel->address, address) ){
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) { if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
// success, start l2cap handshake // success, start l2cap handshake
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
channel->handle = handle; channel->handle = handle;
channel->local_cid = l2cap_next_local_cid(); channel->local_cid = l2cap_next_local_cid();
// check remote SSP feature first
channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES;
} }
} }
} }
@ -771,24 +776,55 @@ void l2cap_event_handler( uint8_t *packet, uint16_t size ){
} }
break; break;
case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
handle = READ_BT_16(packet, 3);
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_REMOTE_SUPPORTED_FEATURES) continue;
// we have been waiting for remote supported features, if both support SSP,
if (hci_ssp_supported_on_both_sides(channel->handle) && !l2cap_security_level_0_allowed_for_PSM(channel->psm)){
// request security level 2
gap_request_security_level(channel->handle, LEVEL_2);
channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE;
break;
}
// fine, go ahead
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
break;
}
case GAP_SECURITY_LEVEL: case GAP_SECURITY_LEVEL:
handle = READ_BT_16(packet, 2); handle = READ_BT_16(packet, 2);
log_info("GAP_SECURITY_LEVEL");
for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){ for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
channel = (l2cap_channel_t *) it; channel = (l2cap_channel_t *) it;
gap_security_level_t actual_level = packet[4]; gap_security_level_t actual_level = packet[4];
log_info("GAP_SECURITY_LEVEL handle %x/%x level %u, state %u", handle, channel->handle, actual_level, channel->state);
if (channel->handle != handle) continue; if (channel->handle != handle) continue;
log_info("handle ok"); switch (channel->state){
if (channel->state != L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE) continue; case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE:
log_info("state ok"); log_info("gap incoming");
if (actual_level >= channel->required_security_level){ if (actual_level >= channel->required_security_level){
log_info("level ok"); channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; l2cap_emit_connection_request(channel);
l2cap_emit_connection_request(channel); } else {
} else { channel->reason = 0x03; // security block
log_info("level nok"); channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE;
channel->reason = 0x03; // security block }
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; break;
case L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE:
log_info("gap outgoing");
if (actual_level >= channel->required_security_level){
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
} else {
// disconnnect, authentication not good enough
hci_disconnect_security_block(handle);
}
break;
default:
break;
} }
} }
break; break;
@ -837,10 +873,9 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
} }
// reject connection (0x03 security block) and disconnect if both have SSP, connection is not encrypted and PSM != SDP // reject connection (0x03 security block) and disconnect if both have SSP, connection is not encrypted and PSM != SDP
if (psm != PSM_SDP if ( l2cap_security_level_0_allowed_for_PSM(psm)
&& hci_local_ssp_activated() && hci_ssp_supported_on_both_sides(handle)
&& hci_remote_ssp_supported(handle) && gap_security_level(handle) == LEVEL_0){
&& gap_security_level(handle) == LEVEL_3){
// 0x0003 Security Block // 0x0003 Security Block
l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0003); l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0003);
@ -869,7 +904,7 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
channel->remote_mtu = L2CAP_DEFAULT_MTU; channel->remote_mtu = L2CAP_DEFAULT_MTU;
channel->packets_granted = 0; channel->packets_granted = 0;
channel->remote_sig_id = sig_id; channel->remote_sig_id = sig_id;
channel->required_security_level = LEVEL_0; // @TODO get from 'security database' channel->required_security_level = service->required_security_level;
// limit local mtu to max acl packet length // limit local mtu to max acl packet length
if (channel->local_mtu > l2cap_max_mtu()) { if (channel->local_mtu > l2cap_max_mtu()) {
@ -877,7 +912,7 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
} }
// set initial state // set initial state
channel->state = L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE; channel->state = L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE;
channel->state_var = L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND; channel->state_var = L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND;
// add to connections list // add to connections list
@ -1258,8 +1293,8 @@ void l2cap_register_service_internal(void *connection, btstack_packet_handler_t
service->mtu = mtu; service->mtu = mtu;
service->connection = connection; service->connection = connection;
service->packet_handler = packet_handler; service->packet_handler = packet_handler;
service->security_level = security_level; service->required_security_level = security_level;
// add to services list // add to services list
linked_list_add(&l2cap_services, (linked_item_t *) service); linked_list_add(&l2cap_services, (linked_item_t *) service);

View File

@ -93,7 +93,9 @@ typedef enum {
L2CAP_STATE_CLOSED = 1, // no baseband L2CAP_STATE_CLOSED = 1, // no baseband
L2CAP_STATE_WILL_SEND_CREATE_CONNECTION, L2CAP_STATE_WILL_SEND_CREATE_CONNECTION,
L2CAP_STATE_WAIT_CONNECTION_COMPLETE, L2CAP_STATE_WAIT_CONNECTION_COMPLETE,
L2CAP_STATE_WAIT_SECURITY_LEVEL_UPDATE, L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES,
L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE,
L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE,
L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT, L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT,
L2CAP_STATE_WAIT_CONNECT_RSP, // from peer L2CAP_STATE_WAIT_CONNECT_RSP, // from peer
L2CAP_STATE_CONFIG, L2CAP_STATE_CONFIG,
@ -180,7 +182,7 @@ typedef struct {
btstack_packet_handler_t packet_handler; btstack_packet_handler_t packet_handler;
// required security level // required security level
gap_security_level_t security_level; gap_security_level_t required_security_level;
} l2cap_service_t; } l2cap_service_t;