diff --git a/ble/att_server.c b/ble/att_server.c index d4f701e6d..d1d32c745 100644 --- a/ble/att_server.c +++ b/ble/att_server.c @@ -292,7 +292,7 @@ static void att_run(void){ switch (sm_authorization_state(att_client_addr_type, att_client_address)){ case AUTHORIZATION_UNKNOWN: l2cap_release_packet_buffer(); - sm_request_authorization(att_client_addr_type, att_client_address); + sm_request_pairing(att_client_addr_type, att_client_address); return; case AUTHORIZATION_PENDING: l2cap_release_packet_buffer(); diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 52aed181a..3ee3154af 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -735,9 +735,8 @@ static void gatt_client_run(void){ switch (peripheral->gatt_client_state){ case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE: case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR: - - if (peripheral->attribute_length < peripheral_mtu(peripheral) - 3) break; - printf(".. ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH %u > %u\n", peripheral->attribute_length, peripheral_mtu(peripheral)); + if (peripheral->attribute_length <= peripheral_mtu(peripheral) - 3) break; + log_error("gatt_client_run: value len %u > MTU %u - 3\n", peripheral->attribute_length, peripheral_mtu(peripheral)); gatt_client_handle_transaction_complete(peripheral); emit_gatt_complete_event(peripheral, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH); return; @@ -1418,7 +1417,7 @@ le_command_status_t gatt_client_write_value_of_characteristic_without_response(u if (!peripheral) return (le_command_status_t) BTSTACK_MEMORY_ALLOC_FAILED; if (!is_ready(peripheral)) return BLE_PERIPHERAL_IN_WRONG_STATE; - if (value_length >= peripheral_mtu(peripheral) - 3) return BLE_VALUE_TOO_LONG; + if (value_length > peripheral_mtu(peripheral) - 3) return BLE_VALUE_TOO_LONG; if (!l2cap_can_send_fixed_channel_packet_now(peripheral->handle)) return BLE_PERIPHERAL_BUSY; peripheral->subclient_id = gatt_client_id; diff --git a/ble/sm.c b/ble/sm.c index 25b497dac..8ce2cf93c 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -964,6 +964,72 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event) } } +static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){ + int le_db_index = -1; + if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION){ + // lookup device based on IRK + int i; + for (i=0; i < le_device_db_count(); i++){ + sm_key_t irk; + bd_addr_t address; + int address_type; + le_device_db_info(i, &address_type, address, irk); + if (memcmp(irk, setup->sm_peer_irk, 16) == 0){ + log_info("sm: device found for IRK, updating"); + le_db_index = i; + break; + } + } + // if not found, add to db + if (le_db_index < 0) { + le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk); + } + } + + // if no IRK available, lookup via public address if possible + log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address)); + if (le_db_index < 0 && setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC){ + int i; + for (i=0; i < le_device_db_count(); i++){ + bd_addr_t address; + int address_type; + le_device_db_info(i, &address_type, address, NULL); + log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address)); + if (address_type == BD_ADDR_TYPE_LE_PUBLIC && memcmp(address, setup->sm_peer_address, 6) == 0){ + log_info("sm: device found for public address, updating"); + le_db_index = i; + break; + } + } + // if not found, add to db + if (le_db_index < 0) { + le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk); + } + } + + if (le_db_index >= 0){ + le_device_db_local_counter_set(le_db_index, 0); + + // store CSRK + if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ + log_info("sm: store remote CSRK"); + le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk); + le_device_db_remote_counter_set(le_db_index, 0); + } + + // store encryption information + 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, authenticatd %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, + sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED); + } + } + + // keep le_db_index + sm_conn->sm_le_db_index = le_db_index; +} + static void sm_run(void){ linked_list_iterator_t it; @@ -1457,8 +1523,14 @@ static void sm_run(void){ // keys are sent if (connection->sm_role){ - // slave -> receive master keys - connection->sm_engine_state = SM_PH3_RECEIVE_KEYS; + // 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; + 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; @@ -1621,7 +1693,19 @@ static void sm_handle_encryption_result(uint8_t * data){ case SM_PH3_CSRK_W4_ENC: swap128(data, setup->sm_local_csrk); log_key("csrk", setup->sm_local_csrk); - connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS; + if (setup->sm_key_distribution_send_set){ + connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS; + } else { + // no keys to send, just continue + if (connection->sm_role){ + // slave -> receive master keys + connection->sm_engine_state = SM_PH3_RECEIVE_KEYS; + } else { + // master -> all done + connection->sm_engine_state = SM_INITIATOR_CONNECTED; + sm_done_for_handle(connection->sm_handle); + } + } return; case SM_RESPONDER_PH4_LTK_W4_ENC: swap128(data, setup->sm_ltk); @@ -1835,7 +1919,13 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint sm_conn->sm_engine_state = SM_PH3_GET_RANDOM; } else { // master - sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS; + 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; + } else { + sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS; + } } break; default: @@ -2131,69 +2221,8 @@ static void sm_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pac } // done with key distribution? if (sm_key_distribution_all_received(sm_conn)){ - int le_db_index = -1; - if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION){ - // lookup device based on IRK - int i; - for (i=0; i < le_device_db_count(); i++){ - sm_key_t irk; - bd_addr_t address; - int address_type; - le_device_db_info(i, &address_type, address, irk); - if (memcmp(irk, setup->sm_peer_irk, 16) == 0){ - log_info("sm: device found for IRK, updating"); - le_db_index = i; - break; - } - } - // if not found, add to db - if (le_db_index < 0) { - le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk); - } - } - // if no IRK available, lookup via public address if possible - log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address)); - if (le_db_index < 0 && setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC){ - int i; - for (i=0; i < le_device_db_count(); i++){ - bd_addr_t address; - int address_type; - le_device_db_info(i, &address_type, address, NULL); - log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address)); - if (address_type == BD_ADDR_TYPE_LE_PUBLIC && memcmp(address, setup->sm_peer_address, 6) == 0){ - log_info("sm: device found for public address, updating"); - le_db_index = i; - break; - } - } - // if not found, add to db - if (le_db_index < 0) { - le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk); - } - } - - if (le_db_index >= 0){ - le_device_db_local_counter_set(le_db_index, 0); - - // store CSRK - if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ - log_info("sm: store remote CSRK"); - le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk); - le_device_db_remote_counter_set(le_db_index, 0); - } - - // store encryption information - 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, authenticatd %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, - sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED); - } - } - - // keep le_db_index - sm_conn->sm_le_db_index = le_db_index; + sm_key_distribution_handle_all_received(sm_conn); if (sm_conn->sm_role){ sm_conn->sm_engine_state = SM_RESPONDER_IDLE; @@ -2257,23 +2286,6 @@ void sm_test_set_irk(sm_key_t irk){ sm_persistent_irk_ready = 1; } - -/** - * @brief Trigger Security Request - */ -void sm_send_security_request(uint16_t handle){ - sm_connection_t * sm_conn = sm_get_connection_for_handle(handle); - switch (sm_conn->sm_engine_state){ - case SM_GENERAL_IDLE: - case SM_RESPONDER_IDLE: - sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST; - sm_run(); - break; - default: - break; - } -} - void sm_init(void){ // set some (BTstack default) ER and IR int i; @@ -2344,16 +2356,35 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres return sm_conn->sm_connection_authorization_state; } -// request authorization -void sm_request_authorization(uint8_t addr_type, bd_addr_t address){ +static void sm_send_security_request_for_connection(sm_connection_t * sm_conn){ + switch (sm_conn->sm_engine_state){ + case SM_GENERAL_IDLE: + case SM_RESPONDER_IDLE: + sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST; + sm_run(); + break; + default: + break; + } +} + +/** + * @brief Trigger Security Request + */ +void sm_send_security_request(uint16_t handle){ + sm_connection_t * sm_conn = sm_get_connection_for_handle(handle); + if (!sm_conn) return; + sm_send_security_request_for_connection(sm_conn); +} + +// request pairing +void sm_request_pairing(uint8_t addr_type, bd_addr_t address){ sm_connection_t * sm_conn = sm_get_connection(addr_type, address); if (!sm_conn) return; // wrong connection - log_info("sm_request_authorization in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state); + log_info("sm_request_pairing in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state); if (sm_conn->sm_role){ - // code has no effect so far - what's the difference between sm_send_security_request and this in slave role - sm_conn->sm_connection_authorization_state = AUTHORIZATION_PENDING; - sm_notify_client(SM_AUTHORIZATION_REQUEST, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, 0, 0); + sm_send_security_request_for_connection(sm_conn); } else { // used as a trigger to start central/master/initiator security procedures uint16_t ediv; diff --git a/ble/sm.h b/ble/sm.h index 49cb5641b..0e45c2fd5 100644 --- a/ble/sm.h +++ b/ble/sm.h @@ -242,7 +242,7 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres * @brief Used by att_server.c to request user authorization. * @param addr_type and address */ -void sm_request_authorization(uint8_t addr_type, bd_addr_t address); +void sm_request_pairing(uint8_t addr_type, bd_addr_t address); /** * @brief Report user authorization decline. diff --git a/ble/sm_minimal.c b/ble/sm_minimal.c index 72e3f0b5b..d56e7b7b9 100644 --- a/ble/sm_minimal.c +++ b/ble/sm_minimal.c @@ -88,8 +88,8 @@ authorization_state_t sm_authorization_state(uint8_t addr_type, bd_addr_t addres return AUTHORIZATION_DECLINED; } -// request authorization -void sm_request_authorization(uint8_t addr_type, bd_addr_t address){} +// request pairing +void sm_request_pairing(uint8_t addr_type, bd_addr_t address){} // called by client app on authorization request void sm_authorization_decline(uint8_t addr_type, bd_addr_t address){} diff --git a/test/Makefile b/test/Makefile index 2625ce2c6..cbeaab0fc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -6,6 +6,7 @@ SUBDIRS = \ ble_client \ des_iterator \ gatt_client \ + hfp \ linked_list \ remote_device_db \ sdp_client \ diff --git a/test/btstack-config.h b/test/btstack-config.h index 571495feb..88454e68f 100644 --- a/test/btstack-config.h +++ b/test/btstack-config.h @@ -10,6 +10,7 @@ #define ENABLE_LOG_DEBUG #define ENABLE_LOG_INFO #define ENABLE_LOG_ERROR +#define HAVE_HCI_DUMP #define HAVE_SDP_EXTRA_QUERIES #define USE_POSIX_RUN_LOOP @@ -32,6 +33,13 @@ #define MAX_NO_WHITELIST_ENTRIES 1 #define HAVE_MALLOC +#if 0 // DeLock 4.0 Dongle (Broadcom BCM20702A0) #define USB_VENDOR_ID 0x0a5c #define USB_PRODUCT_ID 0x21e8 + +#else +// Generic CSR 4.0 Dongle +// #define USB_VENDOR_ID 0x0a12 +// #define USB_PRODUCT_ID 0x0001 +#endif diff --git a/test/hfp/Makefile b/test/hfp/Makefile index da3c20737..fb64e2ac1 100644 --- a/test/hfp/Makefile +++ b/test/hfp/Makefile @@ -53,3 +53,7 @@ hfp_ag_parser_test: ${COMMON_OBJ} hfp_ag.o hfp.o hfp_ag_parser_test.c hfp_hf_parser_test: ${COMMON_OBJ} hfp_hf.o hfp.o hfp_hf_parser_test.c ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ + +test: all + ./hfp_ag_parser_test + ./hfp_hf_parser_test diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index b15ac065c..af6da30f9 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -77,6 +77,7 @@ typedef enum { CENTRAL_W4_NAME_VALUE, CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE, CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE, + CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE } central_state_t; typedef struct advertising_report { @@ -99,7 +100,8 @@ static int gap_connectable = 0; static char * sm_io_capabilities = NULL; static int sm_mitm_protection = 0; static int sm_have_oob_data = 0; -static uint8_t * sm_oob_data = (uint8_t *) "0123456789012345"; // = { 0x30...0x39, 0x30..0x35} +static uint8_t * sm_oob_data_A = (uint8_t *) "0123456789012345"; // = { 0x30...0x39, 0x30..0x35} +static uint8_t * sm_oob_data_B = (uint8_t *) "3333333333333333"; // = { 0x30...0x39, 0x30..0x35} static int sm_min_key_size = 7; static uint8_t pts_privacy_flag; @@ -118,10 +120,17 @@ static int current_pts_address_type; static int reconnection_address_set = 0; static bd_addr_t our_private_address; +static uint16_t pts_signed_write_characteristic_uuid = 0xb00d; +static uint16_t pts_signed_write_characteristic_handle = 0x0100; +static uint8_t signed_write_value[] = { 0x12 }; +static int le_device_db_index; +static sm_key_t signing_csrk; + static central_state_t central_state = CENTRAL_IDLE; static le_characteristic_t gap_name_characteristic; static le_characteristic_t gap_reconnection_address_characteristic; static le_characteristic_t gap_peripheral_privacy_flag_characteristic; +static le_characteristic_t signed_write_characteristic; static void show_usage(); /// @@ -296,10 +305,11 @@ void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, break; case SM_IDENTITY_RESOLVING_SUCCEEDED: - // skip already detected pts - if (memcmp( ((sm_event_t*) packet)->address, current_pts_address, 6) == 0) break; memcpy(current_pts_address, ((sm_event_t*) packet)->address, 6); current_pts_address_type = ((sm_event_t*) packet)->addr_type; + le_device_db_index = ((sm_event_t*) packet)->le_device_db_index; + // skip already detected pts + if (memcmp( ((sm_event_t*) packet)->address, current_pts_address, 6) == 0) break; printf("Address resolving succeeded: resolvable address %s, addr type %u\n", bd_addr_to_str(current_pts_address), current_pts_address_type); break; @@ -368,15 +378,15 @@ void handle_gatt_client_event(le_event_t * event){ printf("Peripheral Privacy Flag set to TRUE\n"); gatt_client_write_value_of_characteristic(gc_id, handle, gap_peripheral_privacy_flag_characteristic.value_handle, 1, &pts_privacy_flag); break; - case 2: - printf("Signed write on Peripheral Privacy Flag to TRUE\n"); - pts_privacy_flag = 1; - gatt_client_signed_write_without_response(gc_id, handle, gap_peripheral_privacy_flag_characteristic.value_handle, 1, &pts_privacy_flag); - break; default: break; } break; + case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE: + printf("Signed write on Characteristic with UUID 0x%04x\n", pts_signed_write_characteristic_uuid); + gatt_client_signed_write_without_response(gc_id, handle, signed_write_characteristic.value_handle, sizeof(signed_write_value), signed_write_value); + break; + default: break; } @@ -394,6 +404,11 @@ void handle_gatt_client_event(le_event_t * event){ case CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE: gap_peripheral_privacy_flag_characteristic = ((le_characteristic_event_t *) event)->characteristic; printf("GAP Peripheral Privacy Flag Characteristic found, value handle: 0x04%x\n", gap_peripheral_privacy_flag_characteristic.value_handle); + break; + case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE: + signed_write_characteristic = ((le_characteristic_event_t *) event)->characteristic; + printf("Characteristic for Signed Write found, value handle: 0x%04x\n", signed_write_characteristic.value_handle); + break; default: break; } @@ -418,8 +433,19 @@ void show_usage(void){ printf("IUT: addr type %u, addr %s\n", iut_address_type, bd_addr_to_str(iut_address)); printf("--------------------------\n"); printf("GAP: connectable %u, bondable %u\n", gap_connectable, gap_bondable); - printf("SM: %s, MITM protection %u, OOB data %u, key range [%u..16]\n", - sm_io_capabilities, sm_mitm_protection, sm_have_oob_data, sm_min_key_size); + printf("SM: %s, MITM protection %u, key range [%u..16], OOB data: ", + sm_io_capabilities, sm_mitm_protection, sm_min_key_size); + switch (sm_have_oob_data){ + case 1: + printf_hexdump(sm_oob_data_A, 16); + break; + case 2: + printf_hexdump(sm_oob_data_B, 16); + break; + default: + printf ("None\n"); + break; + } printf("Privacy %u\n", gap_privacy); printf("Device name: %s\n", gap_device_name); // printf("Value Handle: %x\n", value_handle); @@ -440,7 +466,8 @@ void show_usage(void){ printf("t - terminate connection, stop connecting\n"); printf("p - auto connect to PTS\n"); printf("P - direct connect to PTS\n"); - printf("w - signed write on Privacy Flag\n"); + printf("w - signed write on characteristic with UUID %04x\n", pts_signed_write_characteristic_uuid); + printf("W - signed write on attribute with handle 0x%04x and value 0x12\n", pts_signed_write_characteristic_handle); printf("z - Update L2CAP Connection Parameters\n"); printf("---\n"); printf("4 - IO_CAPABILITY_DISPLAY_ONLY\n"); @@ -449,6 +476,8 @@ void show_usage(void){ printf("7 - IO_CAPABILITY_KEYBOARD_ONLY\n"); printf("8 - IO_CAPABILITY_KEYBOARD_DISPLAY\n"); printf("m/M - MITM protection off\n"); + printf("x/X - encryption key range [7..16]/[16..16]\n"); + printf("y/Y - OOB data off/on/toggle A/B\n"); printf("---\n"); printf("Ctrl-c - exit\n"); printf("---\n"); @@ -466,20 +495,36 @@ void update_auth_req(void){ sm_set_authentication_requirements(auth_req); } +static void att_signed_write_handle_cmac_result(uint8_t hash[8]){ + int value_length = sizeof(signed_write_value); + l2cap_reserve_packet_buffer(); + uint8_t * request = l2cap_get_outgoing_buffer(); + request[0] = ATT_SIGNED_WRITE_COMMAND; + bt_store_16(request, 1, pts_signed_write_characteristic_handle); + memcpy(&request[3], signed_write_value, value_length); + bt_store_32(request, 3 + value_length, 0); + swap64(hash, &request[3 + value_length + 4]); + l2cap_send_prepared_connectionless(handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12); +} + int stdin_process(struct data_source *ds){ char buffer; read(ds->fd, &buffer, 1); int res; + // passkey input if (ui_digits_for_passkey){ - if (buffer < '0' || buffer > '9') return 0; + if (buffer < '0' || buffer > '9') { + printf("stdinprocess: invalid input 0x%02x\n", buffer); + return 0; + } printf("%c", buffer); fflush(stdout); ui_passkey = ui_passkey * 10 + buffer - '0'; ui_digits_for_passkey--; if (ui_digits_for_passkey == 0){ - printf("\nSending Passkey '%06x'\n", ui_passkey); + printf("\nSending Passkey %u (0x%x)\n", ui_passkey, ui_passkey); sm_passkey_input(peer_addr_type, peer_address, ui_passkey); } return 0; @@ -537,16 +582,18 @@ int stdin_process(struct data_source *ds){ show_usage(); break; case 'b': - sm_request_authorization(current_pts_address_type, current_pts_address); + sm_request_pairing(current_pts_address_type, current_pts_address); break; case 'c': gap_connectable = 0; update_advertisment_params(); + hci_connectable_control(gap_connectable); show_usage(); break; case 'C': gap_connectable = 1; update_advertisment_params(); + hci_connectable_control(gap_connectable); show_usage(); break; case 'd': @@ -616,8 +663,35 @@ int stdin_process(struct data_source *ds){ break; case 'w': pts_privacy_flag = 2; - central_state = CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE; - gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_PERIPHERAL_PRIVACY_FLAG); + central_state = CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE; + gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, pts_signed_write_characteristic_uuid); + break; + case 'W': + // fetch csrk + le_device_db_csrk_get(le_device_db_index, signing_csrk); + // calc signature + sm_cmac_start(signing_csrk, ATT_SIGNED_WRITE_COMMAND, pts_signed_write_characteristic_handle, sizeof(signed_write_value), signed_write_value, 0, att_signed_write_handle_cmac_result); + break; + case 'x': + sm_min_key_size = 7; + sm_set_encryption_key_size_range(7, 16); + show_usage(); + break; + case 'X': + sm_min_key_size = 16; + sm_set_encryption_key_size_range(16, 16); + show_usage(); + break; case 'y': + sm_have_oob_data = 0; + show_usage(); + break; + case 'Y': + if (sm_have_oob_data){ + sm_have_oob_data = 3 - sm_have_oob_data; + } else { + sm_have_oob_data = 1; + } + show_usage(); break; case 'z': printf("Updating l2cap connection parameters\n"); @@ -632,12 +706,18 @@ int stdin_process(struct data_source *ds){ } static int get_oob_data_callback(uint8_t addres_type, bd_addr_t addr, uint8_t * oob_data){ - if(!sm_have_oob_data) return 0; - memcpy(oob_data, sm_oob_data, 16); - return 1; + switch(sm_have_oob_data){ + case 1: + memcpy(oob_data, sm_oob_data_A, 16); + return 1; + case 2: + memcpy(oob_data, sm_oob_data_B, 16); + return 1; + default: + return 0; + } } - // ATT Client Read Callback for Dynamic Data // - if buffer == NULL, don't copy data, just return size of value // - if buffer != NULL, copy data and return number bytes copied @@ -709,7 +789,7 @@ int btstack_main(int argc, const char * argv[]){ current_pts_address_type = public_pts_address_type; // classic discoverable / connectable - hci_connectable_control(1); + hci_connectable_control(0); hci_discoverable_control(1); // allow foor terminal input diff --git a/test/security_manager/mock.c b/test/security_manager/mock.c index fa9e8b418..407b858f2 100644 --- a/test/security_manager/mock.c +++ b/test/security_manager/mock.c @@ -33,6 +33,7 @@ uint8_t * mock_packet_buffer(void){ void mock_clear_packet_buffer(void){ packet_buffer_len = 0; + memset(packet_buffer, 0, sizeof(packet_buffer)); } static void dump_packet(int packet_type, uint8_t * buffer, uint16_t size){ diff --git a/test/security_manager/security_manager.c b/test/security_manager/security_manager.c index c18ac75e5..a6238b0ff 100644 --- a/test/security_manager/security_manager.c +++ b/test/security_manager/security_manager.c @@ -118,6 +118,49 @@ uint16_t mock_packet_buffer_len(void); void mock_clear_packet_buffer(void); +void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + uint16_t aHandle; + sm_event_t * sm_event; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (packet[0]) { + case SM_PASSKEY_INPUT_NUMBER: + // store peer address for input + sm_event = (sm_event_t *) packet; + printf("\nGAP Bonding %s (%u): Enter 6 digit passkey: '", bd_addr_to_str(sm_event->address), sm_event->addr_type); + fflush(stdout); + break; + + case SM_PASSKEY_DISPLAY_NUMBER: + sm_event = (sm_event_t *) packet; + printf("\nGAP Bonding %s (%u): Display Passkey '%06u\n", bd_addr_to_str(sm_event->address), sm_event->addr_type, sm_event->passkey); + break; + + case SM_PASSKEY_DISPLAY_CANCEL: + sm_event = (sm_event_t *) packet; + printf("\nGAP Bonding %s (%u): Display cancel\n", bd_addr_to_str(sm_event->address), sm_event->addr_type); + break; + + case SM_JUST_WORKS_REQUEST: + // auto-authorize connection if requested + sm_event = (sm_event_t *) packet; + sm_just_works_confirm(sm_event->addr_type, sm_event->address); + printf("Just Works request confirmed\n"); + break; + + case SM_AUTHORIZATION_REQUEST: + // auto-authorize connection if requested + sm_event = (sm_event_t *) packet; + sm_authorization_grant(sm_event->addr_type, sm_event->address); + break; + + default: + break; + } + } +} + + void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){ int i; for (i=0; i