xref: /btstack/src/mesh/beacon.c (revision 6250fd6f627de0c0bab5d8bb0e68f9b0b6850d1e)
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 
38b3a527ecSMatthias Ringwald #define __BTSTACK_FILE__ "beacon.c"
3977ba3d3fSMatthias Ringwald 
40f4854a5eSMatthias Ringwald #include "mesh/beacon.h"
41f4854a5eSMatthias Ringwald 
4277ba3d3fSMatthias Ringwald #include <string.h>
4377ba3d3fSMatthias Ringwald 
4477ba3d3fSMatthias Ringwald #include "ble/core.h"
4577ba3d3fSMatthias Ringwald #include "bluetooth.h"
4677ba3d3fSMatthias Ringwald #include "bluetooth_data_types.h"
4777ba3d3fSMatthias Ringwald #include "btstack_debug.h"
4877ba3d3fSMatthias Ringwald #include "btstack_event.h"
49f4854a5eSMatthias Ringwald #include "btstack_run_loop.h"
50f4854a5eSMatthias Ringwald #include "btstack_util.h"
5177ba3d3fSMatthias Ringwald #include "gap.h"
52f4854a5eSMatthias Ringwald 
53f4854a5eSMatthias Ringwald #include "mesh/adv_bearer.h"
54f4854a5eSMatthias Ringwald #include "mesh/gatt_bearer.h"
55f4854a5eSMatthias Ringwald #include "mesh/mesh_foundation.h"
56f4854a5eSMatthias Ringwald #include "mesh/mesh_iv_index_seq_number.h"
57f4854a5eSMatthias Ringwald #include "mesh/mesh_keys.h"
5877ba3d3fSMatthias Ringwald 
5977ba3d3fSMatthias Ringwald #define BEACON_TYPE_UNPROVISIONED_DEVICE 0
6077ba3d3fSMatthias Ringwald #define BEACON_TYPE_SECURE_NETWORK 1
6177ba3d3fSMatthias Ringwald 
6277ba3d3fSMatthias Ringwald #define UNPROVISIONED_BEACON_INTERVAL_MS 5000
6377ba3d3fSMatthias Ringwald #define UNPROVISIONED_BEACON_LEN      23
6477ba3d3fSMatthias Ringwald 
6577ba3d3fSMatthias Ringwald #define SECURE_NETWORK_BEACON_INTERVAL_MIN_MS  10000
6677ba3d3fSMatthias Ringwald #define SECURE_NETWORK_BEACON_INTERVAL_MAX_MS 600000
6777ba3d3fSMatthias Ringwald #define SECURE_NETWORK_BEACON_LEN                 22
6877ba3d3fSMatthias Ringwald 
6977ba3d3fSMatthias Ringwald // prototypes
7077ba3d3fSMatthias Ringwald static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts);
7177ba3d3fSMatthias Ringwald 
72b3a527ecSMatthias Ringwald // bearers
73b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER
74b3a527ecSMatthias Ringwald static hci_con_handle_t gatt_bearer_con_handle;
75b3a527ecSMatthias Ringwald #endif
76b3a527ecSMatthias Ringwald 
7777ba3d3fSMatthias Ringwald // beacon
7877ba3d3fSMatthias Ringwald static uint8_t mesh_beacon_data[29];
7977ba3d3fSMatthias Ringwald static uint8_t mesh_beacon_len;
8077ba3d3fSMatthias Ringwald static btstack_timer_source_t   beacon_timer;
8177ba3d3fSMatthias Ringwald 
8277ba3d3fSMatthias Ringwald // unprovisioned device beacon
83b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
8477ba3d3fSMatthias Ringwald static const uint8_t * beacon_device_uuid;
8577ba3d3fSMatthias Ringwald static       uint16_t  beacon_oob_information;
8677ba3d3fSMatthias Ringwald static       uint32_t  beacon_uri_hash;
8777ba3d3fSMatthias Ringwald static int             beacon_send_device_beacon;
88b3a527ecSMatthias Ringwald #endif
8977ba3d3fSMatthias Ringwald 
9077ba3d3fSMatthias Ringwald static btstack_packet_handler_t unprovisioned_device_beacon_handler;
9177ba3d3fSMatthias Ringwald 
9277ba3d3fSMatthias Ringwald // secure network beacon
9377ba3d3fSMatthias Ringwald static btstack_crypto_aes128_cmac_t        mesh_secure_network_beacon_cmac_request;
9477ba3d3fSMatthias Ringwald static uint8_t                             mesh_secure_network_beacon_auth_value[16];
9577ba3d3fSMatthias Ringwald static btstack_packet_handler_t            mesh_secure_network_beacon_handler;
9677ba3d3fSMatthias Ringwald static int                                 mesh_secure_network_beacon_active;
97*6250fd6fSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
9877ba3d3fSMatthias Ringwald static uint8_t                             mesh_secure_network_beacon_validate_buffer[SECURE_NETWORK_BEACON_LEN];
99*6250fd6fSMatthias Ringwald #endif
10077ba3d3fSMatthias Ringwald 
101b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
10277ba3d3fSMatthias Ringwald static void beacon_timer_handler(btstack_timer_source_t * ts){
10377ba3d3fSMatthias Ringwald     // restart timer
10477ba3d3fSMatthias Ringwald     btstack_run_loop_set_timer(ts, UNPROVISIONED_BEACON_INTERVAL_MS);
10577ba3d3fSMatthias Ringwald     btstack_run_loop_add_timer(ts);
10677ba3d3fSMatthias Ringwald 
10777ba3d3fSMatthias Ringwald     // setup beacon
10877ba3d3fSMatthias Ringwald     mesh_beacon_len = UNPROVISIONED_BEACON_LEN;
10977ba3d3fSMatthias Ringwald     mesh_beacon_data[0] = BEACON_TYPE_UNPROVISIONED_DEVICE;
11077ba3d3fSMatthias Ringwald     memcpy(&mesh_beacon_data[1], beacon_device_uuid, 16);
11177ba3d3fSMatthias Ringwald     big_endian_store_16(mesh_beacon_data, 17, beacon_oob_information);
11277ba3d3fSMatthias Ringwald     big_endian_store_32(mesh_beacon_data, 19, beacon_uri_hash);
11377ba3d3fSMatthias Ringwald 
11477ba3d3fSMatthias Ringwald     // request to send
11577ba3d3fSMatthias Ringwald     beacon_send_device_beacon = 1;
1164662af4aSMatthias Ringwald     adv_bearer_request_can_send_now_for_beacon();
11777ba3d3fSMatthias Ringwald }
118b3a527ecSMatthias Ringwald #endif
11977ba3d3fSMatthias Ringwald 
12077ba3d3fSMatthias Ringwald static void mesh_secure_network_beacon_auth_value_calculated(void * arg){
1212fa98d7eSMatthias Ringwald     mesh_subnet_t * mesh_subnet = (mesh_subnet_t *) arg;
12277ba3d3fSMatthias Ringwald 
12377ba3d3fSMatthias Ringwald     memcpy(&mesh_beacon_data[14], mesh_secure_network_beacon_auth_value, 8);
12477ba3d3fSMatthias Ringwald     mesh_beacon_len = SECURE_NETWORK_BEACON_LEN;
12577ba3d3fSMatthias Ringwald 
12677ba3d3fSMatthias Ringwald     printf("Secure Network Beacon\n");
12777ba3d3fSMatthias Ringwald     printf("- ");
12877ba3d3fSMatthias Ringwald     printf_hexdump(mesh_beacon_data, mesh_beacon_len);
12977ba3d3fSMatthias Ringwald 
1302d63f17cSMatthias Ringwald     mesh_secure_network_beacon_active = 0;
1312fa98d7eSMatthias Ringwald     mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_AUTH_VALUE;
13277ba3d3fSMatthias Ringwald 
13377ba3d3fSMatthias Ringwald     mesh_secure_network_beacon_run(NULL);
13477ba3d3fSMatthias Ringwald }
13577ba3d3fSMatthias Ringwald 
1362fa98d7eSMatthias Ringwald static uint8_t mesh_secure_network_beacon_get_flags(mesh_subnet_t * mesh_subnet){
13777ba3d3fSMatthias Ringwald     uint8_t mesh_flags = 0;
1382fa98d7eSMatthias Ringwald     if (mesh_subnet->key_refresh != MESH_KEY_REFRESH_NOT_ACTIVE){
13977ba3d3fSMatthias Ringwald         mesh_flags |= 1;
14077ba3d3fSMatthias Ringwald     }
1417d005332SMatthias Ringwald     if (mesh_iv_update_active()){
1427d005332SMatthias Ringwald         mesh_flags |= 2;
1437d005332SMatthias Ringwald     }
14477ba3d3fSMatthias Ringwald 
14577ba3d3fSMatthias Ringwald     return mesh_flags;
14677ba3d3fSMatthias Ringwald }
14777ba3d3fSMatthias Ringwald 
1482fa98d7eSMatthias Ringwald static void mesh_secure_network_beacon_setup(mesh_subnet_t * mesh_subnet){
14977ba3d3fSMatthias Ringwald     mesh_beacon_data[0] = BEACON_TYPE_SECURE_NETWORK;
1502fa98d7eSMatthias Ringwald     mesh_beacon_data[1] = mesh_secure_network_beacon_get_flags(mesh_subnet);
1512fa98d7eSMatthias Ringwald     // TODO: pick correct key based on key refresh phase
1522fa98d7eSMatthias Ringwald 
1532fa98d7eSMatthias Ringwald     memcpy(&mesh_beacon_data[2], mesh_subnet->old_key->network_id, 8);
15477ba3d3fSMatthias Ringwald     big_endian_store_32(mesh_beacon_data, 10, mesh_get_iv_index());
155bdf219b2SMatthias Ringwald     mesh_network_key_t * network_key = mesh_subnet_get_outgoing_network_key(mesh_subnet);
156bdf219b2SMatthias Ringwald     btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, network_key->beacon_key, 13,
1572fa98d7eSMatthias Ringwald         &mesh_beacon_data[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_auth_value_calculated, mesh_subnet);
15877ba3d3fSMatthias Ringwald }
15977ba3d3fSMatthias Ringwald 
1602fa98d7eSMatthias Ringwald static void mesh_secure_network_beacon_update_interval(mesh_subnet_t * subnet){
16177ba3d3fSMatthias Ringwald     uint32_t min_observation_period_ms = 2 * subnet->beacon_interval_ms;
16277ba3d3fSMatthias Ringwald     uint32_t actual_observation_period = btstack_time_delta(btstack_run_loop_get_time_ms(), subnet->beacon_observation_start_ms);
16377ba3d3fSMatthias Ringwald 
16477ba3d3fSMatthias Ringwald     // The Observation Period in seconds should typically be double the typical Beacon Interval.
16577ba3d3fSMatthias Ringwald     if (actual_observation_period < min_observation_period_ms) return;
16677ba3d3fSMatthias Ringwald 
16777ba3d3fSMatthias Ringwald     // Expected Number of Beacons (1 beacon per 10 seconds)
16877ba3d3fSMatthias Ringwald     uint16_t expected_number_of_beacons = actual_observation_period / SECURE_NETWORK_BEACON_INTERVAL_MIN_MS;
16977ba3d3fSMatthias Ringwald 
17077ba3d3fSMatthias Ringwald     // Beacon Interval = Observation Period * (Observed Number of Beacons + 1) / Expected Number of Beacons
17177ba3d3fSMatthias Ringwald     uint32_t new_beacon_interval  =  actual_observation_period * (subnet->beacon_observation_counter + 1) / expected_number_of_beacons;
17277ba3d3fSMatthias Ringwald 
17377ba3d3fSMatthias Ringwald     if (new_beacon_interval > SECURE_NETWORK_BEACON_INTERVAL_MAX_MS){
17477ba3d3fSMatthias Ringwald         new_beacon_interval = SECURE_NETWORK_BEACON_INTERVAL_MAX_MS;
17577ba3d3fSMatthias Ringwald     }
17677ba3d3fSMatthias Ringwald     else if (new_beacon_interval < SECURE_NETWORK_BEACON_INTERVAL_MIN_MS){
17777ba3d3fSMatthias Ringwald         new_beacon_interval = SECURE_NETWORK_BEACON_INTERVAL_MAX_MS;
17877ba3d3fSMatthias Ringwald     }
17977ba3d3fSMatthias Ringwald     subnet->beacon_interval_ms = new_beacon_interval;
18077ba3d3fSMatthias Ringwald     log_info("New beacon interval %u seconds", (int) (subnet->beacon_interval_ms / 1000));
18177ba3d3fSMatthias Ringwald }
18277ba3d3fSMatthias Ringwald 
18377ba3d3fSMatthias Ringwald static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts){
18477ba3d3fSMatthias Ringwald     UNUSED(ts);
18577ba3d3fSMatthias Ringwald 
18677ba3d3fSMatthias Ringwald     uint32_t next_timeout_ms = 0;
18777ba3d3fSMatthias Ringwald 
18877ba3d3fSMatthias Ringwald     // iterate over all networks
1892fa98d7eSMatthias Ringwald     mesh_subnet_iterator_t it;
1902fa98d7eSMatthias Ringwald     mesh_subnet_iterator_init(&it);
1912fa98d7eSMatthias Ringwald     while (mesh_subnet_iterator_has_more(&it)){
1922fa98d7eSMatthias Ringwald         mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
19377ba3d3fSMatthias Ringwald         switch (subnet->beacon_state){
19477ba3d3fSMatthias Ringwald             case MESH_SECURE_NETWORK_BEACON_W4_INTERVAL:
19577ba3d3fSMatthias Ringwald                 // update beacon interval
19677ba3d3fSMatthias Ringwald                 mesh_secure_network_beacon_update_interval(subnet);
19777ba3d3fSMatthias Ringwald 
19815cb14e1SMatthias Ringwald                 if (mesh_foundation_beacon_get() == 0){
19915cb14e1SMatthias Ringwald                     // beacon off, continue observing
20015cb14e1SMatthias Ringwald                     if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){
20115cb14e1SMatthias Ringwald                         next_timeout_ms = subnet->beacon_interval_ms;
20215cb14e1SMatthias Ringwald                     }
20315cb14e1SMatthias Ringwald                     break;
20415cb14e1SMatthias Ringwald                 }
20515cb14e1SMatthias Ringwald 
20677ba3d3fSMatthias Ringwald                 // send new beacon
20777ba3d3fSMatthias Ringwald                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
20877ba3d3fSMatthias Ringwald 
20977ba3d3fSMatthias Ringwald                 /** Explict Fall-through */
21077ba3d3fSMatthias Ringwald 
21177ba3d3fSMatthias Ringwald             case MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE:
21277ba3d3fSMatthias Ringwald                 if (mesh_secure_network_beacon_active){
21377ba3d3fSMatthias Ringwald                     // just try again in 10 ms
21477ba3d3fSMatthias Ringwald                     next_timeout_ms = 10;
21577ba3d3fSMatthias Ringwald                     break;
21677ba3d3fSMatthias Ringwald                 }
21721ed246fSMatthias Ringwald                 subnet->beacon_state  = MESH_SECURE_NETWORK_BEACON_W4_AUTH_VALUE;
21877ba3d3fSMatthias Ringwald                 mesh_secure_network_beacon_active = 1;
21977ba3d3fSMatthias Ringwald                 mesh_secure_network_beacon_setup(subnet);
22077ba3d3fSMatthias Ringwald                 break;
22177ba3d3fSMatthias Ringwald 
22277ba3d3fSMatthias Ringwald             case MESH_SECURE_NETWORK_BEACON_AUTH_VALUE:
22377ba3d3fSMatthias Ringwald 
22477ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
22577ba3d3fSMatthias Ringwald                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV;
2264662af4aSMatthias Ringwald                 adv_bearer_request_can_send_now_for_beacon();
22777ba3d3fSMatthias Ringwald                 break;
22877ba3d3fSMatthias Ringwald #endif
2298b0144a2SMatthias Ringwald                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_ADV_SENT;
23077ba3d3fSMatthias Ringwald 
23177ba3d3fSMatthias Ringwald                 /** Explict Fall-through */
23277ba3d3fSMatthias Ringwald 
23377ba3d3fSMatthias Ringwald             case MESH_SECURE_NETWORK_BEACON_ADV_SENT:
23477ba3d3fSMatthias Ringwald 
23577ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER
2368b0144a2SMatthias Ringwald                 if (gatt_bearer_con_handle != HCI_CON_HANDLE_INVALID && mesh_foundation_gatt_proxy_get() != 0){
23777ba3d3fSMatthias Ringwald                     subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT;
2384662af4aSMatthias Ringwald                     gatt_bearer_request_can_send_now_for_beacon();
2392931ab39SMatthias Ringwald                     break;
2402931ab39SMatthias Ringwald                 }
24177ba3d3fSMatthias Ringwald #endif
2428b0144a2SMatthias Ringwald                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT;
24377ba3d3fSMatthias Ringwald 
24477ba3d3fSMatthias Ringwald                 /** Explict Fall-through */
24577ba3d3fSMatthias Ringwald 
24677ba3d3fSMatthias Ringwald             case MESH_SECURE_NETWORK_BEACON_GATT_SENT:
24777ba3d3fSMatthias Ringwald                 // now, start listening for beacons
24877ba3d3fSMatthias Ringwald                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W4_INTERVAL;
24977ba3d3fSMatthias Ringwald                 // and request timeout
25077ba3d3fSMatthias Ringwald                 if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){
25177ba3d3fSMatthias Ringwald                     next_timeout_ms = subnet->beacon_interval_ms;
25277ba3d3fSMatthias Ringwald                 }
25377ba3d3fSMatthias Ringwald                 break;
2542931ab39SMatthias Ringwald 
25577ba3d3fSMatthias Ringwald             default:
25677ba3d3fSMatthias Ringwald                 break;
25777ba3d3fSMatthias Ringwald         }
25877ba3d3fSMatthias Ringwald     }
25977ba3d3fSMatthias Ringwald 
26077ba3d3fSMatthias Ringwald     // setup next run
26177ba3d3fSMatthias Ringwald     if (next_timeout_ms == 0) return;
26277ba3d3fSMatthias Ringwald 
2637c8ffd3dSMatthias Ringwald     btstack_run_loop_set_timer(&beacon_timer, next_timeout_ms);
26477ba3d3fSMatthias Ringwald     btstack_run_loop_set_timer_handler(&beacon_timer, mesh_secure_network_beacon_run);
26577ba3d3fSMatthias Ringwald     btstack_run_loop_add_timer(&beacon_timer);
26677ba3d3fSMatthias Ringwald }
26777ba3d3fSMatthias Ringwald 
268*6250fd6fSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
26977ba3d3fSMatthias Ringwald static void beacon_handle_secure_beacon_auth_value_calculated(void * arg){
27077ba3d3fSMatthias Ringwald     UNUSED(arg);
27177ba3d3fSMatthias Ringwald 
27277ba3d3fSMatthias Ringwald     // pass on, if auth value checks out
27377ba3d3fSMatthias Ringwald     if (memcmp(&mesh_secure_network_beacon_validate_buffer[14], mesh_secure_network_beacon_auth_value, 8) == 0) {
27477ba3d3fSMatthias Ringwald         if (mesh_secure_network_beacon_handler){
27577ba3d3fSMatthias Ringwald             (*mesh_secure_network_beacon_handler)(MESH_BEACON_PACKET, 0, mesh_secure_network_beacon_validate_buffer, SECURE_NETWORK_BEACON_LEN);
27677ba3d3fSMatthias Ringwald         }
27777ba3d3fSMatthias Ringwald     }
27877ba3d3fSMatthias Ringwald 
27977ba3d3fSMatthias Ringwald     // done
28077ba3d3fSMatthias Ringwald     mesh_secure_network_beacon_active = 0;
28177ba3d3fSMatthias Ringwald     mesh_secure_network_beacon_run(NULL);
28277ba3d3fSMatthias Ringwald }
28377ba3d3fSMatthias Ringwald 
28477ba3d3fSMatthias Ringwald static void beacon_handle_secure_beacon(uint8_t * packet, uint16_t size){
28577ba3d3fSMatthias Ringwald     if (size != SECURE_NETWORK_BEACON_LEN) return;
28677ba3d3fSMatthias Ringwald 
28789e0288aSMatthias Ringwald     // lookup subnet and netkey by network id
28877ba3d3fSMatthias Ringwald     uint8_t * beacon_network_id = &packet[2];
2892fa98d7eSMatthias Ringwald     mesh_subnet_iterator_t it;
2902fa98d7eSMatthias Ringwald     mesh_subnet_iterator_init(&it);
2912fa98d7eSMatthias Ringwald     mesh_subnet_t * subnet = NULL;
29289e0288aSMatthias Ringwald     mesh_network_key_t * network_key = NULL;
2932fa98d7eSMatthias Ringwald     while (mesh_subnet_iterator_has_more(&it)){
2942fa98d7eSMatthias Ringwald         mesh_subnet_t * item = mesh_subnet_iterator_get_next(&it);
295569f13d0SMatthias Ringwald         if (memcmp(item->old_key->network_id, beacon_network_id, 8) == 0 ) {
29677ba3d3fSMatthias Ringwald             subnet = item;
29789e0288aSMatthias Ringwald             network_key = item->old_key;
298569f13d0SMatthias Ringwald         }
299569f13d0SMatthias Ringwald         if (item->new_key != NULL && memcmp(item->new_key->network_id, beacon_network_id, 8) == 0 ) {
300569f13d0SMatthias Ringwald             subnet = item;
30189e0288aSMatthias Ringwald             network_key = item->new_key;
302569f13d0SMatthias Ringwald         }
30377ba3d3fSMatthias Ringwald         break;
30477ba3d3fSMatthias Ringwald     }
30577ba3d3fSMatthias Ringwald     if (subnet == NULL) return;
30677ba3d3fSMatthias Ringwald 
30777ba3d3fSMatthias Ringwald     // count beacon
30877ba3d3fSMatthias Ringwald     subnet->beacon_observation_counter++;
30977ba3d3fSMatthias Ringwald 
31077ba3d3fSMatthias Ringwald     // check if new flags are set
31177ba3d3fSMatthias Ringwald     uint8_t current_flags = mesh_secure_network_beacon_get_flags(subnet);
31277ba3d3fSMatthias Ringwald     uint8_t new_flags = packet[1] & (~current_flags);
31377ba3d3fSMatthias Ringwald 
31477ba3d3fSMatthias Ringwald     if (new_flags == 0) return;
31577ba3d3fSMatthias Ringwald 
31677ba3d3fSMatthias Ringwald     // validate beacon - if crytpo ready
31777ba3d3fSMatthias Ringwald     if (mesh_secure_network_beacon_active) return;
31877ba3d3fSMatthias Ringwald 
31977ba3d3fSMatthias Ringwald     mesh_secure_network_beacon_active = 1;
32077ba3d3fSMatthias Ringwald     memcpy(mesh_secure_network_beacon_validate_buffer, &packet[0], SECURE_NETWORK_BEACON_LEN);
32177ba3d3fSMatthias Ringwald 
322bdf219b2SMatthias Ringwald     btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, network_key->beacon_key, 13,
32377ba3d3fSMatthias Ringwald         &mesh_secure_network_beacon_validate_buffer[1], mesh_secure_network_beacon_auth_value, &beacon_handle_secure_beacon_auth_value_calculated, subnet);
32477ba3d3fSMatthias Ringwald }
32577ba3d3fSMatthias Ringwald 
32677ba3d3fSMatthias Ringwald static void beacon_handle_beacon_packet(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
32777ba3d3fSMatthias Ringwald     log_info("beacon type %u", packet[0]);
32877ba3d3fSMatthias Ringwald     switch (packet[0]){
32977ba3d3fSMatthias Ringwald         case BEACON_TYPE_UNPROVISIONED_DEVICE:
33077ba3d3fSMatthias Ringwald             if (unprovisioned_device_beacon_handler){
33177ba3d3fSMatthias Ringwald                 (*unprovisioned_device_beacon_handler)(packet_type, channel, packet, size);
33277ba3d3fSMatthias Ringwald             }
33377ba3d3fSMatthias Ringwald             break;
33477ba3d3fSMatthias Ringwald         case BEACON_TYPE_SECURE_NETWORK:
33577ba3d3fSMatthias Ringwald             beacon_handle_secure_beacon(packet, size);
33677ba3d3fSMatthias Ringwald             break;
33777ba3d3fSMatthias Ringwald         default:
33877ba3d3fSMatthias Ringwald             break;
33977ba3d3fSMatthias Ringwald     }
34077ba3d3fSMatthias Ringwald }
34177ba3d3fSMatthias Ringwald 
34277ba3d3fSMatthias Ringwald static void beacon_adv_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
3432fa98d7eSMatthias Ringwald     mesh_subnet_iterator_t it;
34477ba3d3fSMatthias Ringwald     switch (packet_type){
34577ba3d3fSMatthias Ringwald         case HCI_EVENT_PACKET:
34677ba3d3fSMatthias Ringwald             switch(packet[0]){
34777ba3d3fSMatthias Ringwald                 case HCI_EVENT_MESH_META:
34877ba3d3fSMatthias Ringwald                     switch(packet[2]){
34977ba3d3fSMatthias Ringwald                         case MESH_SUBEVENT_CAN_SEND_NOW:
35077ba3d3fSMatthias Ringwald                             if (beacon_send_device_beacon){
35177ba3d3fSMatthias Ringwald                                 beacon_send_device_beacon = 0;
3524662af4aSMatthias Ringwald                                 adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
35377ba3d3fSMatthias Ringwald                                 break;
35477ba3d3fSMatthias Ringwald                             }
35577ba3d3fSMatthias Ringwald                             // secure beacon state machine
3562fa98d7eSMatthias Ringwald                             mesh_subnet_iterator_init(&it);
3572fa98d7eSMatthias Ringwald                             while (mesh_subnet_iterator_has_more(&it)){
3582fa98d7eSMatthias Ringwald                                 mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
35977ba3d3fSMatthias Ringwald                                 switch (subnet->beacon_state){
36077ba3d3fSMatthias Ringwald                                     case MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV:
3614662af4aSMatthias Ringwald                                         adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
36277ba3d3fSMatthias Ringwald                                         subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_ADV_SENT;
36377ba3d3fSMatthias Ringwald                                         mesh_secure_network_beacon_run(NULL);
36477ba3d3fSMatthias Ringwald                                         break;
36577ba3d3fSMatthias Ringwald                                     default:
36677ba3d3fSMatthias Ringwald                                         break;
36777ba3d3fSMatthias Ringwald                                 }
36877ba3d3fSMatthias Ringwald                             }
36977ba3d3fSMatthias Ringwald                             break;
37077ba3d3fSMatthias Ringwald                         default:
37177ba3d3fSMatthias Ringwald                             break;
37277ba3d3fSMatthias Ringwald                     }
37377ba3d3fSMatthias Ringwald                     break;
37477ba3d3fSMatthias Ringwald                 default:
37577ba3d3fSMatthias Ringwald                     break;
37677ba3d3fSMatthias Ringwald             }
37777ba3d3fSMatthias Ringwald             break;
37877ba3d3fSMatthias Ringwald         case MESH_BEACON_PACKET:
37977ba3d3fSMatthias Ringwald             beacon_handle_beacon_packet(packet_type, channel, packet, size);
38077ba3d3fSMatthias Ringwald             break;
38177ba3d3fSMatthias Ringwald         default:
38277ba3d3fSMatthias Ringwald             break;
38377ba3d3fSMatthias Ringwald     }
38477ba3d3fSMatthias Ringwald }
385b3a527ecSMatthias Ringwald #endif
38677ba3d3fSMatthias Ringwald 
38777ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER
38821ed246fSMatthias Ringwald // handle MESH_SUBEVENT_PROXY_DISCONNECTED and MESH_SUBEVENT_CAN_SEND_NOW
38921ed246fSMatthias Ringwald static void beacon_gatt_handle_mesh_event(uint8_t mesh_subevent){
3902fa98d7eSMatthias Ringwald     mesh_subnet_iterator_t it;
3912fa98d7eSMatthias Ringwald     mesh_subnet_iterator_init(&it);
3922fa98d7eSMatthias Ringwald     while (mesh_subnet_iterator_has_more(&it)){
3932fa98d7eSMatthias Ringwald         mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
39477ba3d3fSMatthias Ringwald         switch (subnet->beacon_state){
39577ba3d3fSMatthias Ringwald             case MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT:
39621ed246fSMatthias Ringwald                 // skip send on MESH_SUBEVENT_PROXY_DISCONNECTED
39721ed246fSMatthias Ringwald                 if (mesh_subevent == MESH_SUBEVENT_CAN_SEND_NOW){
3984662af4aSMatthias Ringwald                     gatt_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
39921ed246fSMatthias Ringwald                 }
40077ba3d3fSMatthias Ringwald                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT;
40177ba3d3fSMatthias Ringwald                 mesh_secure_network_beacon_run(NULL);
40277ba3d3fSMatthias Ringwald                 break;
40377ba3d3fSMatthias Ringwald             default:
40477ba3d3fSMatthias Ringwald                 break;
40577ba3d3fSMatthias Ringwald         }
40677ba3d3fSMatthias Ringwald     }
40721ed246fSMatthias Ringwald 
40821ed246fSMatthias Ringwald }
40921ed246fSMatthias Ringwald 
41021ed246fSMatthias Ringwald static void beacon_gatt_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
41121ed246fSMatthias Ringwald     uint8_t mesh_subevent;
41221ed246fSMatthias Ringwald     switch (packet_type){
41321ed246fSMatthias Ringwald         case HCI_EVENT_PACKET:
41421ed246fSMatthias Ringwald             switch(packet[0]){
41521ed246fSMatthias Ringwald                 case HCI_EVENT_MESH_META:
41621ed246fSMatthias Ringwald                     mesh_subevent = packet[2];
41721ed246fSMatthias Ringwald                     switch(mesh_subevent){
41821ed246fSMatthias Ringwald                         case MESH_SUBEVENT_PROXY_CONNECTED:
41921ed246fSMatthias Ringwald                             gatt_bearer_con_handle = mesh_subevent_proxy_connected_get_con_handle(packet);
42021ed246fSMatthias Ringwald                             break;
42121ed246fSMatthias Ringwald                         case MESH_SUBEVENT_PROXY_DISCONNECTED:
42221ed246fSMatthias Ringwald                             gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
42321ed246fSMatthias Ringwald                             beacon_gatt_handle_mesh_event(mesh_subevent);
42421ed246fSMatthias Ringwald                             break;
42521ed246fSMatthias Ringwald                         case MESH_SUBEVENT_CAN_SEND_NOW:
42621ed246fSMatthias Ringwald                             beacon_gatt_handle_mesh_event(mesh_subevent);
42777ba3d3fSMatthias Ringwald                             break;
42877ba3d3fSMatthias Ringwald                         default:
42977ba3d3fSMatthias Ringwald                             break;
43077ba3d3fSMatthias Ringwald                     }
43177ba3d3fSMatthias Ringwald                     break;
43277ba3d3fSMatthias Ringwald                 default:
43377ba3d3fSMatthias Ringwald                     break;
43477ba3d3fSMatthias Ringwald             }
43577ba3d3fSMatthias Ringwald             break;
43677ba3d3fSMatthias Ringwald         case MESH_BEACON_PACKET:
43777ba3d3fSMatthias Ringwald             beacon_handle_beacon_packet(packet_type, channel, packet, size);
43877ba3d3fSMatthias Ringwald             break;
43977ba3d3fSMatthias Ringwald         default:
44077ba3d3fSMatthias Ringwald             break;
44177ba3d3fSMatthias Ringwald     }
44277ba3d3fSMatthias Ringwald }
44377ba3d3fSMatthias Ringwald #endif
44477ba3d3fSMatthias Ringwald 
44577ba3d3fSMatthias Ringwald void beacon_init(void){
446b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
4474662af4aSMatthias Ringwald     adv_bearer_register_for_beacon(&beacon_adv_packet_handler);
448b3a527ecSMatthias Ringwald #endif
44977ba3d3fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER
450b3a527ecSMatthias Ringwald     gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
4514662af4aSMatthias Ringwald     gatt_bearer_register_for_beacon(&beacon_gatt_packet_handler);
45277ba3d3fSMatthias Ringwald #endif
45377ba3d3fSMatthias Ringwald }
45477ba3d3fSMatthias Ringwald 
45577ba3d3fSMatthias Ringwald /**
45677ba3d3fSMatthias Ringwald  * Start Unprovisioned Device Beacon
45777ba3d3fSMatthias Ringwald  */
45877ba3d3fSMatthias Ringwald void beacon_unprovisioned_device_start(const uint8_t * device_uuid, uint16_t oob_information){
459b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
46077ba3d3fSMatthias Ringwald     beacon_oob_information = oob_information;
46177ba3d3fSMatthias Ringwald     if (device_uuid){
46277ba3d3fSMatthias Ringwald         beacon_device_uuid = device_uuid;
46377ba3d3fSMatthias Ringwald         beacon_timer.process = &beacon_timer_handler;
46477ba3d3fSMatthias Ringwald         beacon_timer_handler(&beacon_timer);
46577ba3d3fSMatthias Ringwald     }
466b3a527ecSMatthias Ringwald #endif
46777ba3d3fSMatthias Ringwald }
46877ba3d3fSMatthias Ringwald 
46977ba3d3fSMatthias Ringwald /**
47077ba3d3fSMatthias Ringwald  * Stop Unprovisioned Device Beacon
47177ba3d3fSMatthias Ringwald  */
47277ba3d3fSMatthias Ringwald void beacon_unprovisioned_device_stop(void){
473b3a527ecSMatthias Ringwald #ifdef ENABLE_MESH_ADV_BEARER
47477ba3d3fSMatthias Ringwald     btstack_run_loop_remove_timer(&beacon_timer);
475b3a527ecSMatthias Ringwald #endif
47677ba3d3fSMatthias Ringwald }
47777ba3d3fSMatthias Ringwald 
47877ba3d3fSMatthias Ringwald // secure network beacons
47977ba3d3fSMatthias Ringwald 
4802fa98d7eSMatthias Ringwald void beacon_secure_network_start(mesh_subnet_t * mesh_subnet){
48177ba3d3fSMatthias Ringwald     // default interval
4822fa98d7eSMatthias Ringwald     mesh_subnet->beacon_interval_ms = SECURE_NETWORK_BEACON_INTERVAL_MIN_MS;
4832fa98d7eSMatthias Ringwald     mesh_subnet->beacon_observation_start_ms = btstack_run_loop_get_time_ms();
4842fa98d7eSMatthias Ringwald     mesh_subnet->beacon_observation_counter = 0;
48515cb14e1SMatthias Ringwald     if (mesh_foundation_beacon_get()){
48615cb14e1SMatthias Ringwald         mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
48715cb14e1SMatthias Ringwald     } else {
48815cb14e1SMatthias Ringwald         mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT;
48915cb14e1SMatthias Ringwald     }
49077ba3d3fSMatthias Ringwald 
49177ba3d3fSMatthias Ringwald     // start sending
49277ba3d3fSMatthias Ringwald     mesh_secure_network_beacon_run(NULL);
49377ba3d3fSMatthias Ringwald }
49477ba3d3fSMatthias Ringwald 
49577ba3d3fSMatthias Ringwald // register handler
49677ba3d3fSMatthias Ringwald void beacon_register_for_unprovisioned_device_beacons(btstack_packet_handler_t packet_handler){
49777ba3d3fSMatthias Ringwald     unprovisioned_device_beacon_handler = packet_handler;
49877ba3d3fSMatthias Ringwald }
49977ba3d3fSMatthias Ringwald 
50077ba3d3fSMatthias Ringwald void beacon_register_for_secure_network_beacons(btstack_packet_handler_t packet_handler){
50177ba3d3fSMatthias Ringwald     mesh_secure_network_beacon_handler = packet_handler;
50277ba3d3fSMatthias Ringwald }
503