Skip to content

Commit ba64040

Browse files
committed
l2cap: trigger pairing for outgoing LE Data Channels if security level insufficient
1 parent 66b2f71 commit ba64040

1 file changed

Lines changed: 59 additions & 10 deletions

File tree

src/l2cap.c

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@
3939

4040
/*
4141
* l2cap.c
42-
*
43-
* Logical Link Control and Adaption Protocl (L2CAP)
44-
*
45-
* Created by Matthias Ringwald on 5/16/09.
42+
* Logical Link Control and Adaption Protocol (L2CAP)
4643
*/
4744

4845
#include "l2cap.h"
@@ -55,6 +52,11 @@
5552
#include "btstack_event.h"
5653
#include "btstack_memory.h"
5754

55+
#ifdef ENABLE_LE_DATA_CHANNELS
56+
// TODO avoid dependency on higher layer: used to trigger pairing for outgoing connections
57+
#include "ble/sm.h"
58+
#endif
59+
5860
#include <stdarg.h>
5961
#include <string.h>
6062

@@ -3970,12 +3972,44 @@ uint8_t l2cap_le_decline_connection(uint16_t local_cid){
39703972
return ERROR_CODE_SUCCESS;
39713973
}
39723974

3973-
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle,
3975+
// used to handle pairing complete after triggering to increase
3976+
static void l2cap_sm_packet_handler(uint8_t packet_type, uint16_t channel_nr, uint8_t *packet, uint16_t size) {
3977+
UNUSED(channel_nr);
3978+
UNUSED(size);
3979+
btstack_assert(packet_type = HCI_EVENT_PACKET);
3980+
if (hci_event_packet_get_type(packet) != SM_EVENT_PAIRING_COMPLETE) return;
3981+
hci_con_handle_t con_handle = sm_event_pairing_complete_get_handle(packet);
3982+
btstack_linked_list_iterator_t it;
3983+
btstack_linked_list_iterator_init(&it, &l2cap_channels);
3984+
while (btstack_linked_list_iterator_has_next(&it)) {
3985+
l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
3986+
if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue;
3987+
if (channel->con_handle != con_handle) continue;
3988+
if (channel->state != L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE) continue;
3989+
3990+
// found channel, check security level
3991+
if (gap_security_level(con_handle) < channel->required_security_level){
3992+
// pairing failed or wasn't good enough, inform user
3993+
l2cap_emit_le_channel_opened(channel, ERROR_CODE_INSUFFICIENT_SECURITY);
3994+
// discard channel
3995+
btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel);
3996+
l2cap_free_channel_entry(channel);
3997+
} else {
3998+
// send conn request now
3999+
channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST;
4000+
l2cap_run();
4001+
}
4002+
}
4003+
}
4004+
4005+
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle,
39744006
uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level,
39754007
uint16_t * out_local_cid) {
39764008

3977-
log_info("L2CAP_LE_CREATE_CHANNEL handle 0x%04x psm 0x%x mtu %u", con_handle, psm, mtu);
4009+
static btstack_packet_callback_registration_t sm_event_callback_registration;
4010+
static bool sm_callback_registered = false;
39784011

4012+
log_info("L2CAP_LE_CREATE_CHANNEL handle 0x%04x psm 0x%x mtu %u", con_handle, psm, mtu);
39794013

39804014
hci_connection_t * connection = hci_connection_for_handle(con_handle);
39814015
if (!connection) {
@@ -3994,18 +4028,33 @@ uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con
39944028
*out_local_cid = channel->local_cid;
39954029
}
39964030

3997-
// provide buffer
4031+
// setup channel entry
39984032
channel->con_handle = con_handle;
39994033
channel->receive_sdu_buffer = receive_sdu_buffer;
4000-
channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST;
40014034
channel->new_credits_incoming = initial_credits;
40024035
channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS;
40034036

40044037
// add to connections list
40054038
btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel);
40064039

4007-
// go
4008-
l2cap_run();
4040+
// check security level
4041+
if (gap_security_level(con_handle) < channel->required_security_level){
4042+
if (!sm_callback_registered){
4043+
sm_callback_registered = true;
4044+
// lazy registration for SM events
4045+
sm_event_callback_registration.callback = &l2cap_sm_packet_handler;
4046+
sm_add_event_handler(&sm_event_callback_registration);
4047+
}
4048+
4049+
// start pairing
4050+
channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE;
4051+
sm_request_pairing(con_handle);
4052+
} else {
4053+
// send conn request right away
4054+
channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST;
4055+
l2cap_run();
4056+
}
4057+
40094058
return ERROR_CODE_SUCCESS;
40104059
}
40114060

0 commit comments

Comments
 (0)