introduce temp sm_connection_t struct and put sm_state_responding into it

This commit is contained in:
matthias.ringwald 2014-06-12 19:50:09 +00:00
parent ad0e8d7cb3
commit 642083fd9a

169
ble/sm.c
View File

@ -286,15 +286,20 @@ static sm_key_t sm_m_irk;
// connection info available as long as connection exists // connection info available as long as connection exists
static security_manager_state_t sm_state_responding = SM_STATE_IDLE;
static uint8_t sm_connection_encrypted;
static uint8_t sm_connection_authenticated; // [0..1]
static uint8_t sm_actual_encryption_key_size;
static uint8_t sm_s_request_security = 0;
static authorization_state_t sm_connection_authorization_state;
static uint16_t sm_response_handle = 0;
static timer_source_t sm_timeout;
typedef struct sm_connection {
security_manager_state_t sm_state_responding;
uint8_t connection->sm_connection_encrypted;
uint8_t sm_connection_authenticated; // [0..1]
uint8_t sm_actual_encryption_key_size;
uint8_t sm_s_request_security = 0;
authorization_state_t sm_connection_authorization_state;
uint16_t sm_response_handle = 0;
timer_source_t sm_timeout;
} sm_connection_t;
static sm_connection_t single_connection;
static sm_connection_t * connection = &single_connection;
// @returns 1 if oob data is available // @returns 1 if oob data is available
// stores oob data in provided 16 byte buffer if not null // stores oob data in provided 16 byte buffer if not null
@ -360,7 +365,7 @@ static void sm_truncate_key(sm_key_t key, int max_encryption_size){
static void sm_timeout_handler(timer_source_t * timer){ static void sm_timeout_handler(timer_source_t * timer){
printf("SM timeout\n"); printf("SM timeout\n");
sm_state_responding = SM_STATE_TIMEOUT; connection->sm_state_responding = SM_STATE_TIMEOUT;
} }
static void sm_timeout_start(){ static void sm_timeout_start(){
run_loop_remove_timer(&sm_timeout); run_loop_remove_timer(&sm_timeout);
@ -620,8 +625,8 @@ static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){
} }
// while x_state++ for an enum is possible in C, it isn't in C++. we use this helpers to avoid compile errors for now // while x_state++ for an enum is possible in C, it isn't in C++. we use this helpers to avoid compile errors for now
static inline void sm_state_responding_next_state(){ static inline void sm_next_responding_state(){
sm_state_responding = (security_manager_state_t) (((int)sm_state_responding) + 1); connection->sm_state_responding = (security_manager_state_t) (((int)connection->sm_state_responding) + 1);
} }
static inline void dkg_next_state(){ static inline void dkg_next_state(){
dkg_state = (derived_key_generation_t) (((int)dkg_state) + 1); dkg_state = (derived_key_generation_t) (((int)dkg_state) + 1);
@ -772,7 +777,7 @@ static int sm_key_distribution_done(){
static void sm_pdu_received_in_wrong_state(){ static void sm_pdu_received_in_wrong_state(){
sm_pairing_failed_reason = SM_REASON_UNSPECIFIED_REASON; sm_pairing_failed_reason = SM_REASON_UNSPECIFIED_REASON;
sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
} }
@ -901,14 +906,14 @@ static void sm_run(void){
} }
// responding state // responding state
switch (sm_state_responding){ switch (connection->sm_state_responding){
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;
buffer[1] = SM_AUTHREQ_BONDING; buffer[1] = SM_AUTHREQ_BONDING;
l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
return; return;
} }
@ -957,13 +962,13 @@ static void sm_run(void){
break; break;
} }
sm_state_responding = SM_STATE_PH1_W4_PAIRING_CONFIRM; connection->sm_state_responding = SM_STATE_PH1_W4_PAIRING_CONFIRM;
return; return;
} }
case SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY: case SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY:
hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_response_handle); hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_response_handle);
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
return; return;
case SM_STATE_SEND_PAIRING_FAILED: { case SM_STATE_SEND_PAIRING_FAILED: {
@ -972,7 +977,7 @@ static void sm_run(void){
buffer[1] = sm_pairing_failed_reason; buffer[1] = sm_pairing_failed_reason;
l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_timeout_stop(); sm_timeout_stop();
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
break; break;
} }
@ -982,7 +987,7 @@ static void sm_run(void){
swap128(sm_s_random, &buffer[1]); swap128(sm_s_random, &buffer[1]);
l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_timeout_reset(); sm_timeout_reset();
sm_state_responding = SM_STATE_PH2_W4_LTK_REQUEST; connection->sm_state_responding = SM_STATE_PH2_W4_LTK_REQUEST;
break; break;
} }
@ -992,7 +997,7 @@ static void sm_run(void){
case SM_STATE_PH3_GET_RANDOM: case SM_STATE_PH3_GET_RANDOM:
case SM_STATE_PH3_GET_DIV: case SM_STATE_PH3_GET_DIV:
hci_send_cmd(&hci_le_rand); hci_send_cmd(&hci_le_rand);
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_PH2_C1_GET_ENC_B: case SM_STATE_PH2_C1_GET_ENC_B:
@ -1000,7 +1005,7 @@ static void sm_run(void){
// already busy? // already busy?
if (sm_aes128_state == SM_AES128_ACTIVE) break; if (sm_aes128_state == SM_AES128_ACTIVE) break;
sm_aes128_start(sm_tk, sm_aes128_plaintext); sm_aes128_start(sm_tk, sm_aes128_plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_PH3_LTK_GET_ENC: case SM_STATE_PH3_LTK_GET_ENC:
@ -1008,7 +1013,7 @@ static void sm_run(void){
// already busy? // already busy?
if (sm_aes128_state == SM_AES128_ACTIVE) break; if (sm_aes128_state == SM_AES128_ACTIVE) break;
sm_aes128_start(sm_persistent_er, sm_aes128_plaintext); sm_aes128_start(sm_persistent_er, sm_aes128_plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_PH2_C1_GET_ENC_C: case SM_STATE_PH2_C1_GET_ENC_C:
@ -1017,7 +1022,7 @@ static void sm_run(void){
// calculate m_confirm using aes128 engine - step 1 // 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_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_aes128_start(sm_tk, plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
break; break;
case SM_STATE_PH2_C1_GET_ENC_A: case SM_STATE_PH2_C1_GET_ENC_A:
// already busy? // already busy?
@ -1025,7 +1030,7 @@ static void sm_run(void){
// calculate s_confirm using aes128 engine - step 1 // 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_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_aes128_start(sm_tk, plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
break; break;
case SM_STATE_PH2_CALC_STK: case SM_STATE_PH2_CALC_STK:
// already busy? // already busy?
@ -1033,7 +1038,7 @@ static void sm_run(void){
// calculate STK // calculate STK
sm_s1_r_prime(sm_s_random, sm_m_random, plaintext); sm_s1_r_prime(sm_s_random, sm_m_random, plaintext);
sm_aes128_start(sm_tk, plaintext); sm_aes128_start(sm_tk, plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
break; break;
case SM_STATE_PH3_Y_GET_ENC: case SM_STATE_PH3_Y_GET_ENC:
// already busy? // already busy?
@ -1042,7 +1047,7 @@ static void sm_run(void){
// Y = dm(DHK, Rand) // Y = dm(DHK, Rand)
sm_dm_r_prime(sm_s_rand, plaintext); sm_dm_r_prime(sm_s_rand, plaintext);
sm_aes128_start(sm_persistent_dhk, plaintext); sm_aes128_start(sm_persistent_dhk, plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_PH2_C1_SEND_PAIRING_CONFIRM: { case SM_STATE_PH2_C1_SEND_PAIRING_CONFIRM: {
uint8_t buffer[17]; uint8_t buffer[17];
@ -1050,21 +1055,21 @@ static void sm_run(void){
swap128(sm_s_confirm, &buffer[1]); swap128(sm_s_confirm, &buffer[1]);
l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_timeout_reset(); sm_timeout_reset();
sm_state_responding = SM_STATE_PH2_W4_PAIRING_RANDOM; connection->sm_state_responding = SM_STATE_PH2_W4_PAIRING_RANDOM;
return; return;
} }
case SM_STATE_PH2_SEND_STK: { case SM_STATE_PH2_SEND_STK: {
sm_key_t stk_flipped; sm_key_t stk_flipped;
swap128(sm_s_ltk, stk_flipped); swap128(sm_s_ltk, stk_flipped);
hci_send_cmd(&hci_le_long_term_key_request_reply, sm_response_handle, stk_flipped); hci_send_cmd(&hci_le_long_term_key_request_reply, sm_response_handle, stk_flipped);
sm_state_responding = SM_STATE_PH2_W4_CONNECTION_ENCRYPTED; connection->sm_state_responding = SM_STATE_PH2_W4_CONNECTION_ENCRYPTED;
return; return;
} }
case SM_STATE_PH4_SEND_LTK: { case SM_STATE_PH4_SEND_LTK: {
sm_key_t ltk_flipped; sm_key_t ltk_flipped;
swap128(sm_s_ltk, ltk_flipped); swap128(sm_s_ltk, ltk_flipped);
hci_send_cmd(&hci_le_long_term_key_request_reply, sm_response_handle, ltk_flipped); hci_send_cmd(&hci_le_long_term_key_request_reply, sm_response_handle, ltk_flipped);
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
return; return;
} }
case SM_STATE_PH4_Y_GET_ENC: case SM_STATE_PH4_Y_GET_ENC:
@ -1074,7 +1079,7 @@ static void sm_run(void){
// Y = dm(DHK, Rand) // Y = dm(DHK, Rand)
sm_dm_r_prime(sm_s_rand, plaintext); sm_dm_r_prime(sm_s_rand, plaintext);
sm_aes128_start(sm_persistent_dhk, plaintext); sm_aes128_start(sm_persistent_dhk, plaintext);
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_DISTRIBUTE_KEYS: case SM_STATE_DISTRIBUTE_KEYS:
@ -1129,7 +1134,7 @@ static void sm_run(void){
if (sm_key_distribution_done()){ if (sm_key_distribution_done()){
sm_timeout_stop(); sm_timeout_stop();
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
} }
break; break;
@ -1209,7 +1214,7 @@ static void sm_handle_encryption_result(uint8_t * data){
break; break;
} }
switch (sm_state_responding){ switch (connection->sm_state_responding){
case SM_STATE_PH2_C1_W4_ENC_A: case SM_STATE_PH2_C1_W4_ENC_A:
case SM_STATE_PH2_C1_W4_ENC_C: case SM_STATE_PH2_C1_W4_ENC_C:
{ {
@ -1218,12 +1223,12 @@ static void sm_handle_encryption_result(uint8_t * data){
sm_c1_t3(t2, sm_m_address, sm_s_address, sm_aes128_plaintext); sm_c1_t3(t2, sm_m_address, sm_s_address, sm_aes128_plaintext);
sm_aes128_state = SM_AES128_PLAINTEXT_SET; sm_aes128_state = SM_AES128_PLAINTEXT_SET;
} }
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_PH2_C1_W4_ENC_B: case SM_STATE_PH2_C1_W4_ENC_B:
swap128(data, sm_s_confirm); swap128(data, sm_s_confirm);
print_key("c1!", sm_s_confirm); print_key("c1!", sm_s_confirm);
sm_state_responding_next_state(); sm_next_responding_state();
return; return;
case SM_STATE_PH2_C1_W4_ENC_D: case SM_STATE_PH2_C1_W4_ENC_D:
{ {
@ -1232,18 +1237,18 @@ static void sm_handle_encryption_result(uint8_t * data){
print_key("c1!", m_confirm_test); print_key("c1!", m_confirm_test);
if (memcmp(sm_m_confirm, m_confirm_test, 16) == 0){ if (memcmp(sm_m_confirm, m_confirm_test, 16) == 0){
// send s_random // send s_random
sm_state_responding = SM_STATE_SEND_PAIRING_RANDOM; connection->sm_state_responding = SM_STATE_SEND_PAIRING_RANDOM;
return; return;
} }
sm_pairing_failed_reason = SM_REASON_CONFIRM_VALUE_FAILED; sm_pairing_failed_reason = SM_REASON_CONFIRM_VALUE_FAILED;
sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
} }
return; return;
case SM_STATE_PH2_W4_STK: case SM_STATE_PH2_W4_STK:
swap128(data, sm_s_ltk); swap128(data, sm_s_ltk);
sm_truncate_key(sm_s_ltk, sm_actual_encryption_key_size); sm_truncate_key(sm_s_ltk, sm_actual_encryption_key_size);
print_key("stk", sm_s_ltk); print_key("stk", sm_s_ltk);
sm_state_responding = SM_STATE_PH2_SEND_STK; connection->sm_state_responding = SM_STATE_PH2_SEND_STK;
return; return;
case SM_STATE_PH3_Y_W4_ENC:{ case SM_STATE_PH3_Y_W4_ENC:{
sm_key_t y128; sm_key_t y128;
@ -1257,7 +1262,7 @@ static void sm_handle_encryption_result(uint8_t * data){
// LTK = d1(ER, DIV, 0)) // LTK = d1(ER, DIV, 0))
sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext); sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext);
sm_aes128_state = SM_AES128_PLAINTEXT_SET; sm_aes128_state = SM_AES128_PLAINTEXT_SET;
sm_state_responding = SM_STATE_PH3_LTK_GET_ENC; connection->sm_state_responding = SM_STATE_PH3_LTK_GET_ENC;
return; return;
} }
case SM_STATE_PH4_Y_W4_ENC:{ case SM_STATE_PH4_Y_W4_ENC:{
@ -1272,20 +1277,20 @@ static void sm_handle_encryption_result(uint8_t * data){
// LTK = d1(ER, DIV, 0)) // LTK = d1(ER, DIV, 0))
sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext); sm_d1_d_prime(sm_s_div, 0, sm_aes128_plaintext);
sm_aes128_state = SM_AES128_PLAINTEXT_SET; sm_aes128_state = SM_AES128_PLAINTEXT_SET;
sm_state_responding = SM_STATE_PH4_LTK_GET_ENC; connection->sm_state_responding = SM_STATE_PH4_LTK_GET_ENC;
return; return;
} }
case SM_STATE_PH3_LTK_W4_ENC: case SM_STATE_PH3_LTK_W4_ENC:
swap128(data, sm_s_ltk); swap128(data, sm_s_ltk);
print_key("ltk", sm_s_ltk); print_key("ltk", sm_s_ltk);
// distribute keys // distribute keys
sm_state_responding = SM_STATE_DISTRIBUTE_KEYS; connection->sm_state_responding = SM_STATE_DISTRIBUTE_KEYS;
return; return;
case SM_STATE_PH4_LTK_W4_ENC: case SM_STATE_PH4_LTK_W4_ENC:
swap128(data, sm_s_ltk); swap128(data, sm_s_ltk);
sm_truncate_key(sm_s_ltk, sm_actual_encryption_key_size); sm_truncate_key(sm_s_ltk, sm_actual_encryption_key_size);
print_key("ltk", sm_s_ltk); print_key("ltk", sm_s_ltk);
sm_state_responding = SM_STATE_PH4_SEND_LTK; connection->sm_state_responding = SM_STATE_PH4_SEND_LTK;
return; return;
default: default:
break; break;
@ -1320,7 +1325,7 @@ static void sm_handle_random_result(uint8_t * data){
break; break;
} }
switch (sm_state_responding){ switch (connection->sm_state_responding){
case SM_STATE_PH2_W4_RANDOM_TK: case SM_STATE_PH2_W4_RANDOM_TK:
{ {
// map random to 0-999999 without speding much cycles on a modulus operation // map random to 0-999999 without speding much cycles on a modulus operation
@ -1332,16 +1337,16 @@ static void sm_handle_random_result(uint8_t * data){
sm_reset_tk(); sm_reset_tk();
net_store_32(sm_tk, 12, tk); net_store_32(sm_tk, 12, tk);
// continue with phase 1 // continue with phase 1
sm_state_responding = SM_STATE_PH1_SEND_PAIRING_RESPONSE; connection->sm_state_responding = SM_STATE_PH1_SEND_PAIRING_RESPONSE;
return; return;
} }
case SM_STATE_PH2_C1_W4_RANDOM_A: case SM_STATE_PH2_C1_W4_RANDOM_A:
memcpy(&sm_s_random[0], data, 8); // random endinaness memcpy(&sm_s_random[0], data, 8); // random endinaness
sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_B; connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_B;
return; return;
case SM_STATE_PH2_C1_W4_RANDOM_B: case SM_STATE_PH2_C1_W4_RANDOM_B:
memcpy(&sm_s_random[8], data, 8); // random endinaness memcpy(&sm_s_random[8], data, 8); // random endinaness
sm_state_responding = SM_STATE_PH2_C1_GET_ENC_A; connection->sm_state_responding = SM_STATE_PH2_C1_GET_ENC_A;
return; return;
case SM_STATE_PH3_W4_RANDOM: case SM_STATE_PH3_W4_RANDOM:
swap64(data, sm_s_rand); swap64(data, sm_s_rand);
@ -1349,13 +1354,13 @@ static void sm_handle_random_result(uint8_t * data){
sm_s_rand[7] = (sm_s_rand[7] & 0xf0) + (sm_actual_encryption_key_size - 1); sm_s_rand[7] = (sm_s_rand[7] & 0xf0) + (sm_actual_encryption_key_size - 1);
// no db for authenticated flag hack: store flag in bit 4 of LSB // no db for authenticated flag hack: store flag in bit 4 of LSB
sm_s_rand[7] = (sm_s_rand[7] & 0xef) + (sm_connection_authenticated << 4); sm_s_rand[7] = (sm_s_rand[7] & 0xef) + (sm_connection_authenticated << 4);
sm_state_responding = SM_STATE_PH3_GET_DIV; connection->sm_state_responding = SM_STATE_PH3_GET_DIV;
return; return;
case SM_STATE_PH3_W4_DIV: case SM_STATE_PH3_W4_DIV:
// use 16 bit from random value as div // use 16 bit from random value as div
sm_s_div = READ_NET_16(data, 0); sm_s_div = READ_NET_16(data, 0);
print_hex16("div", sm_s_div); print_hex16("div", sm_s_div);
sm_state_responding = SM_STATE_PH3_Y_GET_ENC; connection->sm_state_responding = SM_STATE_PH3_Y_GET_ENC;
return; return;
default: default:
break; break;
@ -1404,13 +1409,13 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
printf("Incoming connection, own address %s\n", bd_addr_to_str(sm_s_address)); printf("Incoming connection, own address %s\n", bd_addr_to_str(sm_s_address));
// reset security properties // reset security properties
sm_connection_encrypted = 0; connection->sm_connection_encrypted = 0;
sm_connection_authenticated = 0; sm_connection_authenticated = 0;
sm_connection_authorization_state = AUTHORIZATION_UNKNOWN; sm_connection_authorization_state = AUTHORIZATION_UNKNOWN;
// request security // request security
if (sm_s_request_security){ if (sm_s_request_security){
sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST; connection->sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST;
} }
sm_m_csrk_lookup_state = CSRK_LOOKUP_W4_READY; sm_m_csrk_lookup_state = CSRK_LOOKUP_W4_READY;
@ -1423,9 +1428,9 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
break; break;
case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST: case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST:
log_info("LTK Request: state %u", sm_state_responding); log_info("LTK Request: state %u", connection->sm_state_responding);
if (sm_state_responding == SM_STATE_PH2_W4_LTK_REQUEST){ if (connection->sm_state_responding == SM_STATE_PH2_W4_LTK_REQUEST){
sm_state_responding = SM_STATE_PH2_CALC_STK; connection->sm_state_responding = SM_STATE_PH2_CALC_STK;
break; break;
} }
@ -1436,7 +1441,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// assume that we don't have a LTK for ediv == 0 and random == null // 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 (sm_s_ediv == 0 && sm_is_null_random(sm_s_rand)){
printf("LTK Request: ediv & random are empty\n"); printf("LTK Request: ediv & random are empty\n");
sm_state_responding = SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY; connection->sm_state_responding = SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
break; break;
} }
@ -1447,7 +1452,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// no db for authenticated flag hack: flag is stored in bit 4 of LSB // no db for authenticated flag hack: flag is stored in bit 4 of LSB
sm_connection_authenticated = (sm_s_rand[7] & 0x10) >> 4; sm_connection_authenticated = (sm_s_rand[7] & 0x10) >> 4;
sm_state_responding = SM_STATE_PH4_Y_GET_ENC; connection->sm_state_responding = SM_STATE_PH4_Y_GET_ENC;
break; break;
default: default:
@ -1457,16 +1462,16 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
case HCI_EVENT_ENCRYPTION_CHANGE: case HCI_EVENT_ENCRYPTION_CHANGE:
if (sm_response_handle != READ_BT_16(packet, 3)) break; if (sm_response_handle != READ_BT_16(packet, 3)) break;
sm_connection_encrypted = packet[5]; connection->sm_connection_encrypted = packet[5];
log_info("Eencryption state change: %u", sm_connection_encrypted); log_info("Eencryption state change: %u", connection->sm_connection_encrypted);
if (!sm_connection_encrypted) break; if (!connection->sm_connection_encrypted) break;
if (sm_state_responding == SM_STATE_PH2_W4_CONNECTION_ENCRYPTED) { if (connection->sm_state_responding == SM_STATE_PH2_W4_CONNECTION_ENCRYPTED) {
sm_state_responding = SM_STATE_PH3_GET_RANDOM; connection->sm_state_responding = SM_STATE_PH3_GET_RANDOM;
} }
break; break;
case HCI_EVENT_DISCONNECTION_COMPLETE: case HCI_EVENT_DISCONNECTION_COMPLETE:
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
sm_response_handle = 0; sm_response_handle = 0;
break; break;
@ -1505,11 +1510,11 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
} }
if (packet[0] == SM_CODE_PAIRING_FAILED){ if (packet[0] == SM_CODE_PAIRING_FAILED){
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
return; return;
} }
switch (sm_state_responding){ switch (connection->sm_state_responding){
// a sm timeout requries a new physical connection // a sm timeout requries a new physical connection
case SM_STATE_TIMEOUT: case SM_STATE_TIMEOUT:
@ -1530,7 +1535,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
// assert max encryption size above our minimum // assert max encryption size above our minimum
if (sm_m_max_encryption_key_size < sm_min_encryption_key_size){ if (sm_m_max_encryption_key_size < sm_min_encryption_key_size){
sm_pairing_failed_reason = SM_REASON_ENCRYPTION_KEY_SIZE; sm_pairing_failed_reason = SM_REASON_ENCRYPTION_KEY_SIZE;
sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
break; break;
} }
@ -1571,7 +1576,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
} }
if (!ok){ if (!ok){
sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS; sm_pairing_failed_reason = SM_REASON_AUTHENTHICATION_REQUIREMENTS;
sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
break; break;
} }
@ -1580,11 +1585,11 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
// generate random number first, if we need to show passkey // generate random number first, if we need to show passkey
if (sm_stk_generation_method == PK_INIT_INPUT){ if (sm_stk_generation_method == PK_INIT_INPUT){
sm_state_responding = SM_STATE_PH2_GET_RANDOM_TK; connection->sm_state_responding = SM_STATE_PH2_GET_RANDOM_TK;
break; break;
} }
sm_state_responding = SM_STATE_PH1_SEND_PAIRING_RESPONSE; connection->sm_state_responding = SM_STATE_PH1_SEND_PAIRING_RESPONSE;
break; break;
} }
@ -1605,18 +1610,18 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
// handle user cancel pairing? // handle user cancel pairing?
if (sm_user_response == SM_USER_RESPONSE_DECLINE){ if (sm_user_response == SM_USER_RESPONSE_DECLINE){
sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED; sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED;
sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
break; break;
} }
// wait for user action? // wait for user action?
if (sm_user_response == SM_USER_RESPONSE_PENDING){ if (sm_user_response == SM_USER_RESPONSE_PENDING){
sm_state_responding = SM_STATE_PH1_W4_USER_RESPONSE; connection->sm_state_responding = SM_STATE_PH1_W4_USER_RESPONSE;
break; break;
} }
// calculate and send s_confirm // calculate and send s_confirm
sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A; connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A;
break; break;
case SM_STATE_PH2_W4_PAIRING_RANDOM: case SM_STATE_PH2_W4_PAIRING_RANDOM:
@ -1627,7 +1632,7 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
// received random value // received random value
swap128(&packet[1], sm_m_random); swap128(&packet[1], sm_m_random);
sm_state_responding = SM_STATE_PH2_C1_GET_ENC_C; connection->sm_state_responding = SM_STATE_PH2_C1_GET_ENC_C;
break; break;
case SM_STATE_DISTRIBUTE_KEYS: case SM_STATE_DISTRIBUTE_KEYS:
@ -1674,12 +1679,12 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac
// done with key distribution? // done with key distribution?
if (sm_key_distribution_done()){ if (sm_key_distribution_done()){
sm_timeout_stop(); sm_timeout_stop();
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
} }
break; break;
default: default:
// Unexpected PDU // Unexpected PDU
printf("Unexpected PDU %u in state %u\n", packet[0], sm_state_responding); printf("Unexpected PDU %u in state %u\n", packet[0], connection->sm_state_responding);
break; break;
} }
@ -1737,7 +1742,7 @@ void sm_test_set_irk(sm_key_t irk){
* @note Not used normally. Bonding is triggered by access to protected attributes in ATT Server * @note Not used normally. Bonding is triggered by access to protected attributes in ATT Server
*/ */
void sm_send_security_request(){ void sm_send_security_request(){
sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST; connection->sm_state_responding = SM_STATE_SEND_SECURITY_REQUEST;
sm_run(); sm_run();
} }
@ -1752,7 +1757,7 @@ void sm_init(){
} }
sm_set_er(er); sm_set_er(er);
sm_set_ir(ir); sm_set_ir(ir);
sm_state_responding = SM_STATE_IDLE; connection->sm_state_responding = SM_STATE_IDLE;
// defaults // defaults
sm_accepted_stk_generation_methods = SM_STK_GENERATION_METHOD_JUST_WORKS sm_accepted_stk_generation_methods = SM_STK_GENERATION_METHOD_JUST_WORKS
| SM_STK_GENERATION_METHOD_OOB | SM_STK_GENERATION_METHOD_OOB
@ -1779,19 +1784,19 @@ static int sm_get_connection(uint8_t addr_type, bd_addr_t address){
// @returns 0 if not encrypted, 7-16 otherwise // @returns 0 if not encrypted, 7-16 otherwise
int sm_encryption_key_size(uint8_t addr_type, bd_addr_t address){ int sm_encryption_key_size(uint8_t addr_type, bd_addr_t address){
if (!sm_get_connection(addr_type, address)) return 0; // wrong connection if (!sm_get_connection(addr_type, address)) return 0; // wrong connection
if (!sm_connection_encrypted) return 0; if (!connection->sm_connection_encrypted) return 0;
return sm_actual_encryption_key_size; return sm_actual_encryption_key_size;
} }
int sm_authenticated(uint8_t addr_type, bd_addr_t address){ int sm_authenticated(uint8_t addr_type, bd_addr_t address){
if (!sm_get_connection(addr_type, address)) return 0; // wrong connection if (!sm_get_connection(addr_type, address)) return 0; // wrong connection
if (!sm_connection_encrypted) return 0; // unencrypted connection cannot be authenticated if (!connection->sm_connection_encrypted) return 0; // unencrypted connection cannot be authenticated
return sm_connection_authenticated; return sm_connection_authenticated;
} }
authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t address){ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t address){
if (!sm_get_connection(addr_type, address)) return AUTHORIZATION_UNKNOWN; // wrong connection if (!sm_get_connection(addr_type, address)) return AUTHORIZATION_UNKNOWN; // wrong connection
if (!sm_connection_encrypted) return AUTHORIZATION_UNKNOWN; // unencrypted connection cannot be authorized if (!connection->sm_connection_encrypted) return AUTHORIZATION_UNKNOWN; // unencrypted connection cannot be authorized
if (!sm_connection_authenticated) return AUTHORIZATION_UNKNOWN; // unauthenticatd connection cannot be authorized if (!sm_connection_authenticated) return AUTHORIZATION_UNKNOWN; // unauthenticatd connection cannot be authorized
return sm_connection_authorization_state; return sm_connection_authorization_state;
} }
@ -1821,9 +1826,9 @@ void sm_bonding_decline(uint8_t addr_type, bd_addr_t address){
if (!sm_get_connection(addr_type, address)) return; // wrong connection if (!sm_get_connection(addr_type, address)) return; // wrong connection
sm_user_response = SM_USER_RESPONSE_DECLINE; sm_user_response = SM_USER_RESPONSE_DECLINE;
if (sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){ if (connection->sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){
sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED; sm_pairing_failed_reason = SM_REASON_PASSKEYT_ENTRY_FAILED;
sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; connection->sm_state_responding = SM_STATE_SEND_PAIRING_FAILED;
} }
sm_run(); sm_run();
} }
@ -1831,8 +1836,8 @@ 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){ void sm_just_works_confirm(uint8_t addr_type, bd_addr_t address){
if (!sm_get_connection(addr_type, address)) return; // wrong connection if (!sm_get_connection(addr_type, address)) return; // wrong connection
sm_user_response = SM_USER_RESPONSE_CONFIRM; sm_user_response = SM_USER_RESPONSE_CONFIRM;
if (sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){ if (connection->sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){
sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A; connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A;
} }
sm_run(); sm_run();
} }
@ -1842,8 +1847,8 @@ void sm_passkey_input(uint8_t addr_type, bd_addr_t address, uint32_t passkey){
sm_reset_tk(); sm_reset_tk();
net_store_32(sm_tk, 12, passkey); net_store_32(sm_tk, 12, passkey);
sm_user_response = SM_USER_RESPONSE_PASSKEY; sm_user_response = SM_USER_RESPONSE_PASSKEY;
if (sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){ if (connection->sm_state_responding == SM_STATE_PH1_W4_USER_RESPONSE){
sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A; connection->sm_state_responding = SM_STATE_PH2_C1_GET_RANDOM_A;
} }
sm_run(); sm_run();
} }