177ba3d3fSMatthias Ringwald /* 277ba3d3fSMatthias Ringwald * Copyright (C) 2017 BlueKitchen GmbH 377ba3d3fSMatthias Ringwald * 477ba3d3fSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 577ba3d3fSMatthias Ringwald * modification, are permitted provided that the following conditions 677ba3d3fSMatthias Ringwald * are met: 777ba3d3fSMatthias Ringwald * 877ba3d3fSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 977ba3d3fSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 1077ba3d3fSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1177ba3d3fSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 1277ba3d3fSMatthias Ringwald * documentation and/or other materials provided with the distribution. 1377ba3d3fSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 1477ba3d3fSMatthias Ringwald * contributors may be used to endorse or promote products derived 1577ba3d3fSMatthias Ringwald * from this software without specific prior written permission. 1677ba3d3fSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 1777ba3d3fSMatthias Ringwald * personal benefit and not for any commercial purpose or for 1877ba3d3fSMatthias Ringwald * monetary gain. 1977ba3d3fSMatthias Ringwald * 2077ba3d3fSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2177ba3d3fSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2277ba3d3fSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2377ba3d3fSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 2477ba3d3fSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2577ba3d3fSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2677ba3d3fSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2777ba3d3fSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2877ba3d3fSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2977ba3d3fSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3077ba3d3fSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3177ba3d3fSMatthias Ringwald * SUCH DAMAGE. 3277ba3d3fSMatthias Ringwald * 3377ba3d3fSMatthias Ringwald * Please inquire about commercial licensing options at 3477ba3d3fSMatthias Ringwald * [email protected] 3577ba3d3fSMatthias Ringwald * 3677ba3d3fSMatthias Ringwald */ 3777ba3d3fSMatthias Ringwald 382d4000d1SMatthias Ringwald #define BTSTACK_FILE__ "beacon.c" 3977ba3d3fSMatthias Ringwald 40f4854a5eSMatthias Ringwald #include "mesh/beacon.h" 41f4854a5eSMatthias Ringwald 42*3cfa4086SMatthias Ringwald #include <stdio.h> 4377ba3d3fSMatthias Ringwald #include <string.h> 4477ba3d3fSMatthias Ringwald 4577ba3d3fSMatthias Ringwald #include "ble/core.h" 4677ba3d3fSMatthias Ringwald #include "bluetooth.h" 4777ba3d3fSMatthias Ringwald #include "bluetooth_data_types.h" 4877ba3d3fSMatthias Ringwald #include "btstack_debug.h" 4977ba3d3fSMatthias Ringwald #include "btstack_event.h" 50f4854a5eSMatthias Ringwald #include "btstack_run_loop.h" 51f4854a5eSMatthias Ringwald #include "btstack_util.h" 5277ba3d3fSMatthias Ringwald #include "gap.h" 53f4854a5eSMatthias Ringwald 54f4854a5eSMatthias Ringwald #include "mesh/adv_bearer.h" 55f4854a5eSMatthias Ringwald #include "mesh/gatt_bearer.h" 56f4854a5eSMatthias Ringwald #include "mesh/mesh_foundation.h" 57f4854a5eSMatthias Ringwald #include "mesh/mesh_iv_index_seq_number.h" 58f4854a5eSMatthias Ringwald #include "mesh/mesh_keys.h" 5977ba3d3fSMatthias Ringwald 6077ba3d3fSMatthias Ringwald #define BEACON_TYPE_UNPROVISIONED_DEVICE 0 6177ba3d3fSMatthias Ringwald #define BEACON_TYPE_SECURE_NETWORK 1 6277ba3d3fSMatthias Ringwald 6377ba3d3fSMatthias Ringwald #define UNPROVISIONED_BEACON_INTERVAL_MS 5000 6477ba3d3fSMatthias Ringwald #define UNPROVISIONED_BEACON_LEN 23 6577ba3d3fSMatthias Ringwald 6677ba3d3fSMatthias Ringwald #define SECURE_NETWORK_BEACON_INTERVAL_MIN_MS 10000 6777ba3d3fSMatthias Ringwald #define SECURE_NETWORK_BEACON_INTERVAL_MAX_MS 600000 6877ba3d3fSMatthias Ringwald #define SECURE_NETWORK_BEACON_LEN 22 6977ba3d3fSMatthias Ringwald 7077ba3d3fSMatthias Ringwald // prototypes 7177ba3d3fSMatthias Ringwald static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts); 7277ba3d3fSMatthias Ringwald 73b3a527ecSMatthias Ringwald // bearers 74b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 75b3a527ecSMatthias Ringwald static hci_con_handle_t gatt_bearer_con_handle; 76b3a527ecSMatthias Ringwald #endif 77b3a527ecSMatthias Ringwald 7877ba3d3fSMatthias Ringwald // beacon 7977ba3d3fSMatthias Ringwald static uint8_t mesh_beacon_data[29]; 8077ba3d3fSMatthias Ringwald static uint8_t mesh_beacon_len; 8177ba3d3fSMatthias Ringwald static btstack_timer_source_t beacon_timer; 82e90005a5SMatthias Ringwald static int beacon_timer_active; 8377ba3d3fSMatthias Ringwald 8477ba3d3fSMatthias Ringwald // unprovisioned device beacon 85b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 8677ba3d3fSMatthias Ringwald static const uint8_t * beacon_device_uuid; 8777ba3d3fSMatthias Ringwald static uint16_t beacon_oob_information; 8877ba3d3fSMatthias Ringwald static uint32_t beacon_uri_hash; 8977ba3d3fSMatthias Ringwald static int beacon_send_device_beacon; 90b3a527ecSMatthias Ringwald #endif 9177ba3d3fSMatthias Ringwald 9277ba3d3fSMatthias Ringwald static btstack_packet_handler_t unprovisioned_device_beacon_handler; 9377ba3d3fSMatthias Ringwald 9477ba3d3fSMatthias Ringwald // secure network beacon 9577ba3d3fSMatthias Ringwald static btstack_crypto_aes128_cmac_t mesh_secure_network_beacon_cmac_request; 9677ba3d3fSMatthias Ringwald static uint8_t mesh_secure_network_beacon_auth_value[16]; 9777ba3d3fSMatthias Ringwald static btstack_packet_handler_t mesh_secure_network_beacon_handler; 9877ba3d3fSMatthias Ringwald static int mesh_secure_network_beacon_active; 996250fd6fSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 10077ba3d3fSMatthias Ringwald static uint8_t mesh_secure_network_beacon_validate_buffer[SECURE_NETWORK_BEACON_LEN]; 1016250fd6fSMatthias Ringwald #endif 10277ba3d3fSMatthias Ringwald 103b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 10477ba3d3fSMatthias Ringwald static void beacon_timer_handler(btstack_timer_source_t * ts){ 10577ba3d3fSMatthias Ringwald // restart timer 10677ba3d3fSMatthias Ringwald btstack_run_loop_set_timer(ts, UNPROVISIONED_BEACON_INTERVAL_MS); 10777ba3d3fSMatthias Ringwald btstack_run_loop_add_timer(ts); 108e90005a5SMatthias Ringwald beacon_timer_active = 1; 10977ba3d3fSMatthias Ringwald 11077ba3d3fSMatthias Ringwald // setup beacon 11177ba3d3fSMatthias Ringwald mesh_beacon_len = UNPROVISIONED_BEACON_LEN; 11277ba3d3fSMatthias Ringwald mesh_beacon_data[0] = BEACON_TYPE_UNPROVISIONED_DEVICE; 1136535961aSMatthias Ringwald (void)memcpy(&mesh_beacon_data[1], beacon_device_uuid, 16); 11477ba3d3fSMatthias Ringwald big_endian_store_16(mesh_beacon_data, 17, beacon_oob_information); 11577ba3d3fSMatthias Ringwald big_endian_store_32(mesh_beacon_data, 19, beacon_uri_hash); 11677ba3d3fSMatthias Ringwald 11777ba3d3fSMatthias Ringwald // request to send 11877ba3d3fSMatthias Ringwald beacon_send_device_beacon = 1; 1194662af4aSMatthias Ringwald adv_bearer_request_can_send_now_for_beacon(); 12077ba3d3fSMatthias Ringwald } 121b3a527ecSMatthias Ringwald #endif 12277ba3d3fSMatthias Ringwald 12377ba3d3fSMatthias Ringwald static void mesh_secure_network_beacon_auth_value_calculated(void * arg){ 1242fa98d7eSMatthias Ringwald mesh_subnet_t * mesh_subnet = (mesh_subnet_t *) arg; 12577ba3d3fSMatthias Ringwald 1266535961aSMatthias Ringwald (void)memcpy(&mesh_beacon_data[14], 1276535961aSMatthias Ringwald mesh_secure_network_beacon_auth_value, 8); 12877ba3d3fSMatthias Ringwald mesh_beacon_len = SECURE_NETWORK_BEACON_LEN; 12977ba3d3fSMatthias Ringwald 13077ba3d3fSMatthias Ringwald printf("Secure Network Beacon\n"); 13177ba3d3fSMatthias Ringwald printf("- "); 13277ba3d3fSMatthias Ringwald printf_hexdump(mesh_beacon_data, mesh_beacon_len); 13377ba3d3fSMatthias Ringwald 1342d63f17cSMatthias Ringwald mesh_secure_network_beacon_active = 0; 1352fa98d7eSMatthias Ringwald mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_AUTH_VALUE; 13677ba3d3fSMatthias Ringwald 13777ba3d3fSMatthias Ringwald mesh_secure_network_beacon_run(NULL); 13877ba3d3fSMatthias Ringwald } 13977ba3d3fSMatthias Ringwald 1402fa98d7eSMatthias Ringwald static uint8_t mesh_secure_network_beacon_get_flags(mesh_subnet_t * mesh_subnet){ 14177ba3d3fSMatthias Ringwald uint8_t mesh_flags = 0; 1422fa98d7eSMatthias Ringwald if (mesh_subnet->key_refresh != MESH_KEY_REFRESH_NOT_ACTIVE){ 14377ba3d3fSMatthias Ringwald mesh_flags |= 1; 14477ba3d3fSMatthias Ringwald } 1457d005332SMatthias Ringwald if (mesh_iv_update_active()){ 1467d005332SMatthias Ringwald mesh_flags |= 2; 1477d005332SMatthias Ringwald } 14877ba3d3fSMatthias Ringwald 14977ba3d3fSMatthias Ringwald return mesh_flags; 15077ba3d3fSMatthias Ringwald } 15177ba3d3fSMatthias Ringwald 1522fa98d7eSMatthias Ringwald static void mesh_secure_network_beacon_setup(mesh_subnet_t * mesh_subnet){ 15377ba3d3fSMatthias Ringwald mesh_beacon_data[0] = BEACON_TYPE_SECURE_NETWORK; 1542fa98d7eSMatthias Ringwald mesh_beacon_data[1] = mesh_secure_network_beacon_get_flags(mesh_subnet); 1552fa98d7eSMatthias Ringwald // TODO: pick correct key based on key refresh phase 1562fa98d7eSMatthias Ringwald 1576535961aSMatthias Ringwald (void)memcpy(&mesh_beacon_data[2], mesh_subnet->old_key->network_id, 8); 15877ba3d3fSMatthias Ringwald big_endian_store_32(mesh_beacon_data, 10, mesh_get_iv_index()); 159bdf219b2SMatthias Ringwald mesh_network_key_t * network_key = mesh_subnet_get_outgoing_network_key(mesh_subnet); 160bdf219b2SMatthias Ringwald btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, network_key->beacon_key, 13, 1612fa98d7eSMatthias Ringwald &mesh_beacon_data[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_auth_value_calculated, mesh_subnet); 16277ba3d3fSMatthias Ringwald } 16377ba3d3fSMatthias Ringwald 1642fa98d7eSMatthias Ringwald static void mesh_secure_network_beacon_update_interval(mesh_subnet_t * subnet){ 16577ba3d3fSMatthias Ringwald uint32_t min_observation_period_ms = 2 * subnet->beacon_interval_ms; 16677ba3d3fSMatthias Ringwald uint32_t actual_observation_period = btstack_time_delta(btstack_run_loop_get_time_ms(), subnet->beacon_observation_start_ms); 16777ba3d3fSMatthias Ringwald 16877ba3d3fSMatthias Ringwald // The Observation Period in seconds should typically be double the typical Beacon Interval. 16977ba3d3fSMatthias Ringwald if (actual_observation_period < min_observation_period_ms) return; 17077ba3d3fSMatthias Ringwald 17177ba3d3fSMatthias Ringwald // Expected Number of Beacons (1 beacon per 10 seconds) 17277ba3d3fSMatthias Ringwald uint16_t expected_number_of_beacons = actual_observation_period / SECURE_NETWORK_BEACON_INTERVAL_MIN_MS; 17377ba3d3fSMatthias Ringwald 17477ba3d3fSMatthias Ringwald // Beacon Interval = Observation Period * (Observed Number of Beacons + 1) / Expected Number of Beacons 17577ba3d3fSMatthias Ringwald uint32_t new_beacon_interval = actual_observation_period * (subnet->beacon_observation_counter + 1) / expected_number_of_beacons; 17677ba3d3fSMatthias Ringwald 17777ba3d3fSMatthias Ringwald if (new_beacon_interval > SECURE_NETWORK_BEACON_INTERVAL_MAX_MS){ 17877ba3d3fSMatthias Ringwald new_beacon_interval = SECURE_NETWORK_BEACON_INTERVAL_MAX_MS; 17977ba3d3fSMatthias Ringwald } 18077ba3d3fSMatthias Ringwald else if (new_beacon_interval < SECURE_NETWORK_BEACON_INTERVAL_MIN_MS){ 18177ba3d3fSMatthias Ringwald new_beacon_interval = SECURE_NETWORK_BEACON_INTERVAL_MAX_MS; 18277ba3d3fSMatthias Ringwald } 18377ba3d3fSMatthias Ringwald subnet->beacon_interval_ms = new_beacon_interval; 18477ba3d3fSMatthias Ringwald log_info("New beacon interval %u seconds", (int) (subnet->beacon_interval_ms / 1000)); 18577ba3d3fSMatthias Ringwald } 18677ba3d3fSMatthias Ringwald 18777ba3d3fSMatthias Ringwald static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts){ 18877ba3d3fSMatthias Ringwald UNUSED(ts); 18977ba3d3fSMatthias Ringwald 19077ba3d3fSMatthias Ringwald uint32_t next_timeout_ms = 0; 19177ba3d3fSMatthias Ringwald 19277ba3d3fSMatthias Ringwald // iterate over all networks 1932fa98d7eSMatthias Ringwald mesh_subnet_iterator_t it; 1942fa98d7eSMatthias Ringwald mesh_subnet_iterator_init(&it); 1952fa98d7eSMatthias Ringwald while (mesh_subnet_iterator_has_more(&it)){ 1962fa98d7eSMatthias Ringwald mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it); 19777ba3d3fSMatthias Ringwald switch (subnet->beacon_state){ 19877ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_W4_INTERVAL: 19977ba3d3fSMatthias Ringwald // update beacon interval 20077ba3d3fSMatthias Ringwald mesh_secure_network_beacon_update_interval(subnet); 20177ba3d3fSMatthias Ringwald 20215cb14e1SMatthias Ringwald if (mesh_foundation_beacon_get() == 0){ 20315cb14e1SMatthias Ringwald // beacon off, continue observing 20415cb14e1SMatthias Ringwald if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){ 20515cb14e1SMatthias Ringwald next_timeout_ms = subnet->beacon_interval_ms; 20615cb14e1SMatthias Ringwald } 20715cb14e1SMatthias Ringwald break; 20815cb14e1SMatthias Ringwald } 20915cb14e1SMatthias Ringwald 21077ba3d3fSMatthias Ringwald // send new beacon 21177ba3d3fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE; 21277ba3d3fSMatthias Ringwald 213cf373d3aSMatthias Ringwald /* fall through */ 21477ba3d3fSMatthias Ringwald 21577ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE: 21677ba3d3fSMatthias Ringwald if (mesh_secure_network_beacon_active){ 21777ba3d3fSMatthias Ringwald // just try again in 10 ms 21877ba3d3fSMatthias Ringwald next_timeout_ms = 10; 21977ba3d3fSMatthias Ringwald break; 22077ba3d3fSMatthias Ringwald } 22121ed246fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W4_AUTH_VALUE; 22277ba3d3fSMatthias Ringwald mesh_secure_network_beacon_active = 1; 22377ba3d3fSMatthias Ringwald mesh_secure_network_beacon_setup(subnet); 22477ba3d3fSMatthias Ringwald break; 22577ba3d3fSMatthias Ringwald 22677ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_AUTH_VALUE: 22777ba3d3fSMatthias Ringwald 22877ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 22977ba3d3fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV; 2304662af4aSMatthias Ringwald adv_bearer_request_can_send_now_for_beacon(); 23177ba3d3fSMatthias Ringwald break; 23277ba3d3fSMatthias Ringwald #endif 2338b0144a2SMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_ADV_SENT; 23477ba3d3fSMatthias Ringwald 235cf373d3aSMatthias Ringwald /* fall through */ 23677ba3d3fSMatthias Ringwald 23777ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_ADV_SENT: 23877ba3d3fSMatthias Ringwald 23977ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 2408b0144a2SMatthias Ringwald if (gatt_bearer_con_handle != HCI_CON_HANDLE_INVALID && mesh_foundation_gatt_proxy_get() != 0){ 24177ba3d3fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT; 2424662af4aSMatthias Ringwald gatt_bearer_request_can_send_now_for_beacon(); 2432931ab39SMatthias Ringwald break; 2442931ab39SMatthias Ringwald } 24577ba3d3fSMatthias Ringwald #endif 2468b0144a2SMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT; 24777ba3d3fSMatthias Ringwald 248cf373d3aSMatthias Ringwald /* fall through */ 24977ba3d3fSMatthias Ringwald 25077ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_GATT_SENT: 25177ba3d3fSMatthias Ringwald // now, start listening for beacons 25277ba3d3fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W4_INTERVAL; 25377ba3d3fSMatthias Ringwald // and request timeout 25477ba3d3fSMatthias Ringwald if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){ 25577ba3d3fSMatthias Ringwald next_timeout_ms = subnet->beacon_interval_ms; 25677ba3d3fSMatthias Ringwald } 25777ba3d3fSMatthias Ringwald break; 2582931ab39SMatthias Ringwald 25977ba3d3fSMatthias Ringwald default: 26077ba3d3fSMatthias Ringwald break; 26177ba3d3fSMatthias Ringwald } 26277ba3d3fSMatthias Ringwald } 26377ba3d3fSMatthias Ringwald 264e90005a5SMatthias Ringwald if (beacon_timer_active){ 265e90005a5SMatthias Ringwald btstack_run_loop_remove_timer(&beacon_timer); 266e90005a5SMatthias Ringwald beacon_timer_active = 0; 267e90005a5SMatthias Ringwald } 268e90005a5SMatthias Ringwald 26977ba3d3fSMatthias Ringwald // setup next run 27077ba3d3fSMatthias Ringwald if (next_timeout_ms == 0) return; 27177ba3d3fSMatthias Ringwald 2727c8ffd3dSMatthias Ringwald btstack_run_loop_set_timer(&beacon_timer, next_timeout_ms); 27377ba3d3fSMatthias Ringwald btstack_run_loop_set_timer_handler(&beacon_timer, mesh_secure_network_beacon_run); 27477ba3d3fSMatthias Ringwald btstack_run_loop_add_timer(&beacon_timer); 275e90005a5SMatthias Ringwald beacon_timer_active = 1; 27677ba3d3fSMatthias Ringwald } 27777ba3d3fSMatthias Ringwald 2786250fd6fSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 27977ba3d3fSMatthias Ringwald static void beacon_handle_secure_beacon_auth_value_calculated(void * arg){ 28077ba3d3fSMatthias Ringwald UNUSED(arg); 28177ba3d3fSMatthias Ringwald 28277ba3d3fSMatthias Ringwald // pass on, if auth value checks out 28377ba3d3fSMatthias Ringwald if (memcmp(&mesh_secure_network_beacon_validate_buffer[14], mesh_secure_network_beacon_auth_value, 8) == 0) { 28477ba3d3fSMatthias Ringwald if (mesh_secure_network_beacon_handler){ 28577ba3d3fSMatthias Ringwald (*mesh_secure_network_beacon_handler)(MESH_BEACON_PACKET, 0, mesh_secure_network_beacon_validate_buffer, SECURE_NETWORK_BEACON_LEN); 28677ba3d3fSMatthias Ringwald } 28777ba3d3fSMatthias Ringwald } 28877ba3d3fSMatthias Ringwald 28977ba3d3fSMatthias Ringwald // done 29077ba3d3fSMatthias Ringwald mesh_secure_network_beacon_active = 0; 29177ba3d3fSMatthias Ringwald mesh_secure_network_beacon_run(NULL); 29277ba3d3fSMatthias Ringwald } 29377ba3d3fSMatthias Ringwald 29477ba3d3fSMatthias Ringwald static void beacon_handle_secure_beacon(uint8_t * packet, uint16_t size){ 29577ba3d3fSMatthias Ringwald if (size != SECURE_NETWORK_BEACON_LEN) return; 29677ba3d3fSMatthias Ringwald 29789e0288aSMatthias Ringwald // lookup subnet and netkey by network id 29877ba3d3fSMatthias Ringwald uint8_t * beacon_network_id = &packet[2]; 2992fa98d7eSMatthias Ringwald mesh_subnet_iterator_t it; 3002fa98d7eSMatthias Ringwald mesh_subnet_iterator_init(&it); 3012fa98d7eSMatthias Ringwald mesh_subnet_t * subnet = NULL; 30289e0288aSMatthias Ringwald mesh_network_key_t * network_key = NULL; 3032fa98d7eSMatthias Ringwald while (mesh_subnet_iterator_has_more(&it)){ 3042fa98d7eSMatthias Ringwald mesh_subnet_t * item = mesh_subnet_iterator_get_next(&it); 305569f13d0SMatthias Ringwald if (memcmp(item->old_key->network_id, beacon_network_id, 8) == 0 ) { 30677ba3d3fSMatthias Ringwald subnet = item; 30789e0288aSMatthias Ringwald network_key = item->old_key; 308569f13d0SMatthias Ringwald } 309569f13d0SMatthias Ringwald if (item->new_key != NULL && memcmp(item->new_key->network_id, beacon_network_id, 8) == 0 ) { 310569f13d0SMatthias Ringwald subnet = item; 31189e0288aSMatthias Ringwald network_key = item->new_key; 312569f13d0SMatthias Ringwald } 31377ba3d3fSMatthias Ringwald break; 31477ba3d3fSMatthias Ringwald } 31577ba3d3fSMatthias Ringwald if (subnet == NULL) return; 31677ba3d3fSMatthias Ringwald 31777ba3d3fSMatthias Ringwald // count beacon 31877ba3d3fSMatthias Ringwald subnet->beacon_observation_counter++; 31977ba3d3fSMatthias Ringwald 32077ba3d3fSMatthias Ringwald // check if new flags are set 32177ba3d3fSMatthias Ringwald uint8_t current_flags = mesh_secure_network_beacon_get_flags(subnet); 32277ba3d3fSMatthias Ringwald uint8_t new_flags = packet[1] & (~current_flags); 32377ba3d3fSMatthias Ringwald 32477ba3d3fSMatthias Ringwald if (new_flags == 0) return; 32577ba3d3fSMatthias Ringwald 32677ba3d3fSMatthias Ringwald // validate beacon - if crytpo ready 32777ba3d3fSMatthias Ringwald if (mesh_secure_network_beacon_active) return; 32877ba3d3fSMatthias Ringwald 32977ba3d3fSMatthias Ringwald mesh_secure_network_beacon_active = 1; 3306535961aSMatthias Ringwald (void)memcpy(mesh_secure_network_beacon_validate_buffer, &packet[0], 3316535961aSMatthias Ringwald SECURE_NETWORK_BEACON_LEN); 33277ba3d3fSMatthias Ringwald 333bdf219b2SMatthias Ringwald btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, network_key->beacon_key, 13, 33477ba3d3fSMatthias Ringwald &mesh_secure_network_beacon_validate_buffer[1], mesh_secure_network_beacon_auth_value, &beacon_handle_secure_beacon_auth_value_calculated, subnet); 33577ba3d3fSMatthias Ringwald } 33677ba3d3fSMatthias Ringwald 33777ba3d3fSMatthias Ringwald static void beacon_handle_beacon_packet(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 33877ba3d3fSMatthias Ringwald log_info("beacon type %u", packet[0]); 33977ba3d3fSMatthias Ringwald switch (packet[0]){ 34077ba3d3fSMatthias Ringwald case BEACON_TYPE_UNPROVISIONED_DEVICE: 34177ba3d3fSMatthias Ringwald if (unprovisioned_device_beacon_handler){ 34277ba3d3fSMatthias Ringwald (*unprovisioned_device_beacon_handler)(packet_type, channel, packet, size); 34377ba3d3fSMatthias Ringwald } 34477ba3d3fSMatthias Ringwald break; 34577ba3d3fSMatthias Ringwald case BEACON_TYPE_SECURE_NETWORK: 34677ba3d3fSMatthias Ringwald beacon_handle_secure_beacon(packet, size); 34777ba3d3fSMatthias Ringwald break; 34877ba3d3fSMatthias Ringwald default: 34977ba3d3fSMatthias Ringwald break; 35077ba3d3fSMatthias Ringwald } 35177ba3d3fSMatthias Ringwald } 35277ba3d3fSMatthias Ringwald 35377ba3d3fSMatthias Ringwald static void beacon_adv_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 3542fa98d7eSMatthias Ringwald mesh_subnet_iterator_t it; 35577ba3d3fSMatthias Ringwald switch (packet_type){ 35677ba3d3fSMatthias Ringwald case HCI_EVENT_PACKET: 35777ba3d3fSMatthias Ringwald switch(packet[0]){ 35877ba3d3fSMatthias Ringwald case HCI_EVENT_MESH_META: 35977ba3d3fSMatthias Ringwald switch(packet[2]){ 36077ba3d3fSMatthias Ringwald case MESH_SUBEVENT_CAN_SEND_NOW: 36177ba3d3fSMatthias Ringwald if (beacon_send_device_beacon){ 36277ba3d3fSMatthias Ringwald beacon_send_device_beacon = 0; 3634662af4aSMatthias Ringwald adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len); 36477ba3d3fSMatthias Ringwald break; 36577ba3d3fSMatthias Ringwald } 36677ba3d3fSMatthias Ringwald // secure beacon state machine 3672fa98d7eSMatthias Ringwald mesh_subnet_iterator_init(&it); 3682fa98d7eSMatthias Ringwald while (mesh_subnet_iterator_has_more(&it)){ 3692fa98d7eSMatthias Ringwald mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it); 37077ba3d3fSMatthias Ringwald switch (subnet->beacon_state){ 37177ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV: 3724662af4aSMatthias Ringwald adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len); 37377ba3d3fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_ADV_SENT; 37477ba3d3fSMatthias Ringwald mesh_secure_network_beacon_run(NULL); 37577ba3d3fSMatthias Ringwald break; 37677ba3d3fSMatthias Ringwald default: 37777ba3d3fSMatthias Ringwald break; 37877ba3d3fSMatthias Ringwald } 37977ba3d3fSMatthias Ringwald } 38077ba3d3fSMatthias Ringwald break; 38177ba3d3fSMatthias Ringwald default: 38277ba3d3fSMatthias Ringwald break; 38377ba3d3fSMatthias Ringwald } 38477ba3d3fSMatthias Ringwald break; 38577ba3d3fSMatthias Ringwald default: 38677ba3d3fSMatthias Ringwald break; 38777ba3d3fSMatthias Ringwald } 38877ba3d3fSMatthias Ringwald break; 38977ba3d3fSMatthias Ringwald case MESH_BEACON_PACKET: 39077ba3d3fSMatthias Ringwald beacon_handle_beacon_packet(packet_type, channel, packet, size); 39177ba3d3fSMatthias Ringwald break; 39277ba3d3fSMatthias Ringwald default: 39377ba3d3fSMatthias Ringwald break; 39477ba3d3fSMatthias Ringwald } 39577ba3d3fSMatthias Ringwald } 396b3a527ecSMatthias Ringwald #endif 39777ba3d3fSMatthias Ringwald 39877ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 39921ed246fSMatthias Ringwald // handle MESH_SUBEVENT_PROXY_DISCONNECTED and MESH_SUBEVENT_CAN_SEND_NOW 40021ed246fSMatthias Ringwald static void beacon_gatt_handle_mesh_event(uint8_t mesh_subevent){ 4012fa98d7eSMatthias Ringwald mesh_subnet_iterator_t it; 4022fa98d7eSMatthias Ringwald mesh_subnet_iterator_init(&it); 4032fa98d7eSMatthias Ringwald while (mesh_subnet_iterator_has_more(&it)){ 4042fa98d7eSMatthias Ringwald mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it); 40577ba3d3fSMatthias Ringwald switch (subnet->beacon_state){ 40677ba3d3fSMatthias Ringwald case MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT: 40721ed246fSMatthias Ringwald // skip send on MESH_SUBEVENT_PROXY_DISCONNECTED 40821ed246fSMatthias Ringwald if (mesh_subevent == MESH_SUBEVENT_CAN_SEND_NOW){ 4094662af4aSMatthias Ringwald gatt_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len); 41021ed246fSMatthias Ringwald } 41177ba3d3fSMatthias Ringwald subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT; 41277ba3d3fSMatthias Ringwald mesh_secure_network_beacon_run(NULL); 41377ba3d3fSMatthias Ringwald break; 41477ba3d3fSMatthias Ringwald default: 41577ba3d3fSMatthias Ringwald break; 41677ba3d3fSMatthias Ringwald } 41777ba3d3fSMatthias Ringwald } 41821ed246fSMatthias Ringwald 41921ed246fSMatthias Ringwald } 42021ed246fSMatthias Ringwald 42121ed246fSMatthias Ringwald static void beacon_gatt_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 42221ed246fSMatthias Ringwald uint8_t mesh_subevent; 42321ed246fSMatthias Ringwald switch (packet_type){ 42421ed246fSMatthias Ringwald case HCI_EVENT_PACKET: 42521ed246fSMatthias Ringwald switch(packet[0]){ 42621ed246fSMatthias Ringwald case HCI_EVENT_MESH_META: 42721ed246fSMatthias Ringwald mesh_subevent = packet[2]; 42821ed246fSMatthias Ringwald switch(mesh_subevent){ 42921ed246fSMatthias Ringwald case MESH_SUBEVENT_PROXY_CONNECTED: 43021ed246fSMatthias Ringwald gatt_bearer_con_handle = mesh_subevent_proxy_connected_get_con_handle(packet); 43121ed246fSMatthias Ringwald break; 43221ed246fSMatthias Ringwald case MESH_SUBEVENT_PROXY_DISCONNECTED: 43321ed246fSMatthias Ringwald gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID; 43421ed246fSMatthias Ringwald beacon_gatt_handle_mesh_event(mesh_subevent); 43521ed246fSMatthias Ringwald break; 43621ed246fSMatthias Ringwald case MESH_SUBEVENT_CAN_SEND_NOW: 43721ed246fSMatthias Ringwald beacon_gatt_handle_mesh_event(mesh_subevent); 43877ba3d3fSMatthias Ringwald break; 43977ba3d3fSMatthias Ringwald default: 44077ba3d3fSMatthias Ringwald break; 44177ba3d3fSMatthias Ringwald } 44277ba3d3fSMatthias Ringwald break; 44377ba3d3fSMatthias Ringwald default: 44477ba3d3fSMatthias Ringwald break; 44577ba3d3fSMatthias Ringwald } 44677ba3d3fSMatthias Ringwald break; 44777ba3d3fSMatthias Ringwald case MESH_BEACON_PACKET: 44877ba3d3fSMatthias Ringwald beacon_handle_beacon_packet(packet_type, channel, packet, size); 44977ba3d3fSMatthias Ringwald break; 45077ba3d3fSMatthias Ringwald default: 45177ba3d3fSMatthias Ringwald break; 45277ba3d3fSMatthias Ringwald } 45377ba3d3fSMatthias Ringwald } 45477ba3d3fSMatthias Ringwald #endif 45577ba3d3fSMatthias Ringwald 45677ba3d3fSMatthias Ringwald void beacon_init(void){ 457b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 4584662af4aSMatthias Ringwald adv_bearer_register_for_beacon(&beacon_adv_packet_handler); 459b3a527ecSMatthias Ringwald #endif 46077ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 461b3a527ecSMatthias Ringwald gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID; 4624662af4aSMatthias Ringwald gatt_bearer_register_for_beacon(&beacon_gatt_packet_handler); 46377ba3d3fSMatthias Ringwald #endif 46477ba3d3fSMatthias Ringwald } 46577ba3d3fSMatthias Ringwald 46677ba3d3fSMatthias Ringwald /** 46777ba3d3fSMatthias Ringwald * Start Unprovisioned Device Beacon 46877ba3d3fSMatthias Ringwald */ 46977ba3d3fSMatthias Ringwald void beacon_unprovisioned_device_start(const uint8_t * device_uuid, uint16_t oob_information){ 470b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 47177ba3d3fSMatthias Ringwald beacon_oob_information = oob_information; 47277ba3d3fSMatthias Ringwald if (device_uuid){ 47377ba3d3fSMatthias Ringwald beacon_device_uuid = device_uuid; 47477ba3d3fSMatthias Ringwald beacon_timer.process = &beacon_timer_handler; 475698b6644SMatthias Ringwald btstack_run_loop_remove_timer(&beacon_timer); 47677ba3d3fSMatthias Ringwald beacon_timer_handler(&beacon_timer); 47777ba3d3fSMatthias Ringwald } 478b3a527ecSMatthias Ringwald #endif 47977ba3d3fSMatthias Ringwald } 48077ba3d3fSMatthias Ringwald 48177ba3d3fSMatthias Ringwald /** 48277ba3d3fSMatthias Ringwald * Stop Unprovisioned Device Beacon 48377ba3d3fSMatthias Ringwald */ 48477ba3d3fSMatthias Ringwald void beacon_unprovisioned_device_stop(void){ 485b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER 48677ba3d3fSMatthias Ringwald btstack_run_loop_remove_timer(&beacon_timer); 487e90005a5SMatthias Ringwald beacon_timer_active = 0; 488b3a527ecSMatthias Ringwald #endif 48977ba3d3fSMatthias Ringwald } 49077ba3d3fSMatthias Ringwald 49177ba3d3fSMatthias Ringwald // secure network beacons 49277ba3d3fSMatthias Ringwald 4932fa98d7eSMatthias Ringwald void beacon_secure_network_start(mesh_subnet_t * mesh_subnet){ 49477ba3d3fSMatthias Ringwald // default interval 4952fa98d7eSMatthias Ringwald mesh_subnet->beacon_interval_ms = SECURE_NETWORK_BEACON_INTERVAL_MIN_MS; 4962fa98d7eSMatthias Ringwald mesh_subnet->beacon_observation_start_ms = btstack_run_loop_get_time_ms(); 4972fa98d7eSMatthias Ringwald mesh_subnet->beacon_observation_counter = 0; 49815cb14e1SMatthias Ringwald if (mesh_foundation_beacon_get()){ 49915cb14e1SMatthias Ringwald mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE; 50015cb14e1SMatthias Ringwald } else { 50115cb14e1SMatthias Ringwald mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT; 50215cb14e1SMatthias Ringwald } 50377ba3d3fSMatthias Ringwald 50477ba3d3fSMatthias Ringwald // start sending 50577ba3d3fSMatthias Ringwald mesh_secure_network_beacon_run(NULL); 50677ba3d3fSMatthias Ringwald } 50777ba3d3fSMatthias Ringwald 50877ba3d3fSMatthias Ringwald // register handler 50977ba3d3fSMatthias Ringwald void beacon_register_for_unprovisioned_device_beacons(btstack_packet_handler_t packet_handler){ 51077ba3d3fSMatthias Ringwald unprovisioned_device_beacon_handler = packet_handler; 51177ba3d3fSMatthias Ringwald } 51277ba3d3fSMatthias Ringwald 51377ba3d3fSMatthias Ringwald void beacon_register_for_secure_network_beacons(btstack_packet_handler_t packet_handler){ 51477ba3d3fSMatthias Ringwald mesh_secure_network_beacon_handler = packet_handler; 51577ba3d3fSMatthias Ringwald } 516