diff --git a/src/ble/sm.c b/src/ble/sm.c index 9c32ce188..fea337770 100644 --- a/src/ble/sm.c +++ b/src/ble/sm.c @@ -179,6 +179,7 @@ static uint8_t sm_auth_req = 0; static uint8_t sm_io_capabilities = IO_CAPABILITY_NO_INPUT_NO_OUTPUT; static uint8_t sm_slave_request_security; static uint32_t sm_fixed_legacy_pairing_passkey_in_display_role; +static uint8_t sm_reconstruct_ltk_without_le_device_db_entry; #ifdef ENABLE_LE_SECURE_CONNECTIONS static uint8_t sm_have_ec_keypair; #endif @@ -1260,8 +1261,14 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event) sm_connection->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED; sm_connection->sm_le_db_index = matched_device_id; log_info("ADDRESS_RESOLUTION_SUCEEDED, index %d", sm_connection->sm_le_db_index); + if (sm_connection->sm_role) { + // LTK request received before, IRK required -> start LTK calculation + if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){ + sm_connection->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST; + } + break; + } #ifdef ENABLE_LE_CENTRAL - if (sm_connection->sm_role) break; if (!sm_connection->sm_bonding_requested && !sm_connection->sm_security_request_received) break; sm_connection->sm_security_request_received = 0; sm_connection->sm_bonding_requested = 0; @@ -1275,8 +1282,14 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event) break; case ADDRESS_RESOLUTION_FAILED: sm_connection->sm_irk_lookup_state = IRK_LOOKUP_FAILED; + if (sm_connection->sm_role) { + // LTK request received before, IRK required -> negative LTK reply + if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){ + sm_connection->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY; + } + break; + } #ifdef ENABLE_LE_CENTRAL - if (sm_connection->sm_role) break; if (!sm_connection->sm_bonding_requested && !sm_connection->sm_security_request_received) break; sm_connection->sm_security_request_received = 0; sm_connection->sm_bonding_requested = 0; @@ -3100,7 +3113,24 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint // For Legacy Pairing (<=> EDIV != 0 || RAND != NULL), we need to recalculated our LTK as a // potentially stored LTK is from the master if (sm_conn->sm_local_ediv != 0 || !sm_is_null_random(sm_conn->sm_local_rand)){ - sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST; + if (sm_reconstruct_ltk_without_le_device_db_entry){ + sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST; + break; + } + // additionally check if remote is in LE Device DB if requested + switch(sm_conn->sm_irk_lookup_state){ + case IRK_LOOKUP_FAILED: + log_info("LTK Request: device not in device db"); + sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY; + break; + case IRK_LOOKUP_SUCCEEDED: + sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST; + break; + default: + // wait for irk look doen + sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK; + break; + } break; } @@ -3792,7 +3822,8 @@ void sm_init(void){ sm_min_encryption_key_size = 7; sm_fixed_legacy_pairing_passkey_in_display_role = 0xffffffff; - + sm_reconstruct_ltk_without_le_device_db_entry = 1; + #ifdef ENABLE_CMAC_ENGINE sm_cmac_state = CMAC_IDLE; #endif @@ -3862,6 +3893,10 @@ void sm_use_fixed_legacy_pairing_passkey_in_display_role(uint32_t passkey){ sm_fixed_legacy_pairing_passkey_in_display_role = passkey; } +void sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow){ + sm_reconstruct_ltk_without_le_device_db_entry = allow; +} + static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle){ hci_connection_t * hci_con = hci_connection_for_handle(con_handle); if (!hci_con) return NULL; diff --git a/src/ble/sm.h b/src/ble/sm.h index 24e040f72..a4447b512 100644 --- a/src/ble/sm.h +++ b/src/ble/sm.h @@ -298,6 +298,16 @@ void sm_use_fixed_ec_keypair(uint8_t * qx, uint8_t * qy, uint8_t * d); */ void sm_use_fixed_legacy_pairing_passkey_in_display_role(uint32_t passkey); +/** + * @brief Allow connection re-encryption in Peripheral (Responder) role for LE Legacy Pairing + * without entry for Central device stored in LE Device DB + * @note BTstack in Peripheral Role (Responder) supports LE Legacy Pairing without a persistent LE Device DB as + * the LTK is reconstructed from a local secret IRK and EDIV + Random stored on Central (Initiator) device + * On the downside, it's not really possible to delete a pairing if this is enabled. + * @param allow encryption using reconstructed LTK without stored entry (Default: 1) + */ +void sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow); + /* API_END */ // PTS testing diff --git a/src/hci.h b/src/hci.h index eb3bbe455..6bbc04b6e 100644 --- a/src/hci.h +++ b/src/hci.h @@ -303,6 +303,7 @@ typedef enum { SM_RESPONDER_IDLE, SM_RESPONDER_SEND_SECURITY_REQUEST, SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST, + SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK, SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY, SM_RESPONDER_PH1_W4_PAIRING_REQUEST, SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED,