mesh: add security beaon state to network key

This commit is contained in:
Matthias Ringwald 2019-06-24 18:40:15 +02:00
parent c9de66827c
commit f576ee26ea
2 changed files with 161 additions and 52 deletions

View File

@ -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;
}

View File

@ -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;