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_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
|
||||
//
|
||||
@ -257,6 +247,9 @@ static void sm_run();
|
||||
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 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){
|
||||
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){
|
||||
|
||||
// setup locking
|
||||
// - if no connection locked
|
||||
|
||||
// TODO: iterate over all hci_connections instead of handling the single connection
|
||||
sm_connection_t * connection = &single_connection;
|
||||
|
||||
// hack (probably) start security if requested before (setup lock recommended)
|
||||
if (connection->sm_engine_state == SM_INITIATOR_CONNECTED && connection->sm_role == 0x00 && sm_authenticate_outgoing_connections){
|
||||
connection->sm_engine_state = SM_INITIATOR_PH1_SEND_PAIRING_REQUEST;
|
||||
// setup locking
|
||||
// - if no connection locked and we're ready/waiting for setup context, fetch it and start
|
||||
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
|
||||
@ -925,7 +926,7 @@ static void sm_run(void){
|
||||
uint8_t buffer[2];
|
||||
buffer[0] = SM_CODE_SECURITY_REQUEST;
|
||||
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));
|
||||
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){
|
||||
|
||||
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()
|
||||
if (sm_conn->sm_role){
|
||||
// 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 {
|
||||
// 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;
|
||||
|
||||
@ -1550,7 +1610,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
if (!sm_conn) break;
|
||||
|
||||
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_engine_state == SM_PH2_W4_CONNECTION_ENCRYPTED) {
|
||||
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
|
||||
case SM_GENERAL_IDLE:
|
||||
case SM_RESPONDER_SEND_SECURITY_REQUEST:
|
||||
case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
|
||||
{
|
||||
if (packet[0] != SM_CODE_PAIRING_REQUEST){
|
||||
sm_pdu_received_in_wrong_state(sm_conn);
|
||||
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
|
||||
memcpy(&setup->sm_m_preq, packet, 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;
|
||||
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;
|
||||
memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
|
||||
sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
|
||||
break;
|
||||
}
|
||||
|
||||
case SM_RESPONDER_PH1_W4_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){
|
||||
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_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
|
||||
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_LTK_REQUESTED_NEGATIVE_REPLY,
|
||||
SM_RESPONDER_PH1_W4_PAIRING_REQUEST,
|
||||
SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED,
|
||||
SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE,
|
||||
SM_RESPONDER_PH1_W4_PAIRING_CONFIRM,
|
||||
SM_RESPONDER_PH2_W4_PAIRING_RANDOM,
|
||||
@ -419,6 +420,7 @@ typedef enum {
|
||||
|
||||
// INITITIATOR ROLE
|
||||
SM_INITIATOR_CONNECTED,
|
||||
SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST,
|
||||
SM_INITIATOR_PH1_SEND_PAIRING_REQUEST,
|
||||
SM_INITIATOR_PH1_W4_PAIRING_RESPONSE,
|
||||
SM_INITIATOR_PH2_W4_PAIRING_CONFIRM,
|
||||
@ -442,19 +444,30 @@ typedef enum {
|
||||
AUTHORIZATION_GRANTED
|
||||
} 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
|
||||
typedef struct sm_connection {
|
||||
uint16_t sm_handle;
|
||||
uint8_t sm_role; // 0 - IamMaster, 1 = IamSlave
|
||||
bd_addr_t sm_peer_address;
|
||||
uint8_t sm_peer_addr_type;
|
||||
uint16_t sm_handle;
|
||||
uint8_t sm_role; // 0 - IamMaster, 1 = IamSlave
|
||||
bd_addr_t sm_peer_address;
|
||||
uint8_t sm_peer_addr_type;
|
||||
security_manager_state_t sm_engine_state;
|
||||
csrk_lookup_state_t sm_csrk_lookup_state;
|
||||
uint8_t sm_connection_encrypted;
|
||||
uint8_t sm_connection_authenticated; // [0..1]
|
||||
uint8_t sm_actual_encryption_key_size;
|
||||
authorization_state_t sm_connection_authorization_state;
|
||||
timer_source_t sm_timeout;
|
||||
uint8_t sm_connection_encrypted;
|
||||
uint8_t sm_connection_authenticated; // [0..1]
|
||||
uint8_t sm_actual_encryption_key_size;
|
||||
sm_pairing_packet_t sm_m_preq; // only used during c1
|
||||
authorization_state_t sm_connection_authorization_state;
|
||||
timer_source_t sm_timeout;
|
||||
} sm_connection_t;
|
||||
|
||||
typedef struct {
|
||||
@ -500,11 +513,11 @@ typedef struct {
|
||||
uint16_t acl_recombination_pos;
|
||||
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_sco_packets_sent;
|
||||
|
||||
// connection parameter update
|
||||
// LE Connection parameter update
|
||||
le_con_parameter_update_state_t le_con_parameter_update_state;
|
||||
uint16_t le_conn_interval_min;
|
||||
uint16_t le_conn_interval_max;
|
||||
@ -512,8 +525,10 @@ typedef struct {
|
||||
uint16_t le_supervision_timeout;
|
||||
uint16_t le_update_con_parameter_response;
|
||||
|
||||
#ifdef HAVE_BLE
|
||||
// LE Security Manager
|
||||
// sm_connection_t sm_connection;
|
||||
sm_connection_t sm_connection;
|
||||
#endif
|
||||
|
||||
} hci_connection_t;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user