diff --git a/ble/sm.c b/ble/sm.c index eeebe9a7d..57df87d1c 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -218,15 +218,14 @@ static void (*sm_cmac_done_handler)(uint8_t hash[8]); static uint8_t sm_s_addr_type; static bd_addr_t sm_s_address; -// resolvable private address lookup: single instance, should be serialized +// resolvable private address lookup: single instance static int sm_central_device_test; static int sm_central_device_matched; static int sm_central_ah_calculation_active; static uint8_t sm_central_device_addr_type; static bd_addr_t sm_central_device_address; -// data to send to aes128 crypto engine, see sm_aes128_set_key and sm_aes128_set_plaintext -static sm_key_t sm_aes128_plaintext; +// state of aes128 crypto engine static sm_aes128_state_t sm_aes128_state; // @@ -238,56 +237,57 @@ static sm_aes128_state_t sm_aes128_state; // PER INSTANCE DATA -// used during sm setup -static sm_key_t sm_tk; -static uint8_t sm_pairing_failed_reason = 0; +typedef struct sm_setup_context { + // used during sm setup + sm_key_t sm_tk; + sm_key_t sm_aes128_plaintext; + uint8_t sm_pairing_failed_reason; -// defines which keys will be send after connection is encrypted -static int sm_key_distribution_send_set; -static int sm_key_distribution_received_set; + // defines which keys will be send after connection is encrypted + int sm_key_distribution_send_set; + int sm_key_distribution_received_set; -static csrk_lookup_state_t sm_m_csrk_lookup_state; + // user response + uint8_t sm_user_response; -// user response -static uint8_t sm_user_response; + uint8_t sm_m_io_capabilities; + uint8_t sm_m_have_oob_data; + uint8_t sm_m_auth_req; + uint8_t sm_m_max_encryption_key_size; + uint8_t sm_m_key_distribution; + uint8_t sm_m_preq[7]; + sm_key_t sm_m_random; + sm_key_t sm_m_confirm; -static uint8_t sm_m_io_capabilities; -static uint8_t sm_m_have_oob_data; -static uint8_t sm_m_auth_req; -static uint8_t sm_m_max_encryption_key_size; -static uint8_t sm_m_key_distribution; -static uint8_t sm_m_preq[7]; -static sm_key_t sm_m_random; -static sm_key_t sm_m_confirm; + sm_key_t sm_s_random; + uint8_t sm_s_have_oob_data; + sm_key_t sm_s_confirm; + uint8_t sm_s_pres[7]; -static sm_key_t sm_s_random; -static uint8_t sm_s_have_oob_data; -static sm_key_t sm_s_confirm; -static uint8_t sm_s_pres[7]; - -// key distribution, slave sends -static sm_key_t sm_s_ltk; -static uint16_t sm_s_y; -static uint16_t sm_s_div; -static uint16_t sm_s_ediv; -static uint8_t sm_s_rand[8]; -// commented keys are not used in Perihperal role -// static sm_key_t sm_s_csrk; - -// key distribution, received from master -// commented keys that are not stored or used by Peripheral role -// static sm_key_t sm_m_ltk; -// static uint16_t sm_m_ediv; -// static uint8_t sm_m_rand[8]; -static uint8_t sm_m_addr_type; -static bd_addr_t sm_m_address; -static sm_key_t sm_m_csrk; -static sm_key_t sm_m_irk; + // key distribution, slave sends + sm_key_t sm_s_ltk; + uint16_t sm_s_y; + uint16_t sm_s_div; + uint16_t sm_s_ediv; + uint8_t sm_s_rand[8]; + // commented keys are not used in Perihperal role + // sm_key_t sm_s_csrk; + // key distribution, received from master + // commented keys that are not stored or used by Peripheral role + // sm_key_t sm_m_ltk; + // uint16_t sm_m_ediv; + // uint8_t sm_m_rand[8]; + uint8_t sm_m_addr_type; + bd_addr_t sm_m_address; + sm_key_t sm_m_csrk; + sm_key_t sm_m_irk; +} sm_setup_context_t; // connection info available as long as connection exists typedef struct sm_connection { security_manager_state_t sm_state_responding; + csrk_lookup_state_t sm_m_csrk_lookup_state; uint8_t sm_connection_encrypted; uint8_t sm_connection_authenticated; // [0..1] uint8_t sm_actual_encryption_key_size; @@ -297,6 +297,10 @@ typedef struct sm_connection { timer_source_t sm_timeout; } sm_connection_t; +// +static sm_setup_context the_setup; +static sm_setup_context * setup = &the_setup; +// static sm_connection_t single_connection; static sm_connection_t * connection = &single_connection; @@ -337,7 +341,7 @@ static int sm_is_null_random(uint8_t random[8]){ static void sm_reset_tk(){ int i; for (i=0;i<16;i++){ - sm_tk[i] = 0; + setup->sm_tk[i] = 0; } } @@ -527,24 +531,24 @@ static void sm_notify_client_authorization(uint8_t type, uint8_t addr_type, bd_a // - pairing request // - io capabilities // - OOB data availability -static void sm_tk_setup(){ +static void sm_setup_tk(){ // default: just works sm_stk_generation_method = JUST_WORKS; sm_reset_tk(); // query client for OOB data - sm_s_have_oob_data = 0; + setup->sm_s_have_oob_data = 0; if (sm_get_oob_data) { - (*sm_get_oob_data)(sm_m_addr_type, &sm_m_address, sm_tk); + (*sm_get_oob_data)(setup->sm_m_addr_type, &setup->sm_m_address, setup->sm_tk); } // If both devices have out of band authentication data, then the Authentication // Requirements Flags shall be ignored when selecting the pairing method and the // Out of Band pairing method shall be used. - if (sm_m_have_oob_data && sm_s_have_oob_data){ + if (setup->sm_m_have_oob_data && setup->sm_s_have_oob_data){ printf("SM: have OOB data"); - print_key("OOB", sm_tk); + print_key("OOB", setup->sm_tk); sm_stk_generation_method = OOB; return; } @@ -552,20 +556,20 @@ static void sm_tk_setup(){ // If both devices have not set the MITM option in the Authentication Requirements // Flags, then the IO capabilities shall be ignored and the Just Works association // model shall be used. - if ( ((sm_m_auth_req & SM_AUTHREQ_MITM_PROTECTION) == 0x00) && ((sm_s_auth_req & SM_AUTHREQ_MITM_PROTECTION) == 0)){ + if ( ((setup->sm_m_auth_req & SM_AUTHREQ_MITM_PROTECTION) == 0x00) && ((sm_s_auth_req & SM_AUTHREQ_MITM_PROTECTION) == 0)){ return; } // Also use just works if unknown io capabilites - if ((sm_m_io_capabilities > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_m_io_capabilities > IO_CAPABILITY_KEYBOARD_DISPLAY)){ + if ((setup->sm_m_io_capabilities > IO_CAPABILITY_KEYBOARD_DISPLAY) || (setup->sm_m_io_capabilities > IO_CAPABILITY_KEYBOARD_DISPLAY)){ return; } // Otherwise the IO capabilities of the devices shall be used to determine the // pairing method as defined in Table 2.4. - sm_stk_generation_method = stk_generation_method[sm_s_io_capabilities][sm_m_io_capabilities]; - printf("sm_tk_setup: master io cap: %u, slave io cap: %u -> method %u\n", - sm_m_io_capabilities, sm_s_io_capabilities, sm_stk_generation_method); + sm_stk_generation_method = stk_generation_method[sm_s_io_capabilities][setup->sm_m_io_capabilities]; + printf("sm_setup_tk: master io cap: %u, slave io cap: %u -> method %u\n", + setup->sm_m_io_capabilities, sm_s_io_capabilities, sm_stk_generation_method); } static int sm_key_distribution_flags_for_set(uint8_t key_set){ @@ -589,8 +593,8 @@ static void sm_setup_key_distribution(uint8_t key_set){ // TODO: handle initiator case here // distribute keys as requested by initiator - sm_key_distribution_received_set = 0; - sm_key_distribution_send_set = sm_key_distribution_flags_for_set(key_set); + setup->sm_key_distribution_received_set = 0; + setup->sm_key_distribution_send_set = sm_key_distribution_flags_for_set(key_set); } // CSRK Key Lookup @@ -609,7 +613,7 @@ static void sm_central_device_start_lookup(uint8_t addr_type, bd_addr_t addr){ // TODO use relevant connection structure static void sm_central_device_lookup_found(sm_key_t csrk){ - memcpy(sm_m_csrk, csrk, 16); + memcpy(setup->sm_m_csrk, csrk, 16); } // CMAC Implementation using AES128 engine @@ -769,13 +773,13 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){ } static int sm_key_distribution_done(){ - if (sm_key_distribution_send_set) return 0; - int recv_flags = sm_key_distribution_flags_for_set(sm_m_key_distribution); - return recv_flags == sm_key_distribution_received_set; + if (setup->sm_key_distribution_send_set) return 0; + int recv_flags = sm_key_distribution_flags_for_set(setup->sm_m_key_distribution); + return recv_flags == setup->sm_key_distribution_received_set; } static void sm_pdu_received_in_wrong_state(){ - sm_pairing_failed_reason = SM_REASON_UNSPECIFIED_REASON; + setup->sm_pairing_failed_reason = SM_REASON_UNSPECIFIED_REASON; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; } @@ -789,9 +793,9 @@ static void sm_run(void){ sm_key_t plaintext; // CSRK lookup - if (sm_m_csrk_lookup_state == CSRK_LOOKUP_W4_READY && !sm_central_device_lookup_active()){ - sm_central_device_start_lookup(sm_m_addr_type, sm_m_address); - sm_m_csrk_lookup_state = CSRK_LOOKUP_STARTED; + if (connection->sm_m_csrk_lookup_state == CSRK_LOOKUP_W4_READY && !sm_central_device_lookup_active()){ + sm_central_device_start_lookup(setup->sm_m_addr_type, setup->sm_m_address); + connection->sm_m_csrk_lookup_state = CSRK_LOOKUP_STARTED; } // distributed key generation @@ -867,7 +871,7 @@ static void sm_run(void){ break; } - if (sm_m_addr_type == 0){ + if (setup->sm_m_addr_type == 0){ sm_central_device_test++; continue; } @@ -920,14 +924,14 @@ static void sm_run(void){ uint8_t buffer[7]; - memcpy(buffer, sm_m_preq, 7); + memcpy(buffer, setup->sm_m_preq, 7); buffer[0] = SM_CODE_PAIRING_RESPONSE; buffer[1] = sm_s_io_capabilities; - buffer[2] = sm_s_have_oob_data; + buffer[2] = setup->sm_s_have_oob_data; buffer[3] = sm_s_auth_req; buffer[4] = sm_max_encryption_key_size; - memcpy(sm_s_pres, buffer, 7); + memcpy(setup->sm_s_pres, buffer, 7); // for validate @@ -935,21 +939,21 @@ static void sm_run(void){ sm_2timeout_reset(); // notify client for: JUST WORKS confirm, PASSKEY display or input - sm_user_response = SM_USER_RESPONSE_IDLE; + setup->sm_user_response = SM_USER_RESPONSE_IDLE; switch (sm_stk_generation_method){ case PK_RESP_INPUT: - sm_user_response = SM_USER_RESPONSE_PENDING; - sm_notify_client(SM_PASSKEY_INPUT_NUMBER, sm_m_addr_type, sm_m_address, 0, 0); + setup->sm_user_response = SM_USER_RESPONSE_PENDING; + sm_notify_client(SM_PASSKEY_INPUT_NUMBER, setup->sm_m_addr_type, setup->sm_m_address, 0, 0); break; case PK_INIT_INPUT: - sm_notify_client(SM_PASSKEY_DISPLAY_NUMBER, sm_m_addr_type, sm_m_address, READ_NET_32(sm_tk, 12), 0); + sm_notify_client(SM_PASSKEY_DISPLAY_NUMBER, setup->sm_m_addr_type, setup->sm_m_address, READ_NET_32(setup->sm_tk, 12), 0); break; case JUST_WORKS: switch (sm_s_io_capabilities){ case IO_CAPABILITY_KEYBOARD_DISPLAY: case IO_CAPABILITY_DISPLAY_YES_NO: - sm_user_response = SM_USER_RESPONSE_PENDING; - sm_notify_client(SM_JUST_WORKS_REQUEST, sm_m_addr_type, sm_m_address, READ_NET_32(sm_tk, 12), 0); + setup->sm_user_response = SM_USER_RESPONSE_PENDING; + sm_notify_client(SM_JUST_WORKS_REQUEST, setup->sm_m_addr_type, setup->sm_m_address, READ_NET_32(setup->sm_tk, 12), 0); break; default: // cannot ask user @@ -973,7 +977,7 @@ static void sm_run(void){ case SM_STATE_SEND_PAIRING_FAILED: { uint8_t buffer[2]; buffer[0] = SM_CODE_PAIRING_FAILED; - buffer[1] = sm_pairing_failed_reason; + buffer[1] = setup->sm_pairing_failed_reason; l2cap_send_connectionless(connection->sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); sm_2timeout_stop(); connection->sm_state_responding = SM_STATE_IDLE; @@ -983,7 +987,7 @@ static void sm_run(void){ case SM_STATE_SEND_PAIRING_RANDOM: { uint8_t buffer[17]; buffer[0] = SM_CODE_PAIRING_RANDOM; - swap128(sm_s_random, &buffer[1]); + swap128(setup->sm_s_random, &buffer[1]); l2cap_send_connectionless(connection->sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); sm_2timeout_reset(); connection->sm_state_responding = SM_STATE_PH2_W4_LTK_REQUEST; @@ -1003,7 +1007,7 @@ static void sm_run(void){ case SM_STATE_PH2_C1_GET_ENC_D: // already busy? if (sm_aes128_state == SM_AES128_ACTIVE) break; - sm_aes128_start(sm_tk, sm_aes128_plaintext); + sm_aes128_start(setup->sm_tk, setup->sm_aes128_plaintext); sm_next_responding_state(); return; @@ -1011,7 +1015,7 @@ static void sm_run(void){ case SM_STATE_PH4_LTK_GET_ENC: // already busy? if (sm_aes128_state == SM_AES128_ACTIVE) break; - sm_aes128_start(sm_persistent_er, sm_aes128_plaintext); + sm_aes128_start(sm_persistent_er, setup->sm_aes128_plaintext); sm_next_responding_state(); return; @@ -1019,24 +1023,24 @@ static void sm_run(void){ // already busy? if (sm_aes128_state == SM_AES128_ACTIVE) break; // calculate m_confirm using aes128 engine - step 1 - sm_c1_t1(sm_m_random, sm_m_preq, sm_s_pres, sm_m_addr_type, sm_s_addr_type, plaintext); - sm_aes128_start(sm_tk, plaintext); + sm_c1_t1(setup->sm_m_random, setup->sm_m_preq, setup->sm_s_pres, setup->sm_m_addr_type, sm_s_addr_type, plaintext); + sm_aes128_start(setup->sm_tk, plaintext); sm_next_responding_state(); break; case SM_STATE_PH2_C1_GET_ENC_A: // already busy? if (sm_aes128_state == SM_AES128_ACTIVE) break; // calculate s_confirm using aes128 engine - step 1 - sm_c1_t1(sm_s_random, sm_m_preq, sm_s_pres, sm_m_addr_type, sm_s_addr_type, plaintext); - sm_aes128_start(sm_tk, plaintext); + sm_c1_t1(setup->sm_s_random, setup->sm_m_preq, setup->sm_s_pres, setup->sm_m_addr_type, sm_s_addr_type, plaintext); + sm_aes128_start(setup->sm_tk, plaintext); sm_next_responding_state(); break; case SM_STATE_PH2_CALC_STK: // already busy? if (sm_aes128_state == SM_AES128_ACTIVE) break; // calculate STK - sm_s1_r_prime(sm_s_random, sm_m_random, plaintext); - sm_aes128_start(sm_tk, plaintext); + sm_s1_r_prime(setup->sm_s_random, setup->sm_m_random, plaintext); + sm_aes128_start(setup->sm_tk, plaintext); sm_next_responding_state(); break; case SM_STATE_PH3_Y_GET_ENC: @@ -1044,14 +1048,14 @@ static void sm_run(void){ if (sm_aes128_state == SM_AES128_ACTIVE) break; // PH3B2 - calculate Y from - enc // Y = dm(DHK, Rand) - sm_dm_r_prime(sm_s_rand, plaintext); + sm_dm_r_prime(setup->sm_s_rand, plaintext); sm_aes128_start(sm_persistent_dhk, plaintext); sm_next_responding_state(); return; case SM_STATE_PH2_C1_SEND_PAIRING_CONFIRM: { uint8_t buffer[17]; buffer[0] = SM_CODE_PAIRING_CONFIRM; - swap128(sm_s_confirm, &buffer[1]); + swap128(setup->sm_s_confirm, &buffer[1]); l2cap_send_connectionless(connection->sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); sm_2timeout_reset(); connection->sm_state_responding = SM_STATE_PH2_W4_PAIRING_RANDOM; @@ -1059,14 +1063,14 @@ static void sm_run(void){ } case SM_STATE_PH2_SEND_STK: { sm_key_t stk_flipped; - swap128(sm_s_ltk, stk_flipped); + swap128(setup->sm_s_ltk, stk_flipped); hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_response_handle, stk_flipped); connection->sm_state_responding = SM_STATE_PH2_W4_CONNECTION_ENCRYPTED; return; } case SM_STATE_PH4_SEND_LTK: { sm_key_t ltk_flipped; - swap128(sm_s_ltk, ltk_flipped); + swap128(setup->sm_s_ltk, ltk_flipped); hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_response_handle, ltk_flipped); connection->sm_state_responding = SM_STATE_IDLE; return; @@ -1074,35 +1078,35 @@ static void sm_run(void){ case SM_STATE_PH4_Y_GET_ENC: // already busy? if (sm_aes128_state == SM_AES128_ACTIVE) break; - log_info("LTK Request: recalculating with ediv 0x%04x", sm_s_ediv); + log_info("LTK Request: recalculating with ediv 0x%04x", setup->sm_s_ediv); // Y = dm(DHK, Rand) - sm_dm_r_prime(sm_s_rand, plaintext); + sm_dm_r_prime(setup->sm_s_rand, plaintext); sm_aes128_start(sm_persistent_dhk, plaintext); sm_next_responding_state(); return; case SM_STATE_DISTRIBUTE_KEYS: - if (sm_key_distribution_send_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION){ - sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION; + if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION){ + setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION; uint8_t buffer[17]; buffer[0] = SM_CODE_ENCRYPTION_INFORMATION; - swap128(sm_s_ltk, &buffer[1]); + swap128(setup->sm_s_ltk, &buffer[1]); l2cap_send_connectionless(connection->sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); sm_2timeout_reset(); return; } - if (sm_key_distribution_send_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION){ - sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_MASTER_IDENTIFICATION; + if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION){ + setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_MASTER_IDENTIFICATION; uint8_t buffer[11]; buffer[0] = SM_CODE_MASTER_IDENTIFICATION; - bt_store_16(buffer, 1, sm_s_ediv); - swap64(sm_s_rand, &buffer[3]); + bt_store_16(buffer, 1, setup->sm_s_ediv); + swap64(setup->sm_s_rand, &buffer[3]); l2cap_send_connectionless(connection->sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); sm_2timeout_reset(); return; } - if (sm_key_distribution_send_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION){ - sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_INFORMATION; + if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION){ + setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_INFORMATION; uint8_t buffer[17]; buffer[0] = SM_CODE_IDENTITY_INFORMATION; swap128(sm_persistent_irk, &buffer[1]); @@ -1110,8 +1114,8 @@ static void sm_run(void){ sm_2timeout_reset(); return; } - if (sm_key_distribution_send_set & SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION){ - sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION; + if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION){ + setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION; uint8_t buffer[8]; buffer[0] = SM_CODE_IDENTITY_ADDRESS_INFORMATION; buffer[1] = sm_s_addr_type; @@ -1120,8 +1124,8 @@ static void sm_run(void){ sm_2timeout_reset(); return; } - if (sm_key_distribution_send_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ - sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION; + if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ + setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION; uint8_t buffer[17]; buffer[0] = SM_CODE_SIGNING_INFORMATION; // swap128(sm_s_csrk, &buffer[1]); @@ -1143,7 +1147,7 @@ static void sm_run(void){ } } -// note: aes engine is ready as we just got the aes result, also, sm_aes128_plaintext and sm_aes128_key can be set again +// note: aes engine is ready as we just got the aes result, also, setup->sm_aes128_plaintext and sm_aes128_key can be set again static void sm_handle_encryption_result(uint8_t * data){ sm_aes128_state = SM_AES128_IDLE; @@ -1219,14 +1223,14 @@ static void sm_handle_encryption_result(uint8_t * data){ { sm_key_t t2; swap128(data, t2); - sm_c1_t3(t2, sm_m_address, sm_s_address, sm_aes128_plaintext); + sm_c1_t3(t2, setup->sm_m_address, sm_s_address, setup->sm_aes128_plaintext); sm_aes128_state = SM_AES128_PLAINTEXT_SET; } sm_next_responding_state(); return; case SM_STATE_PH2_C1_W4_ENC_B: - swap128(data, sm_s_confirm); - print_key("c1!", sm_s_confirm); + swap128(data, setup->sm_s_confirm); + print_key("c1!", setup->sm_s_confirm); sm_next_responding_state(); return; case SM_STATE_PH2_C1_W4_ENC_D: @@ -1234,32 +1238,32 @@ static void sm_handle_encryption_result(uint8_t * data){ sm_key_t m_confirm_test; swap128(data, m_confirm_test); print_key("c1!", m_confirm_test); - if (memcmp(sm_m_confirm, m_confirm_test, 16) == 0){ + if (memcmp(setup->sm_m_confirm, m_confirm_test, 16) == 0){ // send s_random connection->sm_state_responding = SM_STATE_SEND_PAIRING_RANDOM; return; } - sm_pairing_failed_reason = SM_REASON_CONFIRM_VALUE_FAILED; + setup->sm_pairing_failed_reason = SM_REASON_CONFIRM_VALUE_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; } return; case SM_STATE_PH2_W4_STK: - swap128(data, sm_s_ltk); - sm_truncate_key(sm_s_ltk, connection->sm_actual_encryption_key_size); - print_key("stk", sm_s_ltk); + swap128(data, setup->sm_s_ltk); + sm_truncate_key(setup->sm_s_ltk, connection->sm_actual_encryption_key_size); + print_key("stk", setup->sm_s_ltk); connection->sm_state_responding = SM_STATE_PH2_SEND_STK; return; case SM_STATE_PH3_Y_W4_ENC:{ sm_key_t y128; swap128(data, y128); - sm_s_y = READ_NET_16(y128, 14); - print_hex16("y", sm_s_y); + setup->sm_s_y = READ_NET_16(y128, 14); + print_hex16("y", setup->sm_s_y); // PH3B3 - calculate EDIV - sm_s_ediv = sm_s_y ^ sm_s_div; - print_hex16("ediv", sm_s_ediv); + setup->sm_s_ediv = setup->sm_s_y ^ setup->sm_s_div; + print_hex16("ediv", setup->sm_s_ediv); // PH3B4 - calculate LTK - enc // LTK = d1(ER, DIV, 0)) - sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext); + sm_d1_d_prime(setup->sm_s_div, 0, setup->sm_aes128_plaintext); sm_aes128_state = SM_AES128_PLAINTEXT_SET; connection->sm_state_responding = SM_STATE_PH3_LTK_GET_ENC; return; @@ -1267,28 +1271,28 @@ static void sm_handle_encryption_result(uint8_t * data){ case SM_STATE_PH4_Y_W4_ENC:{ sm_key_t y128; swap128(data, y128); - sm_s_y = READ_NET_16(y128, 14); - print_hex16("y", sm_s_y); + setup->sm_s_y = READ_NET_16(y128, 14); + print_hex16("y", setup->sm_s_y); // PH3B3 - calculate DIV - sm_s_div = sm_s_y ^ sm_s_ediv; - print_hex16("ediv", sm_s_ediv); + setup->sm_s_div = setup->sm_s_y ^ setup->sm_s_ediv; + print_hex16("ediv", setup->sm_s_ediv); // PH3B4 - calculate LTK - enc // LTK = d1(ER, DIV, 0)) - sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext); + sm_d1_d_prime(setup->sm_s_div, 0, setup->sm_aes128_plaintext); sm_aes128_state = SM_AES128_PLAINTEXT_SET; connection->sm_state_responding = SM_STATE_PH4_LTK_GET_ENC; return; } case SM_STATE_PH3_LTK_W4_ENC: - swap128(data, sm_s_ltk); - print_key("ltk", sm_s_ltk); + swap128(data, setup->sm_s_ltk); + print_key("ltk", setup->sm_s_ltk); // distribute keys connection->sm_state_responding = SM_STATE_DISTRIBUTE_KEYS; return; case SM_STATE_PH4_LTK_W4_ENC: - swap128(data, sm_s_ltk); - sm_truncate_key(sm_s_ltk, connection->sm_actual_encryption_key_size); - print_key("ltk", sm_s_ltk); + swap128(data, setup->sm_s_ltk); + sm_truncate_key(setup->sm_s_ltk, connection->sm_actual_encryption_key_size); + print_key("ltk", setup->sm_s_ltk); connection->sm_state_responding = SM_STATE_PH4_SEND_LTK; return; default: @@ -1334,31 +1338,31 @@ static void sm_handle_random_result(uint8_t * data){ tk = tk - 999999; } sm_reset_tk(); - net_store_32(sm_tk, 12, tk); + net_store_32(setup->sm_tk, 12, tk); // continue with phase 1 connection->sm_state_responding = SM_STATE_PH1_SEND_PAIRING_RESPONSE; return; } case SM_STATE_PH2_C1_W4_RANDOM_A: - memcpy(&sm_s_random[0], data, 8); // random endinaness + memcpy(&setup->sm_s_random[0], data, 8); // random endinaness connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_B; return; case SM_STATE_PH2_C1_W4_RANDOM_B: - memcpy(&sm_s_random[8], data, 8); // random endinaness + memcpy(&setup->sm_s_random[8], data, 8); // random endinaness connection->sm_state_responding = SM_STATE_PH2_C1_GET_ENC_A; return; case SM_STATE_PH3_W4_RANDOM: - swap64(data, sm_s_rand); - // no db for encryption size hack: encryption size is stored in lowest nibble of sm_s_rand - sm_s_rand[7] = (sm_s_rand[7] & 0xf0) + (connection->sm_actual_encryption_key_size - 1); + swap64(data, setup->sm_s_rand); + // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_s_rand + setup->sm_s_rand[7] = (setup->sm_s_rand[7] & 0xf0) + (connection->sm_actual_encryption_key_size - 1); // no db for authenticated flag hack: store flag in bit 4 of LSB - sm_s_rand[7] = (sm_s_rand[7] & 0xef) + (connection->sm_connection_authenticated << 4); + setup->sm_s_rand[7] = (setup->sm_s_rand[7] & 0xef) + (connection->sm_connection_authenticated << 4); connection->sm_state_responding = SM_STATE_PH3_GET_DIV; return; case SM_STATE_PH3_W4_DIV: // use 16 bit from random value as div - sm_s_div = READ_NET_16(data, 0); - print_hex16("div", sm_s_div); + setup->sm_s_div = READ_NET_16(data, 0); + print_hex16("div", setup->sm_s_div); connection->sm_state_responding = SM_STATE_PH3_Y_GET_ENC; return; default: @@ -1399,8 +1403,8 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint } connection->sm_response_handle = READ_BT_16(packet, 4); - sm_m_addr_type = packet[7]; - bt_flip_addr(sm_m_address, &packet[8]); + setup->sm_m_addr_type = packet[7]; + bt_flip_addr(setup->sm_m_address, &packet[8]); sm_reset_tk(); @@ -1417,12 +1421,12 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint connection->sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST; } - sm_m_csrk_lookup_state = CSRK_LOOKUP_W4_READY; + connection->sm_m_csrk_lookup_state = CSRK_LOOKUP_W4_READY; if (!sm_central_device_lookup_active()){ // try to lookup device - sm_central_device_start_lookup(sm_m_addr_type, sm_m_address); - sm_m_csrk_lookup_state = CSRK_LOOKUP_STARTED; + sm_central_device_start_lookup(setup->sm_m_addr_type, setup->sm_m_address); + connection->sm_m_csrk_lookup_state = CSRK_LOOKUP_STARTED; } break; @@ -1434,22 +1438,22 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint } // re-establish previously used LTK using Rand and EDIV - swap64(&packet[5], sm_s_rand); - sm_s_ediv = READ_BT_16(packet, 13); + swap64(&packet[5], setup->sm_s_rand); + setup->sm_s_ediv = READ_BT_16(packet, 13); // assume that we don't have a LTK for ediv == 0 and random == null - if (sm_s_ediv == 0 && sm_is_null_random(sm_s_rand)){ + if (setup->sm_s_ediv == 0 && sm_is_null_random(setup->sm_s_rand)){ printf("LTK Request: ediv & random are empty\n"); connection->sm_state_responding = SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY; break; } // re-establish used key encryption size - // no db for encryption size hack: encryption size is stored in lowest nibble of sm_s_rand - connection->sm_actual_encryption_key_size = (sm_s_rand[7] & 0x0f) + 1; + // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_s_rand + connection->sm_actual_encryption_key_size = (setup->sm_s_rand[7] & 0x0f) + 1; // no db for authenticated flag hack: flag is stored in bit 4 of LSB - connection->sm_connection_authenticated = (sm_s_rand[7] & 0x10) >> 4; + connection->sm_connection_authenticated = (setup->sm_s_rand[7] & 0x10) >> 4; connection->sm_state_responding = SM_STATE_PH4_Y_GET_ENC; break; @@ -1526,36 +1530,36 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac } // store key distribtion request - sm_m_io_capabilities = packet[1]; - sm_m_have_oob_data = packet[2]; - sm_m_auth_req = packet[3]; - sm_m_max_encryption_key_size = packet[4]; + setup->sm_m_io_capabilities = packet[1]; + setup->sm_m_have_oob_data = packet[2]; + setup->sm_m_auth_req = packet[3]; + setup->sm_m_max_encryption_key_size = packet[4]; // assert max encryption size above our minimum - if (sm_m_max_encryption_key_size < sm_min_encryption_key_size){ - sm_pairing_failed_reason = SM_REASON_ENCRYPTION_KEY_SIZE; + if (setup->sm_m_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 (sm_m_max_encryption_key_size < sm_max_encryption_key_size){ - connection->sm_actual_encryption_key_size = sm_m_max_encryption_key_size; + if (setup->sm_m_max_encryption_key_size < sm_max_encryption_key_size){ + connection->sm_actual_encryption_key_size = setup->sm_m_max_encryption_key_size; } // setup key distribution - sm_m_key_distribution = packet[5]; + setup->sm_m_key_distribution = packet[5]; sm_setup_key_distribution(packet[6]); // for validate - memcpy(sm_m_preq, packet, 7); + memcpy(setup->sm_m_preq, packet, 7); // start SM timeout sm_2timeout_start(); // decide on STK generation method - sm_tk_setup(); + sm_setup_tk(); printf("SMP: generation method %u\n", sm_stk_generation_method); // check if STK generation method is acceptable by client @@ -1574,7 +1578,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac break; } if (!ok){ - sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS; + setup->sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; break; } @@ -1599,22 +1603,22 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac } // received confirm value - swap128(&packet[1], sm_m_confirm); + swap128(&packet[1], setup->sm_m_confirm); // notify client to hide shown passkey if (sm_stk_generation_method == PK_INIT_INPUT){ - sm_notify_client(SM_PASSKEY_DISPLAY_CANCEL, sm_m_addr_type, sm_m_address, 0, 0); + sm_notify_client(SM_PASSKEY_DISPLAY_CANCEL, setup->sm_m_addr_type, setup->sm_m_address, 0, 0); } // handle user cancel pairing? - if (sm_user_response == SM_USER_RESPONSE_DECLINE){ - sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED; + if (setup->sm_user_response == SM_USER_RESPONSE_DECLINE){ + setup->sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; break; } // wait for user action? - if (sm_user_response == SM_USER_RESPONSE_PENDING){ + if (setup->sm_user_response == SM_USER_RESPONSE_PENDING){ connection->sm_state_responding = SM_STATE_PH1_W4_USER_RESPONSE; break; } @@ -1630,43 +1634,43 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac } // received random value - swap128(&packet[1], sm_m_random); + swap128(&packet[1], setup->sm_m_random); connection->sm_state_responding = SM_STATE_PH2_C1_GET_ENC_C; break; case SM_STATE_DISTRIBUTE_KEYS: switch(packet[0]){ case SM_CODE_ENCRYPTION_INFORMATION: - sm_key_distribution_received_set |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION; + setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION; // swap128(&packet[1], sm_m_ltk); break; case SM_CODE_MASTER_IDENTIFICATION: - sm_key_distribution_received_set |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION; + setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION; // sm_m_ediv = READ_BT_16(packet, 1); // swap64(&packet[3], sm_m_rand); break; case SM_CODE_IDENTITY_INFORMATION: - sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION; - swap128(&packet[1], sm_m_irk); + setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION; + swap128(&packet[1], setup->sm_m_irk); break; case SM_CODE_IDENTITY_ADDRESS_INFORMATION: - sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION; + setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION; // note: we don't update addr_type and address as higher layer would get confused // note: if needed, we could use a different variable pair - // sm_m_addr_type = packet[1]; - // BD_ADDR_COPY(sm_m_address, &packet[2]); + // setup->sm_m_addr_type = packet[1]; + // BD_ADDR_COPY(setup->sm_m_address, &packet[2]); break; case SM_CODE_SIGNING_INFORMATION: - sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION; - swap128(&packet[1], sm_m_csrk); + setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION; + swap128(&packet[1], setup->sm_m_csrk); // store, if: it's a public address, or, we got an IRK - if (sm_m_addr_type == 0 || (sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION)) { - sm_central_device_matched = central_device_db_add(sm_m_addr_type, sm_m_address, sm_m_irk, sm_m_csrk); + if (setup->sm_m_addr_type == 0 || (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION)) { + sm_central_device_matched = central_device_db_add(setup->sm_m_addr_type, setup->sm_m_address, setup->sm_m_irk, setup->sm_m_csrk); break; } break; @@ -1803,30 +1807,30 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres // request authorization void sm_request_authorization(uint8_t addr_type, bd_addr_t address){ connection->sm_connection_authorization_state = AUTHORIZATION_PENDING; - sm_notify_client(SM_AUTHORIZATION_REQUEST, sm_m_addr_type, sm_m_address, 0, 0); + sm_notify_client(SM_AUTHORIZATION_REQUEST, setup->sm_m_addr_type, setup->sm_m_address, 0, 0); } // called by client app on authorization request void sm_authorization_decline(uint8_t addr_type, bd_addr_t address){ if (!sm_get_connection(addr_type, address)) return; // wrong connection connection->sm_connection_authorization_state = AUTHORIZATION_DECLINED; - sm_notify_client_authorization(SM_AUTHORIZATION_RESULT, sm_m_addr_type, sm_m_address, 0); + sm_notify_client_authorization(SM_AUTHORIZATION_RESULT, setup->sm_m_addr_type, setup->sm_m_address, 0); } void sm_authorization_grant(uint8_t addr_type, bd_addr_t address){ if (!sm_get_connection(addr_type, address)) return; // wrong connection connection->sm_connection_authorization_state = AUTHORIZATION_GRANTED; - sm_notify_client_authorization(SM_AUTHORIZATION_RESULT, sm_m_addr_type, sm_m_address, 1); + sm_notify_client_authorization(SM_AUTHORIZATION_RESULT, setup->sm_m_addr_type, setup->sm_m_address, 1); } // GAP Bonding API void sm_bonding_decline(uint8_t addr_type, bd_addr_t address){ if (!sm_get_connection(addr_type, address)) return; // wrong connection - sm_user_response = SM_USER_RESPONSE_DECLINE; + setup->sm_user_response = SM_USER_RESPONSE_DECLINE; if (connection->sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){ - sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED; + setup->sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; } sm_run(); @@ -1834,7 +1838,7 @@ void sm_bonding_decline(uint8_t addr_type, bd_addr_t address){ void sm_just_works_confirm(uint8_t addr_type, bd_addr_t address){ if (!sm_get_connection(addr_type, address)) return; // wrong connection - sm_user_response = SM_USER_RESPONSE_CONFIRM; + setup->sm_user_response = SM_USER_RESPONSE_CONFIRM; if (connection->sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){ connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A; } @@ -1844,8 +1848,8 @@ void sm_just_works_confirm(uint8_t addr_type, bd_addr_t address){ void sm_passkey_input(uint8_t addr_type, bd_addr_t address, uint32_t passkey){ if (!sm_get_connection(addr_type, address)) return; // wrong connection sm_reset_tk(); - net_store_32(sm_tk, 12, passkey); - sm_user_response = SM_USER_RESPONSE_PASSKEY; + net_store_32(setup->sm_tk, 12, passkey); + setup->sm_user_response = SM_USER_RESPONSE_PASSKEY; if (connection->sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){ connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A; }