diff --git a/example/Makefile.inc b/example/Makefile.inc index 833070f3d..63373f987 100644 --- a/example/Makefile.inc +++ b/example/Makefile.inc @@ -321,10 +321,10 @@ hog_mouse_demo: hog_mouse_demo.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SER hog_boot_host_demo: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} hog_boot_host_demo.c ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ -sm_pairing_peripheral: sm_pairing_peripheral.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} sm_pairing_peripheral.c +sm_pairing_peripheral: sm_pairing_peripheral.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${GATT_CLIENT_OBJ} sm_pairing_peripheral.c ${CC} $(filter-out sm_pairing_peripheral.h,$^) ${CFLAGS} ${LDFLAGS} -o $@ -sm_pairing_central: sm_pairing_central.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} sm_pairing_central.o +sm_pairing_central: sm_pairing_central.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${GATT_CLIENT_OBJ} sm_pairing_central.o ${CC} $(filter-out sm_pairing_central.h,$^) ${CFLAGS} ${LDFLAGS} -o $@ gatt_counter: gatt_counter.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${CLASSIC_OBJ} battery_service_server.o gatt_counter.c diff --git a/example/sm_pairing_central.c b/example/sm_pairing_central.c index 18b021a48..8bf0a6ace 100644 --- a/example/sm_pairing_central.c +++ b/example/sm_pairing_central.c @@ -98,12 +98,8 @@ static void sm_pairing_central_setup(void){ // setup ATT server att_server_init(profile_data, NULL, NULL); - /** - * Choose ONE of the following configurations - * Bonding is disabled to allow for repeated testing. It can be enabled by or'ing - * SM_AUTHREQ_BONDING to the authentication requirements like this: - * sm_set_authentication_requirements( X | SM_AUTHREQ_BONDING) - */ + // setup GATT Client + gatt_client_init(); // register handler hci_event_callback_registration.callback = &hci_packet_handler; @@ -112,6 +108,20 @@ static void sm_pairing_central_setup(void){ sm_event_callback_registration.callback = &sm_packet_handler; sm_add_event_handler(&sm_event_callback_registration); + + // Configuration + + // Enable mandatory authentication for GATT Client + // - if un-encrypted connections are not supported, e.g. when connecting to own device, this enforces authentication + // gatt_client_set_required_security_level(LEVEL_2); + + /** + * Choose ONE of the following configurations + * Bonding is disabled to allow for repeated testing. It can be enabled by or'ing + * SM_AUTHREQ_BONDING to the authentication requirements like this: + * sm_set_authentication_requirements( X | SM_AUTHREQ_BONDING) + */ + // LE Legacy Pairing, Just Works // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO); // sm_set_authentication_requirements(0); @@ -131,8 +141,8 @@ static void sm_pairing_central_setup(void){ // sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION); // LE Secure Connections, Numeric Comparison - sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO); - sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION); + // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO); + // sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION); // LE Secure Pairing, Passkey entry initiator (us) enters, responder displays // sm_set_io_capabilities(IO_CAPABILITY_KEYBOARD_ONLY); @@ -163,6 +173,7 @@ static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p if (packet_type != HCI_EVENT_PACKET) return; hci_con_handle_t con_handle; + uint8_t status; switch (hci_event_packet_get_type(packet)) { case BTSTACK_EVENT_STATE: @@ -193,13 +204,42 @@ static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break; con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); printf("Connection complete\n"); - // start pairing + + // for testing, choose one of the following actions + + // manually start pairing sm_request_pairing(con_handle); + + // gatt client request to authenticated characteristic in sm_pairing_peripheral (short cut, uses hard-coded value handle) + // gatt_client_read_value_of_characteristic_using_value_handle(&hci_packet_handler, con_handle, 0x0009); + + // general gatt client request to trigger mandatory authentication + // gatt_client_discover_primary_services(&hci_packet_handler, con_handle); break; case HCI_EVENT_ENCRYPTION_CHANGE: con_handle = hci_event_encryption_change_get_connection_handle(packet); printf("Connection encrypted: %u\n", hci_event_encryption_change_get_encryption_enabled(packet)); break; + case GATT_EVENT_QUERY_COMPLETE: + status = gatt_event_query_complete_get_att_status(packet); + switch (status){ + case ATT_ERROR_INSUFFICIENT_ENCRYPTION: + printf("GATT Query result: Insufficient Encryption\n"); + break; + case ATT_ERROR_INSUFFICIENT_AUTHENTICATION: + printf("GATT Query result: Insufficient Authentication\n"); + break; + case ATT_ERROR_BONDING_INFORMATION_MISSING: + printf("GATT Query result: Bonding Information Missing\n"); + break; + case ATT_ERROR_SUCCESS: + printf("GATT Query result: OK\n"); + break; + default: + printf("GATT Query result: 0x%02x\n", gatt_event_query_complete_get_att_status(packet)); + break; + } + break; default: break; } diff --git a/example/sm_pairing_central.gatt b/example/sm_pairing_central.gatt index fd063358c..e50e38a9e 100644 --- a/example/sm_pairing_central.gatt +++ b/example/sm_pairing_central.gatt @@ -1,6 +1,9 @@ PRIMARY_SERVICE, GAP_SERVICE CHARACTERISTIC, GAP_DEVICE_NAME, READ, "SM Pairing Central" +PRIMARY_SERVICE, GATT_SERVICE +CHARACTERISTIC, GATT_DATABASE_HASH, READ, + // Dummy Service PRIMARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB // Dummy Service, Characteristic, with read and notify + authentication diff --git a/example/sm_pairing_peripheral.c b/example/sm_pairing_peripheral.c index 28610b6a5..be92a2801 100644 --- a/example/sm_pairing_peripheral.c +++ b/example/sm_pairing_peripheral.c @@ -91,6 +91,36 @@ static void sm_peripheral_setup(void){ // setup SM: Display only sm_init(); + // setup ATT server + att_server_init(profile_data, NULL, NULL); + + // setup GATT Client + gatt_client_init(); + + // setup advertisements + uint16_t adv_int_min = 0x0030; + uint16_t adv_int_max = 0x0030; + uint8_t adv_type = 0; + bd_addr_t null_addr; + memset(null_addr, 0, 6); + gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); + gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data); + gap_advertisements_enable(1); + + // register for SM events + sm_event_callback_registration.callback = &packet_handler; + sm_add_event_handler(&sm_event_callback_registration); + + // register for ATT + att_server_register_packet_handler(packet_handler); + + + // Configuration + + // Enable mandatory authentication for GATT Client + // - if un-encrypted connections are not supported, e.g. when connecting to own device, this enforces authentication + // gatt_client_set_required_security_level(LEVEL_2); + /** * Choose ONE of the following configurations * Bonding is disabled to allow for repeated testing. It can be enabled by or'ing @@ -129,26 +159,6 @@ static void sm_peripheral_setup(void){ // sm_set_io_capabilities(IO_CAPABILITY_KEYBOARD_ONLY); // sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION); #endif - - // setup ATT server - att_server_init(profile_data, NULL, NULL); - - // setup advertisements - uint16_t adv_int_min = 0x0030; - uint16_t adv_int_max = 0x0030; - uint8_t adv_type = 0; - bd_addr_t null_addr; - memset(null_addr, 0, 6); - gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); - gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data); - gap_advertisements_enable(1); - - // register for SM events - sm_event_callback_registration.callback = &packet_handler; - sm_add_event_handler(&sm_event_callback_registration); - - // register for ATT - att_server_register_packet_handler(packet_handler); } /* LISTING_END */ @@ -170,16 +180,26 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack hci_con_handle_t con_handle; bd_addr_t addr; + uint8_t status; switch (hci_event_packet_get_type(packet)) { case HCI_EVENT_LE_META: switch (hci_event_le_meta_get_subevent_code(packet)) { case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: printf("Connection complete\n"); - // Uncomment the next lines to trigger explicit pairing on connect - // con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); - // sm_send_security_request(con_handle); + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); UNUSED(con_handle); + + // for testing, choose one of the following actions + + // manually start pairing + // sm_send_security_request(con_handle); + + // gatt client request to authenticated characteristic in sm_pairing_central (short cut, uses hard-coded value handle) + // gatt_client_read_value_of_characteristic_using_value_handle(&packet_handler, con_handle, 0x0009); + + // general gatt client request to trigger mandatory authentication + // gatt_client_discover_primary_services(&packet_handler, con_handle); break; default: break; @@ -249,6 +269,26 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack break; } break; + case GATT_EVENT_QUERY_COMPLETE: + status = gatt_event_query_complete_get_att_status(packet); + switch (status){ + case ATT_ERROR_INSUFFICIENT_ENCRYPTION: + printf("GATT Query result: Insufficient Encryption\n"); + break; + case ATT_ERROR_INSUFFICIENT_AUTHENTICATION: + printf("GATT Query result: Insufficient Authentication\n"); + break; + case ATT_ERROR_BONDING_INFORMATION_MISSING: + printf("GATT Query result: Bonding Information Missing\n"); + break; + case ATT_ERROR_SUCCESS: + printf("GATT Query result: OK\n"); + break; + default: + printf("GATT Query result: 0x%02x\n", gatt_event_query_complete_get_att_status(packet)); + break; + } + break; default: break; }