mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-25 15:41:00 +00:00
use sm_active_connection as mutex for setup context struct
This commit is contained in:
parent
268602ef87
commit
477200f2ef
155
ble/sm.c
155
ble/sm.c
@ -99,16 +99,6 @@ typedef enum {
|
|||||||
SM_AES128_ACTIVE
|
SM_AES128_ACTIVE
|
||||||
} sm_aes128_state_t;
|
} sm_aes128_state_t;
|
||||||
|
|
||||||
typedef struct sm_pairing_packet {
|
|
||||||
uint8_t code;
|
|
||||||
uint8_t io_capability;
|
|
||||||
uint8_t oob_data_flag;
|
|
||||||
uint8_t auth_req;
|
|
||||||
uint8_t max_encryption_key_size;
|
|
||||||
uint8_t initiator_key_distribution;
|
|
||||||
uint8_t responder_key_distribution;
|
|
||||||
} sm_pairing_packet_t;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// GLOBAL DATA
|
// GLOBAL DATA
|
||||||
//
|
//
|
||||||
@ -257,6 +247,9 @@ static void sm_run();
|
|||||||
static void sm_done_for_handle(uint16_t handle);
|
static void sm_done_for_handle(uint16_t handle);
|
||||||
static void sm_notify_client(uint8_t type, uint8_t addr_type, bd_addr_t address, uint32_t passkey, uint16_t index);
|
static void sm_notify_client(uint8_t type, uint8_t addr_type, bd_addr_t address, uint32_t passkey, uint16_t index);
|
||||||
static sm_connection_t * sm_get_connection_for_handle(uint16_t handle);
|
static sm_connection_t * sm_get_connection_for_handle(uint16_t handle);
|
||||||
|
static inline int sm_calc_actual_encryption_key_size(int other);
|
||||||
|
static int sm_validate_stk_generation_method();
|
||||||
|
static void sm_responder_setup(sm_connection_t * sm_conn);
|
||||||
|
|
||||||
static void log_info_hex16(const char * name, uint16_t value){
|
static void log_info_hex16(const char * name, uint16_t value){
|
||||||
log_info("%-6s 0x%04x", name, value);
|
log_info("%-6s 0x%04x", name, value);
|
||||||
@ -768,15 +761,23 @@ static void sm_pdu_received_in_wrong_state(sm_connection_t * sm_conn){
|
|||||||
|
|
||||||
static void sm_run(void){
|
static void sm_run(void){
|
||||||
|
|
||||||
// setup locking
|
|
||||||
// - if no connection locked
|
|
||||||
|
|
||||||
// TODO: iterate over all hci_connections instead of handling the single connection
|
// TODO: iterate over all hci_connections instead of handling the single connection
|
||||||
sm_connection_t * connection = &single_connection;
|
sm_connection_t * connection = &single_connection;
|
||||||
|
|
||||||
// hack (probably) start security if requested before (setup lock recommended)
|
// setup locking
|
||||||
if (connection->sm_engine_state == SM_INITIATOR_CONNECTED && connection->sm_role == 0x00 && sm_authenticate_outgoing_connections){
|
// - if no connection locked and we're ready/waiting for setup context, fetch it and start
|
||||||
connection->sm_engine_state = SM_INITIATOR_PH1_SEND_PAIRING_REQUEST;
|
if (sm_active_connection == 0){
|
||||||
|
switch (connection->sm_engine_state) {
|
||||||
|
case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
|
||||||
|
sm_responder_setup(connection);
|
||||||
|
break;
|
||||||
|
case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
|
||||||
|
sm_active_connection = connection->sm_handle;
|
||||||
|
connection->sm_engine_state = SM_INITIATOR_PH1_SEND_PAIRING_REQUEST;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// assert that we can send at least commands
|
// assert that we can send at least commands
|
||||||
@ -925,7 +926,7 @@ static void sm_run(void){
|
|||||||
uint8_t buffer[2];
|
uint8_t buffer[2];
|
||||||
buffer[0] = SM_CODE_SECURITY_REQUEST;
|
buffer[0] = SM_CODE_SECURITY_REQUEST;
|
||||||
buffer[1] = SM_AUTHREQ_BONDING;
|
buffer[1] = SM_AUTHREQ_BONDING;
|
||||||
connection->sm_engine_state = SM_GENERAL_IDLE;
|
connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
|
||||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1449,6 +1450,54 @@ static void sm_init_setup(sm_connection_t * sm_conn){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void sm_responder_setup(sm_connection_t * sm_conn){
|
||||||
|
|
||||||
|
// start setup in responder role
|
||||||
|
sm_init_setup(sm_conn);
|
||||||
|
|
||||||
|
// recover pairing request
|
||||||
|
memcpy(&setup->sm_m_preq, &sm_conn->sm_m_preq, sizeof(sm_pairing_packet_t));
|
||||||
|
|
||||||
|
// check key size
|
||||||
|
sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(setup->sm_s_pres.max_encryption_key_size);
|
||||||
|
if (sm_conn->sm_actual_encryption_key_size == 0){
|
||||||
|
sm_done_for_handle(sm_conn->sm_handle);
|
||||||
|
setup->sm_pairing_failed_reason = SM_REASON_ENCRYPTION_KEY_SIZE;
|
||||||
|
sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup key distribution
|
||||||
|
sm_setup_key_distribution(setup->sm_m_preq.responder_key_distribution);
|
||||||
|
|
||||||
|
// start SM timeout
|
||||||
|
sm_2timeout_start(sm_conn);
|
||||||
|
|
||||||
|
// decide on STK generation method
|
||||||
|
sm_setup_tk();
|
||||||
|
log_info("SMP: generation method %u", setup->sm_stk_generation_method);
|
||||||
|
|
||||||
|
// check if STK generation method is acceptable by client
|
||||||
|
if (!sm_validate_stk_generation_method()){
|
||||||
|
sm_done_for_handle(sm_conn->sm_handle);
|
||||||
|
setup->sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS;
|
||||||
|
sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JUST WORKS doens't provide authentication
|
||||||
|
sm_conn->sm_connection_authenticated = setup->sm_stk_generation_method == JUST_WORKS ? 0 : 1;
|
||||||
|
|
||||||
|
// generate random number first, if we need to show passkey
|
||||||
|
if (setup->sm_stk_generation_method == PK_INIT_INPUT){
|
||||||
|
sm_conn->sm_engine_state = SM_PH2_GET_RANDOM_TK;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm_conn->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
|
|
||||||
sm_connection_t * sm_conn;
|
sm_connection_t * sm_conn;
|
||||||
@ -1500,10 +1549,21 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
|||||||
// just connected -> everything else happens in sm_run()
|
// just connected -> everything else happens in sm_run()
|
||||||
if (sm_conn->sm_role){
|
if (sm_conn->sm_role){
|
||||||
// slave
|
// slave
|
||||||
sm_conn->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
|
if (sm_slave_request_security){
|
||||||
|
// request security if requested by app
|
||||||
|
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
|
||||||
|
} else {
|
||||||
|
// otherwise, wait for pairing request
|
||||||
|
sm_conn->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
|
||||||
|
}
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
// master
|
// master
|
||||||
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
|
if (sm_authenticate_outgoing_connections){
|
||||||
|
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
||||||
|
} else {
|
||||||
|
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1550,7 +1610,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
|||||||
if (!sm_conn) break;
|
if (!sm_conn) break;
|
||||||
|
|
||||||
sm_conn->sm_connection_encrypted = packet[5];
|
sm_conn->sm_connection_encrypted = packet[5];
|
||||||
log_info("Eencryption state change: %u", sm_conn->sm_connection_encrypted);
|
log_info("Encryption state change: %u", sm_conn->sm_connection_encrypted);
|
||||||
if (!sm_conn->sm_connection_encrypted) break;
|
if (!sm_conn->sm_connection_encrypted) break;
|
||||||
if (sm_conn->sm_engine_state == SM_PH2_W4_CONNECTION_ENCRYPTED) {
|
if (sm_conn->sm_engine_state == SM_PH2_W4_CONNECTION_ENCRYPTED) {
|
||||||
if (sm_conn->sm_role){
|
if (sm_conn->sm_role){
|
||||||
@ -1719,63 +1779,17 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
|||||||
|
|
||||||
// Responder
|
// Responder
|
||||||
case SM_GENERAL_IDLE:
|
case SM_GENERAL_IDLE:
|
||||||
|
case SM_RESPONDER_SEND_SECURITY_REQUEST:
|
||||||
case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
|
case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
|
||||||
{
|
|
||||||
if (packet[0] != SM_CODE_PAIRING_REQUEST){
|
if (packet[0] != SM_CODE_PAIRING_REQUEST){
|
||||||
sm_pdu_received_in_wrong_state(sm_conn);
|
sm_pdu_received_in_wrong_state(sm_conn);
|
||||||
break;;
|
break;;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start setup in responder role
|
|
||||||
sm_init_setup(sm_conn);
|
|
||||||
|
|
||||||
// request security if we're slave and requested by app (setup lock recommended)
|
|
||||||
if (sm_conn->sm_role == 0x01 && sm_slave_request_security){
|
|
||||||
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store pairing request
|
// store pairing request
|
||||||
memcpy(&setup->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
|
memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
|
||||||
|
sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
|
||||||
// check key size
|
|
||||||
sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(setup->sm_s_pres.max_encryption_key_size);
|
|
||||||
if (sm_conn->sm_actual_encryption_key_size == 0){
|
|
||||||
sm_done_for_handle(sm_conn->sm_handle);
|
|
||||||
setup->sm_pairing_failed_reason = SM_REASON_ENCRYPTION_KEY_SIZE;
|
|
||||||
sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup key distribution
|
|
||||||
sm_setup_key_distribution(setup->sm_m_preq.responder_key_distribution);
|
|
||||||
|
|
||||||
// start SM timeout
|
|
||||||
sm_2timeout_start(sm_conn);
|
|
||||||
|
|
||||||
// decide on STK generation method
|
|
||||||
sm_setup_tk();
|
|
||||||
log_info("SMP: generation method %u", setup->sm_stk_generation_method);
|
|
||||||
|
|
||||||
// check if STK generation method is acceptable by client
|
|
||||||
if (!sm_validate_stk_generation_method()){
|
|
||||||
sm_done_for_handle(sm_conn->sm_handle);
|
|
||||||
setup->sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS;
|
|
||||||
sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// JUST WORKS doens't provide authentication
|
|
||||||
sm_conn->sm_connection_authenticated = setup->sm_stk_generation_method == JUST_WORKS ? 0 : 1;
|
|
||||||
|
|
||||||
// generate random number first, if we need to show passkey
|
|
||||||
if (setup->sm_stk_generation_method == PK_INIT_INPUT){
|
|
||||||
sm_conn->sm_engine_state = SM_PH2_GET_RANDOM_TK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sm_conn->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SM_RESPONDER_PH1_W4_PAIRING_CONFIRM:
|
case SM_RESPONDER_PH1_W4_PAIRING_CONFIRM:
|
||||||
if (packet[0] != SM_CODE_PAIRING_CONFIRM){
|
if (packet[0] != SM_CODE_PAIRING_CONFIRM){
|
||||||
@ -1931,6 +1945,7 @@ void sm_test_set_irk(sm_key_t irk){
|
|||||||
*/
|
*/
|
||||||
void sm_send_security_request(uint16_t handle){
|
void sm_send_security_request(uint16_t handle){
|
||||||
sm_connection_t * sm_conn = sm_get_connection_for_handle(handle);
|
sm_connection_t * sm_conn = sm_get_connection_for_handle(handle);
|
||||||
|
if (sm_conn->sm_engine_state != SM_RESPONDER_PH1_W4_PAIRING_REQUEST) return;
|
||||||
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
|
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
|
||||||
sm_run();
|
sm_run();
|
||||||
}
|
}
|
||||||
@ -2016,7 +2031,7 @@ void sm_request_authorization(uint8_t addr_type, bd_addr_t address){
|
|||||||
|
|
||||||
// used as a trigger to start central/master/initiator security procedures
|
// used as a trigger to start central/master/initiator security procedures
|
||||||
if (sm_conn->sm_engine_state == SM_INITIATOR_CONNECTED){
|
if (sm_conn->sm_engine_state == SM_INITIATOR_CONNECTED){
|
||||||
sm_conn->sm_engine_state = SM_INITIATOR_PH1_SEND_PAIRING_REQUEST;
|
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
src/hci.h
39
src/hci.h
@ -411,6 +411,7 @@ typedef enum {
|
|||||||
SM_RESPONDER_SEND_SECURITY_REQUEST,
|
SM_RESPONDER_SEND_SECURITY_REQUEST,
|
||||||
SM_RESPONDER_SEND_LTK_REQUESTED_NEGATIVE_REPLY,
|
SM_RESPONDER_SEND_LTK_REQUESTED_NEGATIVE_REPLY,
|
||||||
SM_RESPONDER_PH1_W4_PAIRING_REQUEST,
|
SM_RESPONDER_PH1_W4_PAIRING_REQUEST,
|
||||||
|
SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED,
|
||||||
SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE,
|
SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE,
|
||||||
SM_RESPONDER_PH1_W4_PAIRING_CONFIRM,
|
SM_RESPONDER_PH1_W4_PAIRING_CONFIRM,
|
||||||
SM_RESPONDER_PH2_W4_PAIRING_RANDOM,
|
SM_RESPONDER_PH2_W4_PAIRING_RANDOM,
|
||||||
@ -419,6 +420,7 @@ typedef enum {
|
|||||||
|
|
||||||
// INITITIATOR ROLE
|
// INITITIATOR ROLE
|
||||||
SM_INITIATOR_CONNECTED,
|
SM_INITIATOR_CONNECTED,
|
||||||
|
SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST,
|
||||||
SM_INITIATOR_PH1_SEND_PAIRING_REQUEST,
|
SM_INITIATOR_PH1_SEND_PAIRING_REQUEST,
|
||||||
SM_INITIATOR_PH1_W4_PAIRING_RESPONSE,
|
SM_INITIATOR_PH1_W4_PAIRING_RESPONSE,
|
||||||
SM_INITIATOR_PH2_W4_PAIRING_CONFIRM,
|
SM_INITIATOR_PH2_W4_PAIRING_CONFIRM,
|
||||||
@ -442,19 +444,30 @@ typedef enum {
|
|||||||
AUTHORIZATION_GRANTED
|
AUTHORIZATION_GRANTED
|
||||||
} authorization_state_t;
|
} authorization_state_t;
|
||||||
|
|
||||||
|
typedef struct sm_pairing_packet {
|
||||||
|
uint8_t code;
|
||||||
|
uint8_t io_capability;
|
||||||
|
uint8_t oob_data_flag;
|
||||||
|
uint8_t auth_req;
|
||||||
|
uint8_t max_encryption_key_size;
|
||||||
|
uint8_t initiator_key_distribution;
|
||||||
|
uint8_t responder_key_distribution;
|
||||||
|
} sm_pairing_packet_t;
|
||||||
|
|
||||||
// connection info available as long as connection exists
|
// connection info available as long as connection exists
|
||||||
typedef struct sm_connection {
|
typedef struct sm_connection {
|
||||||
uint16_t sm_handle;
|
uint16_t sm_handle;
|
||||||
uint8_t sm_role; // 0 - IamMaster, 1 = IamSlave
|
uint8_t sm_role; // 0 - IamMaster, 1 = IamSlave
|
||||||
bd_addr_t sm_peer_address;
|
bd_addr_t sm_peer_address;
|
||||||
uint8_t sm_peer_addr_type;
|
uint8_t sm_peer_addr_type;
|
||||||
security_manager_state_t sm_engine_state;
|
security_manager_state_t sm_engine_state;
|
||||||
csrk_lookup_state_t sm_csrk_lookup_state;
|
csrk_lookup_state_t sm_csrk_lookup_state;
|
||||||
uint8_t sm_connection_encrypted;
|
uint8_t sm_connection_encrypted;
|
||||||
uint8_t sm_connection_authenticated; // [0..1]
|
uint8_t sm_connection_authenticated; // [0..1]
|
||||||
uint8_t sm_actual_encryption_key_size;
|
uint8_t sm_actual_encryption_key_size;
|
||||||
authorization_state_t sm_connection_authorization_state;
|
sm_pairing_packet_t sm_m_preq; // only used during c1
|
||||||
timer_source_t sm_timeout;
|
authorization_state_t sm_connection_authorization_state;
|
||||||
|
timer_source_t sm_timeout;
|
||||||
} sm_connection_t;
|
} sm_connection_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -500,11 +513,11 @@ typedef struct {
|
|||||||
uint16_t acl_recombination_pos;
|
uint16_t acl_recombination_pos;
|
||||||
uint16_t acl_recombination_length;
|
uint16_t acl_recombination_length;
|
||||||
|
|
||||||
// number ACL packets sent to controller
|
// number packets sent to controller
|
||||||
uint8_t num_acl_packets_sent;
|
uint8_t num_acl_packets_sent;
|
||||||
uint8_t num_sco_packets_sent;
|
uint8_t num_sco_packets_sent;
|
||||||
|
|
||||||
// connection parameter update
|
// LE Connection parameter update
|
||||||
le_con_parameter_update_state_t le_con_parameter_update_state;
|
le_con_parameter_update_state_t le_con_parameter_update_state;
|
||||||
uint16_t le_conn_interval_min;
|
uint16_t le_conn_interval_min;
|
||||||
uint16_t le_conn_interval_max;
|
uint16_t le_conn_interval_max;
|
||||||
@ -512,8 +525,10 @@ typedef struct {
|
|||||||
uint16_t le_supervision_timeout;
|
uint16_t le_supervision_timeout;
|
||||||
uint16_t le_update_con_parameter_response;
|
uint16_t le_update_con_parameter_response;
|
||||||
|
|
||||||
|
#ifdef HAVE_BLE
|
||||||
// LE Security Manager
|
// LE Security Manager
|
||||||
// sm_connection_t sm_connection;
|
sm_connection_t sm_connection;
|
||||||
|
#endif
|
||||||
|
|
||||||
} hci_connection_t;
|
} hci_connection_t;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user