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
23*2fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka Ringwald * GMBH 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
423cfa4086SMatthias 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
beacon_timer_handler(btstack_timer_source_t * ts)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
mesh_secure_network_beacon_auth_value_calculated(void * arg)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
mesh_secure_network_beacon_get_flags(mesh_subnet_t * mesh_subnet)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
mesh_secure_network_beacon_setup(mesh_subnet_t * mesh_subnet)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
mesh_secure_network_beacon_update_interval(mesh_subnet_t * subnet)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
mesh_secure_network_beacon_run(btstack_timer_source_t * ts)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
beacon_handle_secure_beacon_auth_value_calculated(void * arg)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
beacon_handle_secure_beacon(uint8_t * packet,uint16_t size)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
beacon_handle_beacon_packet(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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
beacon_adv_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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
beacon_gatt_handle_mesh_event(uint8_t mesh_subevent)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
beacon_gatt_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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
beacon_init(void)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 */
beacon_unprovisioned_device_start(const uint8_t * device_uuid,uint16_t oob_information)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 */
beacon_unprovisioned_device_stop(void)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
beacon_secure_network_start(mesh_subnet_t * mesh_subnet)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
beacon_register_for_unprovisioned_device_beacons(btstack_packet_handler_t packet_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
beacon_register_for_secure_network_beacons(btstack_packet_handler_t packet_handler)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