mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-05 00:40:19 +00:00
started work on initiator side, pairing request/response are exchanged
This commit is contained in:
parent
ab288af094
commit
70e9b98021
116
ble/sm.c
116
ble/sm.c
@ -121,8 +121,12 @@ typedef enum {
|
|||||||
SM_STATE_TIMEOUT, // no other security messages are exchanged
|
SM_STATE_TIMEOUT, // no other security messages are exchanged
|
||||||
|
|
||||||
// MASTR ROLE
|
// MASTR ROLE
|
||||||
SM_STATE_CONNECTED_AS_INITIATOR,
|
SM_STATE_INITIATOR_CONNECTED,
|
||||||
SM_STATE_SEND_PAIRING_REQUEST,
|
SM_STATE_INITIATOR_SEND_PAIRING_REQUEST,
|
||||||
|
SM_STATE_INITIATOR_W4_PAIRING_RESPONSE,
|
||||||
|
SM_STATE_INITIATOR_PH1_SEND_PAIRING_CONFIRM,
|
||||||
|
SM_STATE_INITIATOR_PH2_GET_RANDOM_TK,
|
||||||
|
SM_STATE_INITIATOR_PH2_W4_RANDOM_TK,
|
||||||
|
|
||||||
} security_manager_state_t;
|
} security_manager_state_t;
|
||||||
|
|
||||||
@ -202,6 +206,7 @@ static uint8_t sm_min_encryption_key_size;
|
|||||||
static uint8_t sm_auth_req = 0;
|
static uint8_t sm_auth_req = 0;
|
||||||
static uint8_t sm_io_capabilities = IO_CAPABILITY_UNKNOWN;
|
static uint8_t sm_io_capabilities = IO_CAPABILITY_UNKNOWN;
|
||||||
static uint8_t sm_slave_request_security;
|
static uint8_t sm_slave_request_security;
|
||||||
|
static uint8_t sm_authenticate_outgoing_connections = 0; // might go away
|
||||||
static stk_generation_method_t sm_stk_generation_method;
|
static stk_generation_method_t sm_stk_generation_method;
|
||||||
|
|
||||||
// Security Manager Master Keys, please use sm_set_er(er) and sm_set_ir(ir) with your own 128 bit random values
|
// Security Manager Master Keys, please use sm_set_er(er) and sm_set_ir(ir) with your own 128 bit random values
|
||||||
@ -918,6 +923,16 @@ static void sm_run(void){
|
|||||||
// responding state
|
// responding state
|
||||||
switch (connection->sm_state_responding){
|
switch (connection->sm_state_responding){
|
||||||
|
|
||||||
|
// initiator side
|
||||||
|
case SM_STATE_INITIATOR_SEND_PAIRING_REQUEST:
|
||||||
|
setup->sm_m_preq.code = SM_CODE_PAIRING_REQUEST;
|
||||||
|
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
|
||||||
|
sm_2timeout_reset();
|
||||||
|
connection->sm_state_responding = SM_STATE_INITIATOR_W4_PAIRING_RESPONSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// responder side
|
||||||
|
|
||||||
case SM_STATE_SEND_SECURITY_REQUEST: {
|
case SM_STATE_SEND_SECURITY_REQUEST: {
|
||||||
uint8_t buffer[2];
|
uint8_t buffer[2];
|
||||||
buffer[0] = SM_CODE_SECURITY_REQUEST;
|
buffer[0] = SM_CODE_SECURITY_REQUEST;
|
||||||
@ -1391,6 +1406,8 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
|||||||
switch (packet[2]) {
|
switch (packet[2]) {
|
||||||
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
||||||
|
|
||||||
|
printf("sm: connected\n");
|
||||||
|
|
||||||
if (packet[3]) return; // connection failed
|
if (packet[3]) return; // connection failed
|
||||||
|
|
||||||
// only single connection for peripheral
|
// only single connection for peripheral
|
||||||
@ -1439,7 +1456,9 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
|||||||
setup->sm_m_preq.oob_data_flag = have_oob_data;
|
setup->sm_m_preq.oob_data_flag = have_oob_data;
|
||||||
setup->sm_m_preq.auth_req = sm_auth_req;
|
setup->sm_m_preq.auth_req = sm_auth_req;
|
||||||
setup->sm_m_preq.max_encryption_key_size = sm_max_encryption_key_size;
|
setup->sm_m_preq.max_encryption_key_size = sm_max_encryption_key_size;
|
||||||
connection->sm_state_responding = SM_STATE_CONNECTED_AS_INITIATOR;
|
setup->sm_m_preq.initiator_key_distribution = 0x07;
|
||||||
|
setup->sm_m_preq.responder_key_distribution = 0x07;
|
||||||
|
connection->sm_state_responding = SM_STATE_INITIATOR_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// request security if we're slave and requested by app
|
// request security if we're slave and requested by app
|
||||||
@ -1447,6 +1466,11 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
|||||||
connection->sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST;
|
connection->sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hack (probablu) start security if requested before
|
||||||
|
if (connection->sm_role == 0x00 && sm_authenticate_outgoing_connections){
|
||||||
|
connection->sm_state_responding = SM_STATE_INITIATOR_SEND_PAIRING_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
// prepare CSRK lookup
|
// prepare CSRK lookup
|
||||||
connection->sm_csrk_lookup_state = CSRK_LOOKUP_W4_READY;
|
connection->sm_csrk_lookup_state = CSRK_LOOKUP_W4_READY;
|
||||||
if (!sm_central_device_lookup_active()){
|
if (!sm_central_device_lookup_active()){
|
||||||
@ -1549,6 +1573,77 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
|||||||
case SM_STATE_TIMEOUT:
|
case SM_STATE_TIMEOUT:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Initiator
|
||||||
|
case SM_STATE_INITIATOR_W4_PAIRING_RESPONSE:
|
||||||
|
if (packet[0] != SM_CODE_PAIRING_RESPONSE){
|
||||||
|
sm_pdu_received_in_wrong_state();
|
||||||
|
break;;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store pairing request
|
||||||
|
memcpy(&setup->sm_s_pres, packet, sizeof(sm_pairing_packet_t));
|
||||||
|
|
||||||
|
// identical to responder, just other encryption size field
|
||||||
|
|
||||||
|
// assert max encryption size above our minimum
|
||||||
|
if (setup->sm_s_pres.max_encryption_key_size < sm_min_encryption_key_size){
|
||||||
|
setup->sm_pairing_failed_reason = SM_REASON_ENCRYPTION_KEY_SIZE;
|
||||||
|
connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// min{}
|
||||||
|
connection->sm_actual_encryption_key_size = sm_max_encryption_key_size;
|
||||||
|
if (setup->sm_s_pres.max_encryption_key_size < sm_max_encryption_key_size){
|
||||||
|
connection->sm_actual_encryption_key_size = setup->sm_s_pres.max_encryption_key_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup key distribution
|
||||||
|
sm_setup_key_distribution(setup->sm_s_pres.initiator_key_distribution);
|
||||||
|
|
||||||
|
// identical to responder
|
||||||
|
|
||||||
|
// start SM timeout
|
||||||
|
sm_2timeout_start();
|
||||||
|
|
||||||
|
// decide on STK generation method
|
||||||
|
sm_setup_tk();
|
||||||
|
printf("SMP: generation method %u\n", sm_stk_generation_method);
|
||||||
|
|
||||||
|
// check if STK generation method is acceptable by client
|
||||||
|
int ok = 0;
|
||||||
|
switch (sm_stk_generation_method){
|
||||||
|
case JUST_WORKS:
|
||||||
|
ok = (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_JUST_WORKS) != 0;
|
||||||
|
break;
|
||||||
|
case PK_RESP_INPUT:
|
||||||
|
case PK_INIT_INPUT:
|
||||||
|
case OK_BOTH_INPUT:
|
||||||
|
ok = (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_PASSKEY) != 0;
|
||||||
|
break;
|
||||||
|
case OOB:
|
||||||
|
ok = (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_OOB) != 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ok){
|
||||||
|
setup->sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS;
|
||||||
|
connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JUST WORKS doens't provide authentication
|
||||||
|
connection->sm_connection_authenticated = sm_stk_generation_method == JUST_WORKS ? 0 : 1;
|
||||||
|
|
||||||
|
// generate random number first, if we need to show passkey
|
||||||
|
if (sm_stk_generation_method == PK_RESP_INPUT){
|
||||||
|
connection->sm_state_responding = SM_STATE_INITIATOR_PH2_GET_RANDOM_TK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->sm_state_responding = SM_STATE_INITIATOR_PH1_SEND_PAIRING_CONFIRM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Responder
|
||||||
case SM_STATE_IDLE:
|
case SM_STATE_IDLE:
|
||||||
case SM_STATE_W4_PAIRING_REQUEST:
|
case SM_STATE_W4_PAIRING_REQUEST:
|
||||||
{
|
{
|
||||||
@ -1557,7 +1652,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
|
|||||||
break;;
|
break;;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store key distribtion request
|
// store pairing request
|
||||||
memcpy(&setup->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
|
memcpy(&setup->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
|
||||||
|
|
||||||
// assert max encryption size above our minimum
|
// assert max encryption size above our minimum
|
||||||
@ -1827,8 +1922,21 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres
|
|||||||
|
|
||||||
// request authorization
|
// request authorization
|
||||||
void sm_request_authorization(uint8_t addr_type, bd_addr_t address){
|
void sm_request_authorization(uint8_t addr_type, bd_addr_t address){
|
||||||
|
printf("sm_request_authorization in role %u, state %u\n", connection->sm_role, connection->sm_state_responding);
|
||||||
|
if (connection->sm_role){
|
||||||
|
// code has no effect so far
|
||||||
connection->sm_connection_authorization_state = AUTHORIZATION_PENDING;
|
connection->sm_connection_authorization_state = AUTHORIZATION_PENDING;
|
||||||
sm_notify_client(SM_AUTHORIZATION_REQUEST, setup->sm_m_addr_type, setup->sm_m_address, 0, 0);
|
sm_notify_client(SM_AUTHORIZATION_REQUEST, setup->sm_m_addr_type, setup->sm_m_address, 0, 0);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// HACK
|
||||||
|
sm_authenticate_outgoing_connections = 1;
|
||||||
|
|
||||||
|
// used as a trigger to start central/master/initiator security procedures
|
||||||
|
if (connection->sm_state_responding == SM_STATE_INITIATOR_CONNECTED){
|
||||||
|
connection->sm_state_responding = SM_STATE_INITIATOR_SEND_PAIRING_REQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// called by client app on authorization request
|
// called by client app on authorization request
|
||||||
|
Loading…
x
Reference in New Issue
Block a user