diff --git a/ble/sm.c b/ble/sm.c index 651dd61df..4ce23dd03 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -49,95 +49,6 @@ // SM internal types and globals // -typedef enum { - - // general states - SM_GENERAL_IDLE, - SM_GENERAL_SEND_PAIRING_FAILED, - SM_GENERAL_TIMEOUT, // no other security messages are exchanged - - // Phase 1: Pairing Feature Exchange - SM_PH1_W4_USER_RESPONSE, - - // Phase 2: Authenticating and Encrypting - - // get random number for use as TK Passkey if we show it - SM_PH2_GET_RANDOM_TK, - SM_PH2_W4_RANDOM_TK, - - // get local random number for confirm c1 - SM_PH2_C1_GET_RANDOM_A, - SM_PH2_C1_W4_RANDOM_A, - SM_PH2_C1_GET_RANDOM_B, - SM_PH2_C1_W4_RANDOM_B, - - // calculate confirm value for local side - SM_PH2_C1_GET_ENC_A, - SM_PH2_C1_W4_ENC_A, - SM_PH2_C1_GET_ENC_B, - SM_PH2_C1_W4_ENC_B, - - // calculate confirm value for remote side - SM_PH2_C1_GET_ENC_C, - SM_PH2_C1_W4_ENC_C, - SM_PH2_C1_GET_ENC_D, - SM_PH2_C1_W4_ENC_D, - - SM_PH2_C1_SEND_PAIRING_CONFIRM, - SM_PH2_SEND_PAIRING_RANDOM, - - // calc STK - SM_PH2_CALC_STK, - SM_PH2_W4_STK, - - SM_PH2_W4_CONNECTION_ENCRYPTED, - - // Phase 3: Transport Specific Key Distribution - - // calculate DHK, Y, EDIV, and LTK - SM_PH3_GET_RANDOM, - SM_PH3_W4_RANDOM, - SM_PH3_GET_DIV, - SM_PH3_W4_DIV, - SM_PH3_Y_GET_ENC, - SM_PH3_Y_W4_ENC, - SM_PH3_LTK_GET_ENC, - SM_PH3_LTK_W4_ENC, - SM_PH3_CSRK_GET_ENC, - SM_PH3_CSRK_W4_ENC, - - // exchange keys - SM_PH3_DISTRIBUTE_KEYS, - SM_PH3_RECEIVE_KEYS, - - // Phase 4: re-establish previously distributed LTK - SM_PH4_Y_GET_ENC, - SM_PH4_Y_W4_ENC, - SM_PH4_LTK_GET_ENC, - SM_PH4_LTK_W4_ENC, - SM_PH4_SEND_LTK, - - // RESPONDER ROLE - SM_RESPONDER_SEND_SECURITY_REQUEST, - SM_RESPONDER_SEND_LTK_REQUESTED_NEGATIVE_REPLY, - SM_RESPONDER_PH1_W4_PAIRING_REQUEST, - SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE, - SM_RESPONDER_PH1_W4_PAIRING_CONFIRM, - SM_RESPONDER_PH2_W4_PAIRING_RANDOM, - SM_RESPONDER_PH2_W4_LTK_REQUEST, - SM_RESPONDER_PH2_SEND_LTK_REPLY, - - // INITITIATOR ROLE - SM_INITIATOR_CONNECTED, - SM_INITIATOR_PH1_SEND_PAIRING_REQUEST, - SM_INITIATOR_PH1_W4_PAIRING_RESPONSE, - SM_INITIATOR_PH2_W4_PAIRING_CONFIRM, - SM_INITIATOR_PH2_W4_PAIRING_RANDOM, - SM_INITIATOR_PH3_SEND_START_ENCRYPTION, - SM_INITIATOR_PH3_XXXX, - -} security_manager_state_t; - typedef enum { DKG_W4_WORKING, DKG_CALC_IRK, @@ -166,12 +77,6 @@ typedef enum { CMAC_W4_MLAST } cmac_state_t; -typedef enum { - CSRK_LOOKUP_IDLE, - CSRK_LOOKUP_W4_READY, - CSRK_LOOKUP_STARTED, -} csrk_lookup_state_t; - typedef enum { JUST_WORKS, PK_RESP_INPUT, // Initiator displays PK, initiator inputs PK @@ -315,21 +220,6 @@ typedef struct sm_setup_context { bd_addr_t sm_peer_address; } sm_setup_context_t; -// connection info available as long as connection exists -typedef struct sm_connection { - uint16_t sm_handle; - uint8_t sm_role; // 0 - IamMaster, 1 = IamSlave - bd_addr_t sm_peer_address; - uint8_t sm_peer_addr_type; - security_manager_state_t sm_engine_state; - csrk_lookup_state_t sm_csrk_lookup_state; - uint8_t sm_connection_encrypted; - uint8_t sm_connection_authenticated; // [0..1] - uint8_t sm_actual_encryption_key_size; - authorization_state_t sm_connection_authorization_state; - timer_source_t sm_timeout; -} sm_connection_t; - // static sm_setup_context_t the_setup; static sm_setup_context_t * setup = &the_setup; diff --git a/ble/sm.h b/ble/sm.h index 71bcb0755..c2ac41418 100644 --- a/ble/sm.h +++ b/ble/sm.h @@ -71,13 +71,6 @@ typedef enum { IO_CAPABILITY_KEYBOARD_DISPLAY, // not used by secure simple pairing } io_capability_t; -// Authorization state -typedef enum { - AUTHORIZATION_UNKNOWN, - AUTHORIZATION_PENDING, - AUTHORIZATION_DECLINED, - AUTHORIZATION_GRANTED -} authorization_state_t; // Authentication requirement flags #define SM_AUTHREQ_NO_BONDING 0x00 diff --git a/ble/sm_minimal.c b/ble/sm_minimal.c index cd5a71a83..98e738f81 100644 --- a/ble/sm_minimal.c +++ b/ble/sm_minimal.c @@ -49,24 +49,14 @@ // SM internal types and globals // -typedef enum { - SM_STATE_IDLE, - SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY, - SM_STATE_SEND_PAIRING_FAILED, - SM_STATE_PAIRING_FAILED - -} security_manager_state_t; - static void sm_run(); // used to notify applicationss that user interaction is neccessary, see sm_notify_t below static btstack_packet_handler_t sm_client_packet_handler = NULL; -static security_manager_state_t sm_state_responding = SM_STATE_IDLE; +static security_manager_state_t sm_state_responding = SM_GENERAL_IDLE; static uint16_t sm_response_handle = 0; static uint8_t sm_pairing_failed_reason = 0; - - void sm_set_er(sm_key_t er){} void sm_set_ir(sm_key_t ir){} void sm_test_set_irk(sm_key_t irk){} @@ -118,7 +108,7 @@ void sm_register_packet_handler(btstack_packet_handler_t handler){ static void sm_pdu_received_in_wrong_state(){ sm_pairing_failed_reason = SM_REASON_UNSPECIFIED_REASON; - sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; + sm_state_responding = SM_GENERAL_SEND_PAIRING_FAILED; } static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ @@ -131,18 +121,18 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac } if (packet[0] == SM_CODE_PAIRING_FAILED){ - sm_state_responding = SM_STATE_PAIRING_FAILED; + sm_state_responding = SM_GENERAL_SEND_PAIRING_FAILED; return; } switch (sm_state_responding){ - case SM_STATE_IDLE: { + case SM_GENERAL_IDLE: { if (packet[0] != SM_CODE_PAIRING_REQUEST){ sm_pdu_received_in_wrong_state(); break;; } - sm_state_responding = SM_STATE_SEND_PAIRING_FAILED; + sm_state_responding = SM_GENERAL_SEND_PAIRING_FAILED; sm_pairing_failed_reason = SM_REASON_PAIRING_NOT_SUPPORTED; break; } @@ -169,12 +159,12 @@ static void sm_event_packet_handler (void * connection, uint8_t packet_type, uin return; } sm_response_handle = READ_BT_16(packet, 4); - sm_state_responding = SM_STATE_IDLE; + sm_state_responding = SM_GENERAL_IDLE; break; case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST: log_info("LTK Request: state %u", sm_state_responding); - sm_state_responding = SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY; + sm_state_responding = SM_RESPONDER_SEND_LTK_REQUESTED_NEGATIVE_REPLY; break; default: @@ -183,7 +173,7 @@ static void sm_event_packet_handler (void * connection, uint8_t packet_type, uin break; case HCI_EVENT_DISCONNECTION_COMPLETE: - sm_state_responding = SM_STATE_IDLE; + sm_state_responding = SM_GENERAL_IDLE; sm_response_handle = 0; break; } @@ -202,18 +192,18 @@ static void sm_run(void){ // assert that we can send either one switch (sm_state_responding){ - case SM_STATE_SEND_LTK_REQUESTED_NEGATIVE_REPLY: + case SM_RESPONDER_SEND_LTK_REQUESTED_NEGATIVE_REPLY: if (!hci_can_send_command_packet_now()) return; hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_response_handle); - sm_state_responding = SM_STATE_IDLE; + sm_state_responding = SM_GENERAL_IDLE; return; - case SM_STATE_SEND_PAIRING_FAILED: { + case SM_GENERAL_SEND_PAIRING_FAILED: { if (!l2cap_can_send_fixed_channel_packet_now(sm_response_handle)) return; uint8_t buffer[2]; buffer[0] = SM_CODE_PAIRING_FAILED; buffer[1] = sm_pairing_failed_reason; l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); - sm_state_responding = SM_STATE_IDLE; + sm_state_responding = SM_GENERAL_IDLE; break; } default: diff --git a/src/hci.h b/src/hci.h index e045fb19f..3ba83d4b0 100644 --- a/src/hci.h +++ b/src/hci.h @@ -335,6 +335,127 @@ typedef enum { LE_STOP_SCAN, } le_scanning_state_t; +// +// SM internal types and globals +// + +typedef enum { + + // general states + SM_GENERAL_IDLE, + SM_GENERAL_SEND_PAIRING_FAILED, + SM_GENERAL_TIMEOUT, // no other security messages are exchanged + + // Phase 1: Pairing Feature Exchange + SM_PH1_W4_USER_RESPONSE, + + // Phase 2: Authenticating and Encrypting + + // get random number for use as TK Passkey if we show it + SM_PH2_GET_RANDOM_TK, + SM_PH2_W4_RANDOM_TK, + + // get local random number for confirm c1 + SM_PH2_C1_GET_RANDOM_A, + SM_PH2_C1_W4_RANDOM_A, + SM_PH2_C1_GET_RANDOM_B, + SM_PH2_C1_W4_RANDOM_B, + + // calculate confirm value for local side + SM_PH2_C1_GET_ENC_A, + SM_PH2_C1_W4_ENC_A, + SM_PH2_C1_GET_ENC_B, + SM_PH2_C1_W4_ENC_B, + + // calculate confirm value for remote side + SM_PH2_C1_GET_ENC_C, + SM_PH2_C1_W4_ENC_C, + SM_PH2_C1_GET_ENC_D, + SM_PH2_C1_W4_ENC_D, + + SM_PH2_C1_SEND_PAIRING_CONFIRM, + SM_PH2_SEND_PAIRING_RANDOM, + + // calc STK + SM_PH2_CALC_STK, + SM_PH2_W4_STK, + + SM_PH2_W4_CONNECTION_ENCRYPTED, + + // Phase 3: Transport Specific Key Distribution + + // calculate DHK, Y, EDIV, and LTK + SM_PH3_GET_RANDOM, + SM_PH3_W4_RANDOM, + SM_PH3_GET_DIV, + SM_PH3_W4_DIV, + SM_PH3_Y_GET_ENC, + SM_PH3_Y_W4_ENC, + SM_PH3_LTK_GET_ENC, + SM_PH3_LTK_W4_ENC, + SM_PH3_CSRK_GET_ENC, + SM_PH3_CSRK_W4_ENC, + + // exchange keys + SM_PH3_DISTRIBUTE_KEYS, + SM_PH3_RECEIVE_KEYS, + + // Phase 4: re-establish previously distributed LTK + SM_PH4_Y_GET_ENC, + SM_PH4_Y_W4_ENC, + SM_PH4_LTK_GET_ENC, + SM_PH4_LTK_W4_ENC, + SM_PH4_SEND_LTK, + + // RESPONDER ROLE + SM_RESPONDER_SEND_SECURITY_REQUEST, + SM_RESPONDER_SEND_LTK_REQUESTED_NEGATIVE_REPLY, + SM_RESPONDER_PH1_W4_PAIRING_REQUEST, + SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE, + SM_RESPONDER_PH1_W4_PAIRING_CONFIRM, + SM_RESPONDER_PH2_W4_PAIRING_RANDOM, + SM_RESPONDER_PH2_W4_LTK_REQUEST, + SM_RESPONDER_PH2_SEND_LTK_REPLY, + + // INITITIATOR ROLE + SM_INITIATOR_CONNECTED, + SM_INITIATOR_PH1_SEND_PAIRING_REQUEST, + SM_INITIATOR_PH1_W4_PAIRING_RESPONSE, + SM_INITIATOR_PH2_W4_PAIRING_CONFIRM, + SM_INITIATOR_PH2_W4_PAIRING_RANDOM, + SM_INITIATOR_PH3_SEND_START_ENCRYPTION, + SM_INITIATOR_PH3_XXXX, + +} security_manager_state_t; + +typedef enum { + CSRK_LOOKUP_IDLE, + CSRK_LOOKUP_W4_READY, + CSRK_LOOKUP_STARTED, +} csrk_lookup_state_t; + +// Authorization state +typedef enum { + AUTHORIZATION_UNKNOWN, + AUTHORIZATION_PENDING, + AUTHORIZATION_DECLINED, + AUTHORIZATION_GRANTED +} authorization_state_t; + +// connection info available as long as connection exists +typedef struct sm_connection { + uint16_t sm_handle; + uint8_t sm_role; // 0 - IamMaster, 1 = IamSlave + bd_addr_t sm_peer_address; + uint8_t sm_peer_addr_type; + security_manager_state_t sm_engine_state; + csrk_lookup_state_t sm_csrk_lookup_state; + uint8_t sm_connection_encrypted; + uint8_t sm_connection_authenticated; // [0..1] + uint8_t sm_actual_encryption_key_size; + authorization_state_t sm_connection_authorization_state; + timer_source_t sm_timeout; +} sm_connection_t; typedef struct { // linked list - assert: first field @@ -389,6 +510,10 @@ typedef struct { uint16_t le_conn_latency; uint16_t le_supervision_timeout; uint16_t le_update_con_parameter_response; + + // LE Security Manager + // sm_connection_t sm_connection; + } hci_connection_t; /**