sm: fix mbedTLS integration

This commit is contained in:
Matthias Ringwald 2017-09-25 17:31:42 +02:00
parent aa29f5873d
commit 034d8e7065

View File

@ -30,13 +30,13 @@
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define __BTSTACK_FILE__ "sm.c"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
@ -76,7 +76,7 @@
#error "HCI_ACL_PAYLOAD_SIZE must be at least 69 bytes when using LE Secure Conection. Please increase HCI_ACL_PAYLOAD_SIZE or disable ENABLE_LE_SECURE_CONNECTIONS"
#endif
// configure ECC implementations
// configure ECC implementations
#ifdef ENABLE_LE_SECURE_CONNECTIONS
#if defined(ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS) && defined(HAVE_MBEDTLS_ECC_P256)
#error "If you already have mbedTLS (HAVE_MBEDTLS_ECC_P256), please disable uECC (USE_MICRO_ECC_FOR_ECDH) in bstack_config.h"
@ -143,7 +143,7 @@ typedef enum {
typedef enum {
JUST_WORKS,
PK_RESP_INPUT, // Initiator displays PK, responder inputs PK
PK_RESP_INPUT, // Initiator displays PK, responder inputs PK
PK_INIT_INPUT, // Responder displays PK, initiator inputs PK
OK_BOTH_INPUT, // Only input on both, both input PK
NK_BOTH_INPUT, // Only numerical compparison (yes/no) on on both sides
@ -318,7 +318,7 @@ typedef struct sm_setup_context {
sm_key_t sm_tk;
uint8_t sm_use_secure_connections;
sm_key_t sm_c1_t3_value; // c1 calculation
sm_key_t sm_c1_t3_value; // c1 calculation
sm_pairing_packet_t sm_m_preq; // pairing request - needed only for c1
sm_pairing_packet_t sm_s_pres; // pairing response - needed only for c1
sm_key_t sm_local_random;
@ -326,7 +326,7 @@ typedef struct sm_setup_context {
sm_key_t sm_peer_random;
sm_key_t sm_peer_confirm;
uint8_t sm_m_addr_type; // address and type can be removed
uint8_t sm_s_addr_type; // ''
uint8_t sm_s_addr_type; // ''
bd_addr_t sm_m_address; // ''
bd_addr_t sm_s_address; // ''
sm_key_t sm_ltk;
@ -336,7 +336,7 @@ typedef struct sm_setup_context {
uint8_t sm_peer_q[64]; // also stores random for EC key generation during init
sm_key_t sm_peer_nonce; // might be combined with sm_peer_random
sm_key_t sm_local_nonce; // might be combined with sm_local_random
sm_key_t sm_dhkey;
sm_key_t sm_dhkey;
sm_key_t sm_peer_dhkey_check;
sm_key_t sm_local_dhkey_check;
sm_key_t sm_ra;
@ -371,7 +371,7 @@ typedef struct sm_setup_context {
} sm_setup_context_t;
//
//
static sm_setup_context_t the_setup;
static sm_setup_context_t * setup = &the_setup;
@ -481,14 +481,14 @@ static void sm_timeout_stop(void){
}
static void sm_timeout_reset(sm_connection_t * sm_conn){
sm_timeout_stop();
sm_timeout_start(sm_conn);
sm_timeout_start(sm_conn);
}
// end of sm timeout
// GAP Random Address updates
static gap_random_address_type_t gap_random_adress_type;
static btstack_timer_source_t gap_random_address_update_timer;
static btstack_timer_source_t gap_random_address_update_timer;
static uint32_t gap_random_adress_update_period;
static void gap_random_address_trigger(void){
@ -598,7 +598,7 @@ static void sm_c1_t1(sm_key_t r, uint8_t preq[7], uint8_t pres[7], uint8_t iat,
// For example, if the 8-bit iat is 0x01, the 8-bit rat is 0x00, the 56-bit preq
// is 0x07071000000101 and the 56 bit pres is 0x05000800000302 then
// p1 is 0x05000800000302070710000001010001."
sm_key_t p1;
reverse_56(pres, &p1[0]);
reverse_56(preq, &p1[7]);
@ -606,7 +606,7 @@ static void sm_c1_t1(sm_key_t r, uint8_t preq[7], uint8_t pres[7], uint8_t iat,
p1[15] = iat;
log_info_key("p1", p1);
log_info_key("r", r);
// t1 = r xor p1
int i;
for (i=0;i<16;i++){
@ -622,7 +622,7 @@ static void sm_c1_t3(sm_key_t t2, bd_addr_t ia, bd_addr_t ra, uint8_t * t3){
// the most significant octet of padding becomes the most significant octet of p2.
// For example, if 48-bit ia is 0xA1A2A3A4A5A6 and the 48-bit ra is
// 0xB1B2B3B4B5B6 then p2 is 0x00000000A1A2A3A4A5A6B1B2B3B4B5B6.
sm_key_t p2;
memset(p2, 0, 16);
memcpy(&p2[4], ia, 6);
@ -668,7 +668,7 @@ static void calc_subkeys(sm_key_t k0, sm_key_t k1, sm_key_t k2){
sm_shift_left_by_one_bit_inplace(16, k2);
if (k1[0] & 0x80){
k2[15] ^= 0x87;
}
}
}
static void aes_cmac(sm_key_t aes_cmac, const sm_key_t key, const uint8_t * data, int cmac_message_len){
@ -785,7 +785,7 @@ static void sm_notify_client_index(uint8_t type, hci_con_handle_t con_handle, ui
static void sm_notify_client_authorization(uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address, uint8_t result){
uint8_t event[18];
sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
event[11] = result;
sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
}
@ -808,11 +808,11 @@ static void sm_setup_tk(void){
#else
setup->sm_use_secure_connections = 0;
#endif
// 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_pairing_packet_get_auth_req(setup->sm_m_preq) & SM_AUTHREQ_MITM_PROTECTION) == 0)
// model shall be used.
if (((sm_pairing_packet_get_auth_req(setup->sm_m_preq) & SM_AUTHREQ_MITM_PROTECTION) == 0)
&& ((sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_MITM_PROTECTION) == 0)){
log_info("SM: MITM not required by both -> JUST WORKS");
return;
@ -849,7 +849,7 @@ static void sm_setup_tk(void){
if (setup->sm_use_secure_connections){
generation_method = stk_generation_method_with_secure_connection;
}
#endif
#endif
setup->sm_stk_generation_method = generation_method[sm_pairing_packet_get_io_capability(setup->sm_s_pres)][sm_pairing_packet_get_io_capability(setup->sm_m_preq)];
log_info("sm_setup_tk: master io cap: %u, slave io cap: %u -> method %u",
@ -860,11 +860,11 @@ static int sm_key_distribution_flags_for_set(uint8_t key_set){
int flags = 0;
if (key_set & SM_KEYDIST_ENC_KEY){
flags |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
flags |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
flags |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
}
if (key_set & SM_KEYDIST_ID_KEY){
flags |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
flags |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
flags |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
}
if (key_set & SM_KEYDIST_SIGN){
flags |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
@ -909,7 +909,7 @@ int sm_address_resolution_lookup(uint8_t address_type, bd_addr_t address){
if (!entry) return BTSTACK_MEMORY_ALLOC_FAILED;
entry->address_type = (bd_addr_type_t) address_type;
memcpy(entry->address, address, 6);
btstack_linked_list_add(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
btstack_linked_list_add(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
sm_run();
return 0;
}
@ -1025,7 +1025,7 @@ static void sm_cmac_handle_aes_engine_ready(void){
int i;
sm_key_t y;
for (i=0;i<16;i++){
y[i] = sm_cmac_x[i] ^ sm_cmac_m_last[i];
y[i] = sm_cmac_x[i] ^ sm_cmac_m_last[i];
}
log_info_key("Y", y);
sm_cmac_block_current++;
@ -1064,7 +1064,7 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){
sm_shift_left_by_one_bit_inplace(16, k2);
if (k1[0] & 0x80){
k2[15] ^= 0x87;
}
}
log_info_key("k", sm_cmac_k);
log_info_key("k1", k1);
@ -1092,12 +1092,12 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){
}
// next
sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST;
sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST;
break;
}
case CMAC_W4_MI:
memcpy(sm_cmac_x, data, 16);
sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST;
sm_cmac_state = sm_cmac_block_current < sm_cmac_block_count - 1 ? CMAC_CALC_MI : CMAC_CALC_MLAST;
break;
case CMAC_W4_MLAST:
// done
@ -1120,26 +1120,26 @@ static void sm_trigger_user_response(sm_connection_t * sm_conn){
case PK_RESP_INPUT:
if (IS_RESPONDER(sm_conn->sm_role)){
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
} else {
sm_notify_client_passkey(SM_EVENT_PASSKEY_DISPLAY_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
sm_notify_client_passkey(SM_EVENT_PASSKEY_DISPLAY_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
}
break;
case PK_INIT_INPUT:
if (IS_RESPONDER(sm_conn->sm_role)){
sm_notify_client_passkey(SM_EVENT_PASSKEY_DISPLAY_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
sm_notify_client_passkey(SM_EVENT_PASSKEY_DISPLAY_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
} else {
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
}
break;
case OK_BOTH_INPUT:
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
break;
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
break;
case NK_BOTH_INPUT:
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
sm_notify_client_passkey(SM_EVENT_NUMERIC_COMPARISON_REQUEST, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
sm_notify_client_passkey(SM_EVENT_NUMERIC_COMPARISON_REQUEST, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
break;
case JUST_WORKS:
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
@ -1159,8 +1159,8 @@ static int sm_key_distribution_all_received(sm_connection_t * sm_conn){
} else {
// master / initiator
recv_flags = sm_key_distribution_flags_for_set(sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres));
}
log_debug("sm_key_distribution_all_received: received 0x%02x, expecting 0x%02x", setup->sm_key_distribution_received_set, recv_flags);
}
log_debug("sm_key_distribution_all_received: received 0x%02x, expecting 0x%02x", setup->sm_key_distribution_received_set, recv_flags);
return recv_flags == setup->sm_key_distribution_received_set;
}
@ -1199,7 +1199,7 @@ static void sm_init_setup(sm_connection_t * sm_conn){
if (sm_get_oob_data) {
have_oob_data = (*sm_get_oob_data)(sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, setup->sm_tk);
}
sm_pairing_packet_t * local_packet;
if (IS_RESPONDER(sm_conn->sm_role)){
// slave
@ -1266,7 +1266,7 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
int matched_device_id = sm_address_resolution_test;
address_resolution_mode_t mode = sm_address_resolution_mode;
void * context = sm_address_resolution_context;
// reset context
sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
sm_address_resolution_context = NULL;
@ -1384,7 +1384,7 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
sm_notify_client_index(SM_EVENT_IDENTITY_CREATED, sm_conn->sm_handle, setup->sm_peer_addr_type, setup->sm_peer_address, le_db_index);
if (le_db_index >= 0){
#ifdef ENABLE_LE_SIGNED_WRITE
// store local CSRK
if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
@ -1407,10 +1407,10 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
memset(zero_rand, 0, 8);
le_device_db_encryption_set(le_db_index, 0, zero_rand, setup->sm_ltk, sm_conn->sm_actual_encryption_key_size,
sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED);
}
}
// store encryption information for legacy pairing: peer LTK, EDIV, RAND
else if ( (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION)
else if ( (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION)
&& (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION )){
log_info("sm: set encryption information (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
@ -1420,7 +1420,7 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
}
// keep le_db_index
sm_conn->sm_le_db_index = le_db_index;
sm_conn->sm_le_db_index = le_db_index;
}
static void sm_pairing_error(sm_connection_t * sm_conn, uint8_t reason){
@ -1479,7 +1479,7 @@ static void sm_sc_state_after_receiving_random(sm_connection_t * sm_conn){
case OOB:
// TODO: implement SC OOB
break;
}
}
}
}
@ -1496,7 +1496,7 @@ static void sm_sc_cmac_done(uint8_t * hash){
#ifdef ENABLE_CLASSIC
link_key_type_t link_key_type;
#endif
switch (sm_conn->sm_engine_state){
case SM_SC_W4_CMAC_FOR_CONFIRMATION:
memcpy(setup->sm_local_confirm, hash, 16);
@ -1520,11 +1520,11 @@ static void sm_sc_cmac_done(uint8_t * hash){
case SM_SC_W4_CALCULATE_F5_SALT:
memcpy(setup->sm_t, hash, 16);
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_MACKEY;
break;
break;
case SM_SC_W4_CALCULATE_F5_MACKEY:
memcpy(setup->sm_mackey, hash, 16);
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_LTK;
break;
break;
case SM_SC_W4_CALCULATE_F5_LTK:
// truncate sm_ltk, but keep full LTK for cross-transport key derivation in sm_local_ltk
// Errata Service Release to the Bluetooth Specification: ESR09
@ -1534,7 +1534,7 @@ static void sm_sc_cmac_done(uint8_t * hash){
memcpy(setup->sm_local_ltk, hash, 16);
sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK;
break;
break;
case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
memcpy(setup->sm_local_dhkey_check, hash, 16);
if (IS_RESPONDER(sm_conn->sm_role)){
@ -1546,7 +1546,7 @@ static void sm_sc_cmac_done(uint8_t * hash){
}
} else {
sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
}
}
break;
case SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
if (0 != memcmp(hash, setup->sm_peer_dhkey_check, 16) ){
@ -1578,16 +1578,16 @@ static void sm_sc_cmac_done(uint8_t * hash){
}
#endif
if (IS_RESPONDER(sm_conn->sm_role)){
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
} else {
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
}
sm_done_for_handle(sm_conn->sm_handle);
break;
default:
log_error("sm_sc_cmac_done in state %u", sm_conn->sm_engine_state);
break;
}
}
sm_run();
}
@ -1606,7 +1606,7 @@ static void f4_engine(sm_connection_t * sm_conn, const sm_key256_t u, const sm_k
static const sm_key_t f5_salt = { 0x6C ,0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38, 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE};
static const uint8_t f5_key_id[] = { 0x62, 0x74, 0x6c, 0x65 };
static const uint8_t f5_length[] = { 0x01, 0x00};
static const uint8_t f5_length[] = { 0x01, 0x00};
#ifdef USE_SOFTWARE_ECDH_IMPLEMENTATION
@ -1730,7 +1730,7 @@ static void f6_engine(sm_connection_t * sm_conn, const sm_key_t w, const sm_key_
static void g2_engine(sm_connection_t * sm_conn, const sm_key256_t u, const sm_key256_t v, const sm_key_t x, const sm_key_t y){
const uint16_t message_len = 80;
sm_cmac_connection = sm_conn;
memcpy(sm_cmac_sc_buffer, u, 32);
memcpy(sm_cmac_sc_buffer, u, 32);
memcpy(sm_cmac_sc_buffer+32, v, 32);
memcpy(sm_cmac_sc_buffer+64, y, 16);
log_info("g2 key");
@ -1743,7 +1743,7 @@ static void g2_engine(sm_connection_t * sm_conn, const sm_key256_t u, const sm_k
static void g2_calculate(sm_connection_t * sm_conn) {
// calc Va if numeric comparison
if (IS_RESPONDER(sm_conn->sm_role)){
// responder
// responder
g2_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, setup->sm_local_nonce);;
} else {
// initiator
@ -1878,7 +1878,7 @@ static void h6_calculate_br_edr_link_key(sm_connection_t * sm_conn){
// - responder reconnects: responder uses LTK receveived from master
// key management secure connections:
// - both devices store same LTK from ECDH key exchange.
// - both devices store same LTK from ECDH key exchange.
#if defined(ENABLE_LE_SECURE_CONNECTIONS) || defined(ENABLE_LE_CENTRAL)
static void sm_load_security_info(sm_connection_t * sm_connection){
@ -1892,7 +1892,7 @@ static void sm_load_security_info(sm_connection_t * sm_connection){
log_info("db index %u, key size %u, authenticated %u, authorized %u", sm_connection->sm_le_db_index, encryption_key_size, authenticated, authorized);
sm_connection->sm_actual_encryption_key_size = encryption_key_size;
sm_connection->sm_connection_authenticated = authenticated;
sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
}
#endif
@ -1913,7 +1913,7 @@ static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_con
static void sm_run(void){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_t it;
// assert that stack has already bootet
if (hci_get_state() != HCI_STATE_WORKING) return;
@ -1950,7 +1950,7 @@ static void sm_run(void){
}
break;
default:
break;
break;
}
#ifdef ENABLE_LE_SECURE_CONNECTIONS
@ -1961,7 +1961,7 @@ static void sm_run(void){
ec_key_generation_state = EC_KEY_GENERATION_W4_KEY;
hci_send_cmd(&hci_le_read_local_p256_public_key);
#endif
return;
return;
}
#endif
@ -2100,9 +2100,9 @@ static void sm_run(void){
}
}
//
//
// active connection handling
// -- use loop to handle next connection if lock on setup context is released
// -- use loop to handle next connection if lock on setup context is released
while (1) {
@ -2121,7 +2121,7 @@ static void sm_run(void){
// send packet if possible,
if (l2cap_can_send_fixed_channel_packet_now(sm_connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL)){
const uint8_t buffer[2] = { SM_CODE_SECURITY_REQUEST, SM_AUTHREQ_BONDING};
sm_connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
sm_connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
l2cap_send_connectionless(sm_connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
} else {
l2cap_request_can_send_fix_channel_now_event(sm_connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL);
@ -2203,9 +2203,9 @@ static void sm_run(void){
}
}
//
//
// active connection handling
//
//
if (sm_active_connection_handle == HCI_CON_HANDLE_INVALID) return;
@ -2384,7 +2384,7 @@ static void sm_run(void){
case OOB:
// TODO: implement SC OOB
break;
}
}
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_timeout_reset(connection);
@ -2414,7 +2414,7 @@ static void sm_run(void){
} else {
// initiator
connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
}
}
} else {
if (IS_RESPONDER(connection->sm_role)){
// responder
@ -2426,7 +2426,7 @@ static void sm_run(void){
} else {
// initiator
connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
}
}
}
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_timeout_reset(connection);
@ -2444,7 +2444,7 @@ static void sm_run(void){
}
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
sm_timeout_reset(connection);
sm_timeout_reset(connection);
break;
}
@ -2691,14 +2691,14 @@ static void sm_run(void){
// slave -> receive master keys if any
if (sm_key_distribution_all_received(connection)){
sm_key_distribution_handle_all_received(connection);
connection->sm_engine_state = SM_RESPONDER_IDLE;
connection->sm_engine_state = SM_RESPONDER_IDLE;
sm_done_for_handle(connection->sm_handle);
} else {
connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
}
} else {
// master -> all done
connection->sm_engine_state = SM_INITIATOR_CONNECTED;
connection->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_done_for_handle(connection->sm_handle);
}
break;
@ -2866,19 +2866,19 @@ static void sm_handle_encryption_result(uint8_t * data){
connection->sm_engine_state = SM_SC_W2_CALCULATE_H6_ILK;
} else {
// master -> all done
connection->sm_engine_state = SM_INITIATOR_CONNECTED;
connection->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_done_for_handle(connection->sm_handle);
}
}
}
}
return;
return;
#ifdef ENABLE_LE_PERIPHERAL
case SM_RESPONDER_PH4_LTK_W4_ENC:
reverse_128(data, setup->sm_ltk);
sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
log_info_key("ltk", setup->sm_ltk);
connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
return;
return;
#endif
default:
break;
@ -2905,7 +2905,7 @@ static int sm_generate_f_rng(unsigned char * buffer, unsigned size){
// @return error - just wrap sm_generate_f_rng
static int sm_generate_f_rng_mbedtls(void * context, unsigned char * buffer, size_t size){
UNUSED(context);
return sm_generate_f_rng(buffer, size) == 1;
return sm_generate_f_rng(buffer, size) == 0;
}
#endif /* USE_MBEDTLS_FOR_ECDH */
#endif /* ENABLE_LE_SECURE_CONNECTIONS */
@ -2945,7 +2945,7 @@ static void sm_handle_random_result(uint8_t * data){
#else
// static version
uECC_make_key(ec_q, ec_d);
#endif
#endif
#endif /* USE_MICRO_ECC_FOR_ECDH */
#ifdef USE_MBEDTLS_FOR_ECDH
@ -2960,7 +2960,7 @@ static void sm_handle_random_result(uint8_t * data){
mbedtls_mpi_write_binary(&d, ec_d, 32);
mbedtls_ecp_point_free(&P);
mbedtls_mpi_free(&d);
#endif /* USE_MBEDTLS_FOR_ECDH */
#endif /* USE_MBEDTLS_FOR_ECDH */
ec_key_generation_state = EC_KEY_GENERATION_DONE;
log_info("Elliptic curve: d");
@ -2969,7 +2969,7 @@ static void sm_handle_random_result(uint8_t * data){
}
}
#endif
switch (rau_state){
case RAU_W4_RANDOM:
// non-resolvable vs. resolvable
@ -2986,7 +2986,7 @@ static void sm_handle_random_result(uint8_t * data){
default:
// "The two most significant bits of the address shall be equal to 0""
memcpy(sm_random_address, data, 6);
sm_random_address[0] &= 0x3f;
sm_random_address[0] &= 0x3f;
rau_state = RAU_SET_ADDRESS;
break;
}
@ -3026,7 +3026,7 @@ static void sm_handle_random_result(uint8_t * data){
tk = tk & 0xfffff; // 1048575
if (tk >= 999999){
tk = tk - 999999;
}
}
} else {
// override with pre-defined passkey
tk = sm_fixed_legacy_pairing_passkey_in_display_role;
@ -3084,7 +3084,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
hci_con_handle_t con_handle;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
@ -3106,7 +3106,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
case GAP_RANDOM_ADDRESS_TYPE_OFF:
rau_state = RAU_IDLE;
break;
case GAP_RANDOM_ADDRESS_TYPE_STATIC:
case GAP_RANDOM_ADDRESS_TYPE_STATIC:
rau_state = RAU_SET_ADDRESS;
break;
default:
@ -3116,7 +3116,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
sm_run();
}
break;
case HCI_EVENT_LE_META:
switch (packet[2]) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
@ -3153,7 +3153,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// request security if requested by app
sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
} else {
// otherwise, wait for pairing request
// otherwise, wait for pairing request
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
}
}
@ -3216,7 +3216,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
#endif
break;
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(USE_MICRO_ECC_FOR_ECDH)
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(USE_SOFTWARE_ECDH_IMPLEMENTATION)
case HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE:
if (hci_subevent_le_read_local_p256_public_key_complete_get_status(packet)){
log_error("Read Local P256 Public Key failed");
@ -3225,7 +3225,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_x(packet, &ec_q[0]);
hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_y(packet, &ec_q[32]);
ec_key_generation_state = EC_KEY_GENERATION_DONE;
sm_log_ec_keypair();
break;
@ -3254,7 +3254,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
}
break;
case HCI_EVENT_ENCRYPTION_CHANGE:
case HCI_EVENT_ENCRYPTION_CHANGE:
con_handle = little_endian_read_16(packet, 3);
sm_conn = sm_get_connection_for_handle(con_handle);
if (!sm_conn) break;
@ -3267,9 +3267,9 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// continue if part of initial pairing
switch (sm_conn->sm_engine_state){
case SM_INITIATOR_PH0_W4_CONNECTION_ENCRYPTED:
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_done_for_handle(sm_conn->sm_handle);
break;
break;
case SM_PH2_W4_CONNECTION_ENCRYPTED:
if (IS_RESPONDER(sm_conn->sm_role)){
// slave
@ -3283,7 +3283,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
if (sm_key_distribution_all_received(sm_conn)){
// skip receiving keys as there are none
sm_key_distribution_handle_all_received(sm_conn);
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
} else {
sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
}
@ -3304,9 +3304,9 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
// continue if part of initial pairing
switch (sm_conn->sm_engine_state){
case SM_INITIATOR_PH0_W4_CONNECTION_ENCRYPTED:
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
sm_done_for_handle(sm_conn->sm_handle);
break;
break;
case SM_PH2_W4_CONNECTION_ENCRYPTED:
if (IS_RESPONDER(sm_conn->sm_role)){
// slave
@ -3320,7 +3320,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
break;
}
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
con_handle = little_endian_read_16(packet, 3);
@ -3329,7 +3329,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
if (!sm_conn) break;
// delete stored bonding on disconnect with authentication failure in ph0
if (sm_conn->sm_role == 0
if (sm_conn->sm_role == 0
&& sm_conn->sm_engine_state == SM_INITIATOR_PH0_W4_CONNECTION_ENCRYPTED
&& packet[2] == ERROR_CODE_AUTHENTICATION_FAILURE){
le_device_db_remove(sm_conn->sm_le_db_index);
@ -3338,7 +3338,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
sm_conn->sm_engine_state = SM_GENERAL_IDLE;
sm_conn->sm_handle = 0;
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_encrypt)){
sm_handle_encryption_result(&packet[6]);
@ -3355,8 +3355,9 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
le_device_db_set_local_bd_addr(addr);
}
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_commands)){
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(USE_MICRO_ECC_FOR_ECDH)
#if defined(ENABLE_LE_SECURE_CONNECTIONS) && !defined(USE_SOFTWARE_ECDH_IMPLEMENTATION)
if ((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+34] & 0x06) != 0x06){
// mbedTLS can also be used if already available (and malloc is supported)
log_error("LE Secure Connections enabled, but HCI Controller doesn't support it. Please add USE_MICRO_ECC_FOR_ECDH to btstack_config.h");
}
#endif
@ -3387,7 +3388,7 @@ static int sm_just_works_or_numeric_comparison(stk_generation_method_t method){
case NK_BOTH_INPUT:
return 1;
default:
return 0;
return 0;
}
}
// responder
@ -3397,7 +3398,7 @@ static int sm_passkey_used(stk_generation_method_t method){
case PK_RESP_INPUT:
return 1;
default:
return 0;
return 0;
}
}
#endif
@ -3482,7 +3483,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
}
switch (sm_conn->sm_engine_state){
// a sm timeout requries a new physical connection
case SM_GENERAL_TIMEOUT:
return;
@ -3506,7 +3507,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
log_info("sm: Setting up previous ltk/ediv/rand for device index %u", sm_conn->sm_le_db_index);
sm_conn->sm_engine_state = SM_INITIATOR_PH0_HAS_LTK;
} else {
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
}
break;
}
@ -3536,26 +3537,26 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
#ifdef ENABLE_LE_SECURE_CONNECTIONS
if (setup->sm_use_secure_connections){
// SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
// SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
if (setup->sm_stk_generation_method == JUST_WORKS){
sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
sm_trigger_user_response(sm_conn);
if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
}
}
} else {
sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
}
break;
}
#endif
}
#endif
sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
sm_trigger_user_response(sm_conn);
// response_idle == nothing <--> sm_trigger_user_response() did not require response
if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
sm_conn->sm_engine_state = SM_PH2_C1_GET_RANDOM_A;
}
break;
}
break;
case SM_INITIATOR_PH2_W4_PAIRING_CONFIRM:
if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
@ -3583,7 +3584,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
#ifdef ENABLE_LE_PERIPHERAL
// Responder
case SM_RESPONDER_IDLE:
case SM_RESPONDER_SEND_SECURITY_REQUEST:
case SM_RESPONDER_SEND_SECURITY_REQUEST:
case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
sm_pdu_received_in_wrong_state(sm_conn);
@ -3637,9 +3638,9 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
break;
}
#ifndef USE_MICRO_ECC_FOR_ECDH
// start calculating dhkey
setup->sm_state_vars |= SM_STATE_VAR_DHKEY_NEEDED;
#ifndef USE_SOFTWARE_ECDH_IMPLEMENTATION
// ask controller to calculate dhkey
setup->sm_state_vars |= SM_STATE_VAR_DHKEY_NEEDED;
#endif
if (IS_RESPONDER(sm_conn->sm_role)){
@ -3668,7 +3669,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
case OOB:
// TODO: implement SC OOB
break;
}
}
}
break;
@ -3687,7 +3688,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
// still waiting for passkey
sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
break;
}
}
}
sm_sc_start_calculating_local_confirm(sm_conn);
} else {
@ -3695,10 +3696,10 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
if (sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method)){
sm_conn->sm_engine_state = SM_SC_W2_GET_RANDOM_A;
} else {
sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
}
}
break;
break;
case SM_SC_W4_PAIRING_RANDOM:
if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
@ -3709,7 +3710,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
// received random value
reverse_128(&packet[1], setup->sm_peer_nonce);
// validate confirm value if Cb = f4(Pkb, Pka, Nb, z)
// validate confirm value if Cb = f4(Pkb, Pka, Nb, z)
// only check for JUST WORK/NC in initiator role AND passkey entry
if (sm_conn->sm_role || sm_passkey_used(setup->sm_stk_generation_method)) {
sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
@ -3810,7 +3811,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
setup->sm_peer_addr_type = packet[1];
reverse_bd_addr(&packet[2], setup->sm_peer_address);
reverse_bd_addr(&packet[2], setup->sm_peer_address);
break;
case SM_CODE_SIGNING_INFORMATION:
@ -3821,8 +3822,8 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
// Unexpected PDU
log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
break;
}
// done with key distribution?
}
// done with key distribution?
if (sm_key_distribution_all_received(sm_conn)){
sm_key_distribution_handle_all_received(sm_conn);
@ -3831,14 +3832,14 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
if (setup->sm_use_secure_connections && (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION)){
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_H6_ILK;
} else {
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
sm_done_for_handle(sm_conn->sm_handle);
}
} else {
if (setup->sm_use_secure_connections){
sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
} else {
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
}
}
}
@ -3925,7 +3926,7 @@ void sm_init(void){
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
@ -3936,7 +3937,7 @@ void sm_init(void){
sm_address_resolution_ah_calculation_active = 0;
sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
sm_address_resolution_general_queue = NULL;
gap_random_adress_update_period = 15 * 60 * 1000L;
sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
@ -4007,7 +4008,7 @@ void sm_allow_ltk_reconstruction_without_le_device_db_entry(int 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;
return &hci_con->sm_connection;
return &hci_con->sm_connection;
}
// @returns 0 if not encrypted, 7-16 otherwise
@ -4045,7 +4046,7 @@ static void sm_send_security_request_for_connection(sm_connection_t * sm_conn){
}
}
/**
/**
* @brief Trigger Security Request
*/
void sm_send_security_request(hci_con_handle_t con_handle){
@ -4069,7 +4070,7 @@ void sm_request_pairing(hci_con_handle_t con_handle){
if (sm_conn->sm_engine_state == SM_INITIATOR_CONNECTED){
switch (sm_conn->sm_irk_lookup_state){
case IRK_LOOKUP_FAILED:
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
break;
case IRK_LOOKUP_SUCCEEDED:
le_device_db_encryption_get(sm_conn->sm_le_db_index, &ediv, NULL, ltk, NULL, NULL, NULL);
@ -4077,7 +4078,7 @@ void sm_request_pairing(hci_con_handle_t con_handle){
log_info("sm: Setting up previous ltk/ediv/rand for device index %u", sm_conn->sm_le_db_index);
sm_conn->sm_engine_state = SM_INITIATOR_PH0_HAS_LTK;
} else {
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
}
break;
default:
@ -4119,7 +4120,7 @@ void sm_bonding_decline(hci_con_handle_t con_handle){
case PK_INIT_INPUT:
case OK_BOTH_INPUT:
sm_pairing_error(sm_conn, SM_GENERAL_SEND_PAIRING_FAILED);
break;
break;
case NK_BOTH_INPUT:
sm_pairing_error(sm_conn, SM_REASON_NUMERIC_COMPARISON_FAILED);
break;
@ -4259,4 +4260,3 @@ void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, u
direct_address_typ, direct_address, channel_map, filter_policy);
}
#endif