mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-01 04:20:33 +00:00
mesh: add security beaon state to network key
This commit is contained in:
parent
c9de66827c
commit
f576ee26ea
@ -49,32 +49,162 @@
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_event.h"
|
||||
#include "gap.h"
|
||||
#include "mesh_keys.h"
|
||||
|
||||
#define UNPROVISIONED_BEACON_INTERVAL_MS 5000
|
||||
|
||||
#define BEACON_TYPE_UNPROVISIONED_DEVICE 0
|
||||
#define BEACON_TYPE_SECURE_NETWORK 1
|
||||
|
||||
#define SECURE_BEACON_INTERVAL_MIN_MS 10000
|
||||
|
||||
|
||||
// beacon
|
||||
static uint8_t mesh_beacon_data[29];
|
||||
static uint8_t mesh_beacon_len;
|
||||
static btstack_timer_source_t beacon_timer;
|
||||
|
||||
// unprovisioned device beacon
|
||||
static const uint8_t * beacon_device_uuid;
|
||||
static uint16_t beacon_oob_information;
|
||||
static uint32_t beacon_uri_hash;
|
||||
static btstack_timer_source_t beacon_timer;
|
||||
|
||||
static btstack_packet_handler_t unprovisioned_device_beacon_handler;
|
||||
static btstack_packet_handler_t secure_network_beacon_handler;
|
||||
|
||||
// secure network beacon
|
||||
static btstack_crypto_aes128_cmac_t mesh_secure_network_beacon_cmac_request;
|
||||
static uint8_t mesh_secure_network_beacon_auth_value[16];
|
||||
static btstack_packet_handler_t mesh_secure_network_beacon_handler;
|
||||
static int mesh_secure_network_beacon_active;
|
||||
|
||||
static void beacon_timer_handler(btstack_timer_source_t * ts){
|
||||
// restart timer
|
||||
btstack_run_loop_set_timer(ts, UNPROVISIONED_BEACON_INTERVAL_MS);
|
||||
btstack_run_loop_add_timer(ts);
|
||||
|
||||
// setup beacon
|
||||
mesh_beacon_len = 23;
|
||||
mesh_beacon_data[0] = BEACON_TYPE_UNPROVISIONED_DEVICE;
|
||||
memcpy(&mesh_beacon_data[1], beacon_device_uuid, 16);
|
||||
big_endian_store_16(mesh_beacon_data, 17, beacon_oob_information);
|
||||
big_endian_store_32(mesh_beacon_data, 19, beacon_uri_hash);
|
||||
|
||||
// request to send
|
||||
adv_bearer_request_can_send_now_for_mesh_beacon();
|
||||
}
|
||||
|
||||
static void mesh_secure_network_beacon_auth_value_calculated(void * arg){
|
||||
mesh_network_key_t * mesh_network_key = (mesh_network_key_t *) arg;
|
||||
|
||||
memcpy(&mesh_beacon_data[14], mesh_secure_network_beacon_auth_value, 8);
|
||||
mesh_beacon_len = 22;
|
||||
|
||||
printf("Secure Network Beacon\n");
|
||||
printf("- ");
|
||||
printf_hexdump(mesh_beacon_data, sizeof(mesh_beacon_len));
|
||||
|
||||
mesh_network_key->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV;
|
||||
adv_bearer_request_can_send_now_for_mesh_beacon();
|
||||
}
|
||||
|
||||
static void mesh_secure_network_beacon_setup(mesh_network_key_t * mesh_network_key){
|
||||
mesh_network_key->beacon_state = MESH_SECURE_NETWORK_BEACON_W4_AUTH_VALUE;
|
||||
|
||||
// calculate mesh flags
|
||||
uint8_t mesh_flags = 0;
|
||||
if (mesh_network_key->key_refresh != MESH_KEY_REFRESH_NOT_ACTIVE){
|
||||
mesh_flags |= 1;
|
||||
}
|
||||
|
||||
// TODO: set bit 1 if IV Update is active
|
||||
|
||||
mesh_beacon_data[0] = BEACON_TYPE_SECURE_NETWORK;
|
||||
mesh_beacon_data[1] = mesh_flags;
|
||||
memcpy(&mesh_beacon_data[2], mesh_network_key->network_id, 8);
|
||||
big_endian_store_32(mesh_beacon_data, 10, mesh_get_iv_index());
|
||||
btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, mesh_network_key->beacon_key, 13,
|
||||
&mesh_beacon_data[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_auth_value_calculated, mesh_network_key);
|
||||
}
|
||||
|
||||
static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts){
|
||||
UNUSED(ts);
|
||||
|
||||
uint32_t next_timeout_ms = 0;
|
||||
|
||||
// iterate over all networks
|
||||
mesh_network_key_iterator_t it;
|
||||
mesh_network_key_iterator_init(&it);
|
||||
while (mesh_network_key_iterator_has_more(&it)){
|
||||
mesh_network_key_t * subnet = mesh_network_key_iterator_get_next(&it);
|
||||
switch (subnet->beacon_state){
|
||||
case MESH_SECURE_NETWORK_BEACON_W4_INTERVAL:
|
||||
// TODO: calculate beacon interval
|
||||
|
||||
// send new beacon
|
||||
subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
|
||||
|
||||
/** Explict Fall-through */
|
||||
|
||||
case MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE:
|
||||
if (mesh_secure_network_beacon_active){
|
||||
// just try again in 10 ms
|
||||
next_timeout_ms = 10;
|
||||
break;
|
||||
}
|
||||
mesh_secure_network_beacon_active = 1;
|
||||
mesh_secure_network_beacon_setup(subnet);
|
||||
break;
|
||||
|
||||
case MESH_SECURE_NETWORK_BEACON_SENT:
|
||||
// now, start listening for beacons
|
||||
subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W4_INTERVAL;
|
||||
// and request timeout
|
||||
if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){
|
||||
next_timeout_ms = subnet->beacon_interval_ms;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// setup next run
|
||||
if (next_timeout_ms == 0) return;
|
||||
|
||||
btstack_run_loop_set_timer(&beacon_timer, 10);
|
||||
btstack_run_loop_set_timer_handler(&beacon_timer, mesh_secure_network_beacon_run);
|
||||
btstack_run_loop_add_timer(&beacon_timer);
|
||||
}
|
||||
|
||||
static void beacon_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
uint8_t beacon[23];
|
||||
mesh_network_key_iterator_t it;
|
||||
int secure_beacon_run = 0;
|
||||
switch (packet_type){
|
||||
case HCI_EVENT_PACKET:
|
||||
switch(packet[0]){
|
||||
case HCI_EVENT_MESH_META:
|
||||
switch(packet[2]){
|
||||
case MESH_SUBEVENT_CAN_SEND_NOW:
|
||||
beacon[0] = BEACON_TYPE_UNPROVISIONED_DEVICE;
|
||||
memcpy(&beacon[1], beacon_device_uuid, 16);
|
||||
big_endian_store_16(beacon, 17, beacon_oob_information);
|
||||
big_endian_store_32(beacon, 19, beacon_uri_hash);
|
||||
adv_bearer_send_mesh_beacon(beacon, sizeof(beacon));
|
||||
adv_bearer_send_mesh_beacon(mesh_beacon_data, mesh_beacon_len);
|
||||
mesh_secure_network_beacon_active = 0;
|
||||
|
||||
// secure beacon state machine
|
||||
mesh_network_key_iterator_init(&it);
|
||||
while (mesh_network_key_iterator_has_more(&it)){
|
||||
mesh_network_key_t * subnet = mesh_network_key_iterator_get_next(&it);
|
||||
switch (subnet->beacon_state){
|
||||
case MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV:
|
||||
// send
|
||||
subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_SENT;
|
||||
secure_beacon_run = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!secure_beacon_run) break;
|
||||
mesh_secure_network_beacon_run(NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -93,8 +223,8 @@ static void beacon_packet_handler (uint8_t packet_type, uint16_t channel, uint8_
|
||||
}
|
||||
break;
|
||||
case BEACON_TYPE_SECURE_NETWORK:
|
||||
if (secure_network_beacon_handler){
|
||||
(*secure_network_beacon_handler)(packet_type, channel, packet, size);
|
||||
if (mesh_secure_network_beacon_handler){
|
||||
(*mesh_secure_network_beacon_handler)(packet_type, channel, packet, size);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -106,14 +236,6 @@ static void beacon_packet_handler (uint8_t packet_type, uint16_t channel, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
static void beacon_timer_handler(btstack_timer_source_t * ts){
|
||||
// restart timer
|
||||
btstack_run_loop_set_timer(ts, UNPROVISIONED_BEACON_INTERVAL_MS);
|
||||
btstack_run_loop_add_timer(ts);
|
||||
|
||||
adv_bearer_request_can_send_now_for_mesh_beacon();
|
||||
}
|
||||
|
||||
void beacon_init(void){
|
||||
adv_bearer_register_for_mesh_beacon(&beacon_packet_handler);
|
||||
}
|
||||
@ -139,39 +261,15 @@ void beacon_unprovisioned_device_stop(void){
|
||||
|
||||
// secure network beacons
|
||||
|
||||
static btstack_crypto_aes128_cmac_t mesh_secure_network_beacon_cmac_request;
|
||||
static uint8_t mesh_secure_network_beacon[22];
|
||||
static uint8_t mesh_secure_network_beacon_auth_value[16];
|
||||
|
||||
static void mesh_secure_network_beacon_send_adv_auth_value_calculated(void * arg){
|
||||
UNUSED(arg);
|
||||
memcpy(&mesh_secure_network_beacon[14], mesh_secure_network_beacon_auth_value, 8);
|
||||
printf("Secure Network Beacon\n");
|
||||
printf("- ");
|
||||
printf_hexdump(mesh_secure_network_beacon, sizeof(mesh_secure_network_beacon));
|
||||
adv_bearer_send_mesh_beacon(mesh_secure_network_beacon, sizeof(mesh_secure_network_beacon));
|
||||
}
|
||||
|
||||
static void mesh_secure_network_beacon_send_adv(const char * network_id, const char * beacon_key, int8_t mesh_flags){
|
||||
mesh_secure_network_beacon[0] = BEACON_TYPE_SECURE_NETWORK;
|
||||
mesh_secure_network_beacon[1] = mesh_flags;
|
||||
memcpy(&mesh_secure_network_beacon[2], network_id, 8);
|
||||
big_endian_store_32(mesh_secure_network_beacon, 10, mesh_get_iv_index());
|
||||
btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, beacon_key, 13,
|
||||
&mesh_secure_network_beacon[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_send_adv_auth_value_calculated, NULL);
|
||||
}
|
||||
|
||||
// crypto context
|
||||
static void beacon_secure_network_timer_handler(btstack_timer_source_t * ts){
|
||||
|
||||
}
|
||||
|
||||
void beacon_secure_network_start(mesh_network_key_t * mesh_network_key){
|
||||
// start with default interval
|
||||
mesh_network_key->beacon_interval_ms = 10 * 1000; // 10 seconds
|
||||
// set timer for next one
|
||||
// default interval
|
||||
mesh_network_key->beacon_interval_ms = SECURE_BEACON_INTERVAL_MIN_MS;
|
||||
mesh_network_key->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
|
||||
mesh_network_key->beacon_observation_start_ms = btstack_run_loop_get_time_ms();
|
||||
mesh_network_key->beacon_observation_counter = 0;
|
||||
|
||||
//
|
||||
// start sending
|
||||
mesh_secure_network_beacon_run(NULL);
|
||||
}
|
||||
|
||||
// register handler
|
||||
@ -180,5 +278,5 @@ void beacon_register_for_unprovisioned_device_beacons(btstack_packet_handler_t p
|
||||
}
|
||||
|
||||
void beacon_register_for_secure_network_beacons(btstack_packet_handler_t packet_handler){
|
||||
secure_network_beacon_handler = packet_handler;
|
||||
mesh_secure_network_beacon_handler = packet_handler;
|
||||
}
|
||||
|
@ -57,6 +57,15 @@ typedef enum {
|
||||
MESH_KEY_REFRESH_SECOND_PHASE
|
||||
} mesh_key_refresh_state_t;
|
||||
|
||||
typedef enum {
|
||||
MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE,
|
||||
MESH_SECURE_NETWORK_BEACON_W4_AUTH_VALUE,
|
||||
MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV,
|
||||
MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT,
|
||||
MESH_SECURE_NETWORK_BEACON_SENT,
|
||||
MESH_SECURE_NETWORK_BEACON_W4_INTERVAL
|
||||
} mesh_secure_network_beacon_state_t;
|
||||
|
||||
typedef struct {
|
||||
btstack_linked_item_t item;
|
||||
|
||||
@ -93,8 +102,10 @@ typedef struct {
|
||||
adv_bearer_connectable_advertisement_data_item_t advertisement_with_network_id;
|
||||
|
||||
// secure network beacons
|
||||
btstack_timer_source_t beacon_timer;
|
||||
uint32_t beacon_interval_ms;
|
||||
mesh_secure_network_beacon_state_t beacon_state;
|
||||
uint32_t beacon_interval_ms;
|
||||
uint32_t beacon_observation_start_ms;
|
||||
uint16_t beacon_observation_counter;
|
||||
|
||||
} mesh_network_key_t;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user