From 30be89fedbad8cb929e8c5c69ebb45171d50a34a Mon Sep 17 00:00:00 2001 From: Lurkars Date: Sun, 12 Jul 2020 14:14:06 +0200 Subject: [PATCH] prepare interface, moved from loop to tasks, replace loops with memcpy, fixed shift_deletion --- README.md | 6 +- main/CMakeLists.txt | 2 +- main/ena-bluetooth-advertise.c | 2 +- main/ena-bluetooth-advertise.h | 2 +- main/ena-bluetooth-scan.c | 46 +++++-------- main/ena-crypto.c | 12 ++-- main/ena-crypto.h | 10 +-- main/ena-detection.c | 5 +- main/ena-detection.h | 2 +- main/ena-interface.c | 65 ++++++++++++++++++ main/ena-interface.h | 43 ++++++++++++ main/ena-storage.c | 122 ++++++++++++++++++--------------- main/ena-storage.h | 37 +++++----- main/ena.c | 117 +++++++++++++++++++------------ main/ena.h | 5 +- main/main.c | 12 +--- 16 files changed, 308 insertions(+), 180 deletions(-) create mode 100644 main/ena-interface.c create mode 100644 main/ena-interface.h diff --git a/README.md b/README.md index 84a1461..ca9a1eb 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,11 @@ Implementation of the Covid-19 Exposure Notification API by Apple and Google on an ESP32 (with ESP-IDF). More information about the Covid-19 Exposure Notification at [Apple](https://www.apple.com/covid19/contacttracing/) and [Google](https://www.google.com/covid19/exposurenotifications/). This is meant for people without smartphone or without smartphones with Apples/Googles implementation. +[Demo Video](https://twitter.com/Lurkars/status/1282223547579019264) + This implementation covers for now the BLE part including the cryptography specifications needed (see Bluetooth Specifications and Cryptography Specifications documents in the links above): * send tokens -* store send tokens on flash (last 14 tokens) +* store TEKs on flash (last 14 tokens) * receive tokens * received tokens are stored after 5 minutes threshold (storage is limited, ~100k tokens can be stored) @@ -23,7 +25,7 @@ Extensions planned: * delete tokens * show status * report infection? -* receive infected token list for Germany (will test [Corona Warn App](https://github.com/corona-warn-app)) +* receive infected token list (will test [Corona Warn App](https://github.com/corona-warn-app)) * send infected status (will test [Corona Warn App](https://github.com/corona-warn-app)) * battery support * 3d print case diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6f979d3..c940d90 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register( - SRCS "ena-detection.c" "ena-storage.c" "ena-crypto.c" "main.c" "ena.c" "ena-bluetooth-scan.c" "ena-bluetooth-advertise.c" "ena-detection.c" + SRCS "ena-detection.c" "ena-storage.c" "ena-crypto.c" "main.c" "ena.c" "ena-bluetooth-scan.c" "ena-bluetooth-advertise.c" "ena-detection.c" "ena-interface.c" INCLUDE_DIRS "" ) diff --git a/main/ena-bluetooth-advertise.c b/main/ena-bluetooth-advertise.c index d5a2215..ea1b1be 100644 --- a/main/ena-bluetooth-advertise.c +++ b/main/ena-bluetooth-advertise.c @@ -19,7 +19,7 @@ void ena_bluetooth_advertise_start(void) ESP_ERROR_CHECK(esp_ble_gap_start_advertising(&ena_adv_params)); } -void ena_bluetooth_advertise_set_payload(uint32_t enin, uint8_t tek[]) +void ena_bluetooth_advertise_set_payload(uint32_t enin, uint8_t *tek) { uint8_t rpik[ENA_KEY_LENGTH] = {0}; uint8_t rpi[ENA_KEY_LENGTH] = {0}; diff --git a/main/ena-bluetooth-advertise.h b/main/ena-bluetooth-advertise.h index a8fc89d..08e5f30 100644 --- a/main/ena-bluetooth-advertise.h +++ b/main/ena-bluetooth-advertise.h @@ -21,7 +21,7 @@ void ena_bluetooth_advertise_start(void); -void ena_bluetooth_advertise_set_payload(uint32_t enin, uint8_t tek[]); +void ena_bluetooth_advertise_set_payload(uint32_t enin, uint8_t *tek); void ena_bluetooth_advertise_stop(void); diff --git a/main/ena-bluetooth-scan.c b/main/ena-bluetooth-scan.c index ff8f2e8..aee5a62 100644 --- a/main/ena-bluetooth-scan.c +++ b/main/ena-bluetooth-scan.c @@ -1,5 +1,4 @@ - -#include +#include #include #include "esp_log.h" @@ -10,6 +9,8 @@ static int scan_status = ENA_SCAN_STATUS_NOT_SCANNING; +static const uint16_t ENA_SERVICE_UUID = 0xFD6F; + static esp_ble_scan_params_t ena_scan_params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, .own_addr_type = BLE_ADDR_TYPE_RANDOM, @@ -34,36 +35,25 @@ void ena_bluetooth_scan_event_callback(esp_gap_ble_cb_event_t event, esp_ble_gap case ESP_GAP_BLE_SCAN_RESULT_EVT: if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { - if (p->scan_rst.adv_data_len < 28) + uint8_t service_uuid_length = 0; + uint8_t *service_uuid_data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, 0x03, &service_uuid_length); + // check for ENA Service UUID + if (service_uuid_length == sizeof(ENA_SERVICE_UUID) && memcmp(service_uuid_data, &ENA_SERVICE_UUID, service_uuid_length) == 0) { - // adv_data too short for exposure notification - break; - } - - int flag_offset = 0; - // received payload from Google does not contain flag specified in Bluetooth Specification!? So check for length and then add offset - if (p->scan_rst.adv_data_len == 31) - { - // data contains flag - flag_offset = 3; - } - - // check for ENA Service UUID: (after flag 0x03 0x03 0x6f 0xfd for ENA service) - if (p->scan_rst.ble_adv[0 + flag_offset] == 0x3 && p->scan_rst.ble_adv[1 + flag_offset] == 0x3 && p->scan_rst.ble_adv[2 + flag_offset] == 0x6f && p->scan_rst.ble_adv[3 + flag_offset] == 0xfd) - { - uint8_t rpi[ENA_KEY_LENGTH] = {0}; - for (int i = 0; i < ENA_KEY_LENGTH; i++) - { - rpi[i] = p->scan_rst.ble_adv[i + 8 + flag_offset]; - } - - uint8_t aem[ENA_AEM_METADATA_LENGTH] = {0}; - for (int i = 0; i < ENA_AEM_METADATA_LENGTH; i++) - { - aem[i] = p->scan_rst.ble_adv[i + ENA_KEY_LENGTH + 8 + flag_offset]; + uint8_t service_data_length = 0; + uint8_t *service_data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, 0x16, &service_data_length); + if (service_data_length != (sizeof(ENA_SERVICE_UUID) + ENA_KEY_LENGTH + ENA_AEM_METADATA_LENGTH)) { + ESP_LOGW(ENA_SCAN_LOG, "received ENA Service with invalid payload"); + break; } + uint8_t *rpi = malloc(ENA_KEY_LENGTH); + memcpy(rpi, &service_data[sizeof(ENA_SERVICE_UUID)], ENA_KEY_LENGTH); + uint8_t *aem = malloc(ENA_AEM_METADATA_LENGTH); + memcpy(aem, &service_data[sizeof(ENA_SERVICE_UUID) + ENA_KEY_LENGTH], ENA_AEM_METADATA_LENGTH); ena_detection((uint32_t)time(NULL), rpi, aem, p->scan_rst.rssi); + free(rpi); + free(aem); } } else if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) diff --git a/main/ena-crypto.c b/main/ena-crypto.c index 65f05e1..f7db6f2 100644 --- a/main/ena-crypto.c +++ b/main/ena-crypto.c @@ -33,7 +33,7 @@ uint32_t ena_crypto_enin(uint32_t unix_epoch_time) return unix_epoch_time / ENA_TIME_WINDOW; } -void ena_crypto_tek(uint8_t tek[]) +void ena_crypto_tek(uint8_t *tek) { int ret; if ((ret = mbedtls_ctr_drbg_random(&ctr_drbg, tek, ENA_KEY_LENGTH)) != 0) @@ -42,15 +42,15 @@ void ena_crypto_tek(uint8_t tek[]) } } -void ena_crypto_rpik(uint8_t rpik[], uint8_t tek[]) +void ena_crypto_rpik(uint8_t *rpik, uint8_t *tek) { const uint8_t rpik_info[] = "EN-RPIK"; mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, tek, ENA_KEY_LENGTH, rpik_info, sizeof(rpik_info), rpik, ENA_KEY_LENGTH); } -void ena_crypto_rpi(uint8_t rpi[], uint8_t rpik[], uint32_t enin) +void ena_crypto_rpi(uint8_t *rpi, uint8_t *rpik, uint32_t enin) { - uint8_t padded_data[ENA_KEY_LENGTH] = "EN-RPI"; + uint8_t padded_data[] = "EN-RPI"; padded_data[12] = (enin & 0x000000ff); padded_data[13] = (enin & 0x0000ff00) >> 8; padded_data[14] = (enin & 0x00ff0000) >> 16; @@ -63,13 +63,13 @@ void ena_crypto_rpi(uint8_t rpi[], uint8_t rpik[], uint32_t enin) mbedtls_aes_free(&aes); } -void ena_crypto_aemk(uint8_t aemk[], uint8_t tek[]) +void ena_crypto_aemk(uint8_t *aemk, uint8_t *tek) { uint8_t aemkInfo[] = "EN-AEMK"; mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, tek, ENA_KEY_LENGTH, aemkInfo, sizeof(aemkInfo), aemk, ENA_KEY_LENGTH); } -void ena_crypto_aem(uint8_t aem[], uint8_t aemk[], uint8_t rpi[], uint8_t power_level) +void ena_crypto_aem(uint8_t *aem, uint8_t *aemk, uint8_t *rpi, uint8_t power_level) { uint8_t metadata[ENA_AEM_METADATA_LENGTH]; metadata[0] = 0b01000000; diff --git a/main/ena-crypto.h b/main/ena-crypto.h index b552f19..8dbbcb3 100644 --- a/main/ena-crypto.h +++ b/main/ena-crypto.h @@ -35,26 +35,26 @@ uint32_t ena_crypto_enin(uint32_t seconds); /** * calculate a new random Temporary Exposure Key (TEK) */ -void ena_crypto_tek(uint8_t tek[]); +void ena_crypto_tek(uint8_t *tek); /** * calculate a new Rolling Proximity Identifier Key (RPIK) with given TEK */ -void ena_crypto_rpik(uint8_t rpik[], uint8_t tek[]); +void ena_crypto_rpik(uint8_t *rpik, uint8_t *tek); /** * calculate a new Rolling Proximity Identifier with given RPIK and ENIN */ -void ena_crypto_rpi(uint8_t rpi[], uint8_t rpik[], uint32_t enin); +void ena_crypto_rpi(uint8_t *rpi, uint8_t *rpik, uint32_t enin); /** * calculate a new Associated Encrypted Metadata Key (AEMK) with given TEK */ -void ena_crypto_aemk(uint8_t aemk[], uint8_t tek[]); +void ena_crypto_aemk(uint8_t *aemk, uint8_t *tek); /** * create Associated Encrypted Metadata (AEM) with given AEMK along the RPI */ -void ena_crypto_aem(uint8_t aem[], uint8_t aemk[], uint8_t rpi[], uint8_t power_level); +void ena_crypto_aem(uint8_t *aem, uint8_t *aemk, uint8_t *rpi, uint8_t power_level); #endif \ No newline at end of file diff --git a/main/ena-detection.c b/main/ena-detection.c index 10e3c5a..5406b9a 100644 --- a/main/ena-detection.c +++ b/main/ena-detection.c @@ -13,7 +13,7 @@ static uint32_t temp_detection_timestamp_first[ENA_STOARGE_TEMP_DETECTIONS_MAX] static uint32_t temp_detection_timestamp_last[ENA_STOARGE_TEMP_DETECTIONS_MAX] = {0}; static int temp_detection_rssi_last[ENA_STOARGE_TEMP_DETECTIONS_MAX] = {0}; -int ena_get_temp_detection_index(uint8_t rpi[], uint8_t aem[]) +int ena_get_temp_detection_index(uint8_t *rpi, uint8_t *aem) { for (int i = 0; i < temp_detections_count; i++) { @@ -53,6 +53,7 @@ void ena_detections_temp_refresh(uint32_t unix_timestamp) for (int i = 0; i < temp_detections_count; i++) { ena_storage_read_temp_detection(i, &temp_detection_timestamp_first[i], temp_detection_rpi[i], temp_detection_aem[i], &temp_detection_rssi_last[i]); + temp_detection_timestamp_last[i] = temp_detection_timestamp_first[i]; } // DEBUG dump @@ -61,7 +62,7 @@ void ena_detections_temp_refresh(uint32_t unix_timestamp) ena_storage_dump_detections(); } -void ena_detection(uint32_t unix_timestamp, uint8_t rpi[], uint8_t aem[], int rssi) +void ena_detection(uint32_t unix_timestamp, uint8_t *rpi, uint8_t *aem, int rssi) { uint32_t detection_index = ena_get_temp_detection_index(rpi, aem); diff --git a/main/ena-detection.h b/main/ena-detection.h index a0caa7e..3a2476a 100644 --- a/main/ena-detection.h +++ b/main/ena-detection.h @@ -14,6 +14,6 @@ void ena_detections_temp_refresh(uint32_t unix_timestamp); -void ena_detection(uint32_t unix_timestamp, uint8_t rpi[], uint8_t aem[], int rssi); +void ena_detection(uint32_t unix_timestamp, uint8_t *rpi, uint8_t *aem, int rssi); #endif \ No newline at end of file diff --git a/main/ena-interface.c b/main/ena-interface.c new file mode 100644 index 0000000..c7d89cd --- /dev/null +++ b/main/ena-interface.c @@ -0,0 +1,65 @@ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "driver/touch_pad.h" +#include "esp_log.h" + +#include "ena-interface.h" + +static int interface_state = ENA_INTERFACE_STATE_MENU; + +static bool touch_status[TOUCH_PAD_MAX] = {0}; +static ena_interface_touch_callback touch_callbacks[TOUCH_PAD_MAX]; + +void ena_interface_register_touch_callback(int touch_pad, ena_interface_touch_callback callback) +{ + touch_callbacks[touch_pad] = callback; +}; + +void ena_interface_run(void *pvParameter) +{ + uint16_t touch_value; + bool touch_status_current[4] = {0}; + while (1) + { + for (int i = 0; i < TOUCH_PAD_MAX; i++) + { + + touch_pad_read_filtered(i, &touch_value); + touch_status_current[i] = touch_value < TOUCHPAD_TOUCH_THRESHOLD; + + if (!touch_status[i] & touch_status_current[i] && touch_callbacks[i] != NULL) + { + (*touch_callbacks[i])(); + } + touch_status[i] = touch_status_current[i]; + } + + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} + +void ena_interface_start(void) +{ + ESP_ERROR_CHECK(touch_pad_init()); + ESP_ERROR_CHECK(touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V)); + ESP_ERROR_CHECK(touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW)); + ESP_ERROR_CHECK(touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD)); + ESP_ERROR_CHECK(touch_pad_config(TOUCH_PAD_ESC, TOUCHPAD_TOUCH_THRESHOLD)); + ESP_ERROR_CHECK(touch_pad_config(TOUCH_PAD_OK, TOUCHPAD_TOUCH_THRESHOLD)); + ESP_ERROR_CHECK(touch_pad_config(TOUCH_PAD_UP, TOUCHPAD_TOUCH_THRESHOLD)); + ESP_ERROR_CHECK(touch_pad_config(TOUCH_PAD_DOWN, TOUCHPAD_TOUCH_THRESHOLD)); + xTaskCreate(&ena_interface_run, "ena_interface_run", configMINIMAL_STACK_SIZE, NULL, 5, NULL); +} + +int ena_interface_get_state(void) +{ + return interface_state; +} + +void ena_interface_set_state(ena_inerface_state state) +{ + interface_state = state; +} diff --git a/main/ena-interface.h b/main/ena-interface.h new file mode 100644 index 0000000..5d7fbb0 --- /dev/null +++ b/main/ena-interface.h @@ -0,0 +1,43 @@ +/** + * Interface for different operations + * + */ +#include "driver/touch_pad.h" + +#ifndef _ena_INTERFACE_H_ +#define _ena_INTERFACE_H_ + +#define ENA_INTERFACE_LOG "ESP-ENA-interface" // TAG for Logging + +#define TOUCHPAD_FILTER_TOUCH_PERIOD (10) +#define TOUCHPAD_TOUCH_THRESHOLD (600) + +#define TOUCH_PAD_ESC (TOUCH_PAD_NUM0) +#define TOUCH_PAD_OK (TOUCH_PAD_NUM6) +#define TOUCH_PAD_UP (TOUCH_PAD_NUM4) +#define TOUCH_PAD_DOWN (TOUCH_PAD_NUM3) + +typedef enum +{ + ENA_INTERFACE_STATE_IDLE = 0, + ENA_INTERFACE_STATE_MENU, + ENA_INTERFACE_STATE_SET_YEAR, + ENA_INTERFACE_STATE_SET_MONTH, + ENA_INTERFACE_STATE_SET_DAY, + ENA_INTERFACE_STATE_SET_HOUR, + ENA_INTERFACE_STATE_SET_MINUTE, + ENA_INTERFACE_STATE_SET_SECONDS, + ENA_INTERFACE_STATE_STATUS, +} ena_inerface_state; + +typedef void (*ena_interface_touch_callback)(void); + +void ena_interface_register_touch_callback(int touch_pad, ena_interface_touch_callback callback); + +int ena_interface_get_state(void); + +void ena_interface_set_state(ena_inerface_state state); + +void ena_interface_start(void); + +#endif \ No newline at end of file diff --git a/main/ena-storage.c b/main/ena-storage.c index 46155af..2ea426e 100644 --- a/main/ena-storage.c +++ b/main/ena-storage.c @@ -23,7 +23,7 @@ void ena_storage_read(size_t address, uint8_t *data, size_t size) ESP_LOGD(ENA_STORAGE_LOG, "END ena_storage_read"); } -void ena_storage_write(size_t address, uint8_t data[], size_t size) +void ena_storage_write(size_t address, uint8_t *data, size_t size) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write"); const esp_partition_t *partition = esp_partition_find_first( @@ -36,7 +36,7 @@ void ena_storage_write(size_t address, uint8_t data[], size_t size) if (address + size > (block_num + 1) * BLOCK_SIZE) { - ESP_LOGI(ENA_STORAGE_LOG, "overflow block at address %u with size %d (block %d)", address, size, block_num); + ESP_LOGD(ENA_STORAGE_LOG, "overflow block at address %u with size %d (block %d)", address, size, block_num); const size_t block1_address = address; const size_t block2_address = (block_num + 1) * BLOCK_SIZE; const size_t data2_size = address + size - block2_address; @@ -44,18 +44,12 @@ void ena_storage_write(size_t address, uint8_t data[], size_t size) ESP_LOGD(ENA_STORAGE_LOG, "block1_address %d, block1_size %d (block %d)", block1_address, data1_size, block_num); ESP_LOGD(ENA_STORAGE_LOG, "block2_address %d, block2_size %d (block %d)", block2_address, data2_size, block_num + 1); uint8_t *data1 = malloc(data1_size); - for (int i = 0; i < data1_size; i++) - { - data1[i] = data[i]; - } - uint8_t *data2 = malloc(data2_size); - for (int i = 0; i < data2_size; i++) - { - data2[i] = data[data1_size + i]; - } - + memcpy(data1, data, data1_size); ena_storage_write(block1_address, data1, data1_size); free(data1); + + uint8_t *data2 = malloc(data2_size); + memcpy(data2, &data[data1_size], data2_size); ena_storage_write(block2_address, data2, data2_size); free(data2); } @@ -74,10 +68,8 @@ void ena_storage_write(size_t address, uint8_t data[], size_t size) vTaskDelay(1); ESP_ERROR_CHECK(esp_partition_erase_range(partition, block_start, BLOCK_SIZE)); - for (int i = 0; i < size; i++) - { - buffer[block_address + i] = data[i]; - } + memcpy(&buffer[block_address], data, size); + ESP_ERROR_CHECK(esp_partition_write(partition, block_start, buffer, BLOCK_SIZE)); free(buffer); ESP_LOGD(ENA_STORAGE_LOG, "write data at %u", address); @@ -86,53 +78,69 @@ void ena_storage_write(size_t address, uint8_t data[], size_t size) ESP_LOGD(ENA_STORAGE_LOG, "END ena_storage_write"); } -void ena_storage_shift_delete(size_t address, size_t size) +void ena_storage_shift_delete(size_t address, size_t end_address, size_t size) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_shift_delete"); - const esp_partition_t *partition = esp_partition_find_first( - ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); - assert(partition); - const int block_num = address / BLOCK_SIZE; - - // split if size extends block TODO this does not work like this!!! Shift puts data back to first block! - if (address + size > (block_num + 1) * BLOCK_SIZE) + int block_num_start = address / BLOCK_SIZE; + // split if size extends block + if (address + size > (block_num_start + 1) * BLOCK_SIZE) { - const int block1_address = address; - const int block2_address = (block_num + 1) * BLOCK_SIZE; - const int data2_size = address + size - block2_address; - const int data1_size = size - data2_size; - ena_storage_shift_delete(block1_address, data1_size); - ena_storage_shift_delete(block2_address, data2_size); + ESP_LOGD(ENA_STORAGE_LOG, "overflow block at address %u with size %d (block %d)", address, size, block_num_start); + const size_t block1_address = address; + const size_t block2_address = (block_num_start + 1) * BLOCK_SIZE; + const size_t data2_size = address + size - block2_address; + const size_t data1_size = size - data2_size; + ena_storage_shift_delete(block1_address, end_address, data1_size); + ena_storage_shift_delete(block2_address, end_address - data1_size, data2_size); } else { - const int block_start = block_num * BLOCK_SIZE; - const int block_address = address - block_start; - uint8_t *buffer = malloc(BLOCK_SIZE); - ESP_ERROR_CHECK(esp_partition_read(partition, block_start, buffer, BLOCK_SIZE)); - vTaskDelay(1); - ESP_LOGD(ENA_STORAGE_LOG, "shift block from %u to %u with size %u (move %u)", block_address, block_address + size, size, BLOCK_SIZE - address + size); - // shift manually - for (int i = block_address + size; i < BLOCK_SIZE; i++) - { - buffer[i - size] = buffer[i]; - } + const esp_partition_t *partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(partition); - for (int i = BLOCK_SIZE - size; i < BLOCK_SIZE; i++) + int block_num_end = end_address / BLOCK_SIZE; + size_t block_start = address - block_num_start * BLOCK_SIZE; + while (block_num_end >= block_num_start) { - buffer[i] = 0; + + uint8_t *buffer = malloc(BLOCK_SIZE); + ESP_ERROR_CHECK(esp_partition_read(partition, block_num_start * BLOCK_SIZE, buffer, BLOCK_SIZE)); + vTaskDelay(1); + // shift inside buffer + ESP_LOGD(ENA_STORAGE_LOG, "shift block %d from %u to %u with size %u", block_num_start, (block_start + size), block_start, (BLOCK_SIZE - block_start - size)); + memcpy(&buffer[block_start], &buffer[block_start + size], BLOCK_SIZE - block_start - size); + if (block_num_end > block_num_start) + { + uint8_t *buffer_next_block = malloc(BLOCK_SIZE); + + ESP_ERROR_CHECK(esp_partition_read(partition, (block_num_start + 1) * BLOCK_SIZE, buffer_next_block, BLOCK_SIZE)); + vTaskDelay(1); + // shift from next block + ESP_LOGD(ENA_STORAGE_LOG, "shift next block size %u", size); + memcpy(&buffer[BLOCK_SIZE - size], &buffer_next_block[0], size); + free(buffer_next_block); + } + else + { + // fill end with zeros + ESP_LOGD(ENA_STORAGE_LOG, "fill with zeros %u", size); + memset(&buffer[BLOCK_SIZE - size], 0, size); + } + + ESP_ERROR_CHECK(esp_partition_erase_range(partition, block_num_start * BLOCK_SIZE, BLOCK_SIZE)); + ESP_ERROR_CHECK(esp_partition_write(partition, block_num_start * BLOCK_SIZE, buffer, BLOCK_SIZE)); + free(buffer); + + block_num_start++; + block_start = 0; } - // memmove seems to lead to corrupt heap memory! - // memmove(&buffer[block_address], &buffer[block_address + size], BLOCK_SIZE - address + size); - ESP_ERROR_CHECK(esp_partition_erase_range(partition, block_start, BLOCK_SIZE)); - ESP_ERROR_CHECK(esp_partition_write(partition, block_start, buffer, BLOCK_SIZE)); - free(buffer); } ESP_LOGD(ENA_STORAGE_LOG, "END ena_storage_shift_delete"); } -void ena_storage_write_tek(uint32_t enin, uint8_t tek[]) +void ena_storage_write_tek(uint32_t enin, uint8_t *tek) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write_tek"); uint8_t tek_count = ena_storage_read_u8(ENA_STORAGE_TEK_COUNT_ADDRESS); @@ -169,7 +177,7 @@ uint32_t ena_storage_read_enin(void) return result; } -void ena_storage_read_tek(uint8_t tek[]) +void ena_storage_read_tek(uint8_t *tek) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_read_tek"); uint8_t tek_count = ena_storage_read_u8(ENA_STORAGE_TEK_COUNT_ADDRESS); @@ -195,7 +203,7 @@ uint32_t ena_storage_temp_detections_count(void) return count; } -uint32_t ena_storage_write_temp_detection(uint32_t timestamp, uint8_t rpi[], uint8_t aem[], int rssi) +uint32_t ena_storage_write_temp_detection(uint32_t timestamp, uint8_t *rpi, uint8_t *aem, int rssi) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write_temp_detection"); uint32_t count = ena_storage_temp_detections_count() + 1; @@ -224,7 +232,7 @@ uint32_t ena_storage_write_temp_detection(uint32_t timestamp, uint8_t rpi[], uin return count - 1; } -void ena_storage_read_temp_detection(uint32_t index, uint32_t *timestamp, uint8_t rpi[], uint8_t aem[], int *rssi) +void ena_storage_read_temp_detection(uint32_t index, uint32_t *timestamp, uint8_t *rpi, uint8_t *aem, int *rssi) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_read_temp_detection"); size_t address = ENA_STORAGE_TEMP_DETECTIONS_START_ADDRESS + index * ENA_STORAGE_DETECTION_LENGTH; @@ -247,9 +255,9 @@ void ena_storage_remove_temp_detection(uint32_t index) ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_remove_temp_detection"); size_t address = ENA_STORAGE_TEMP_DETECTIONS_START_ADDRESS + index * ENA_STORAGE_DETECTION_LENGTH; - ena_storage_shift_delete(address, ENA_STORAGE_DETECTION_LENGTH); - uint32_t count = ena_storage_temp_detections_count(); + ena_storage_shift_delete(address, ENA_STORAGE_TEMP_DETECTIONS_START_ADDRESS + count * ENA_STORAGE_DETECTION_LENGTH, ENA_STORAGE_DETECTION_LENGTH); + count--; ena_storage_write_u32(ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS, count); ESP_LOGD(ENA_STORAGE_LOG, "remove temp detection: %u", index); @@ -265,7 +273,7 @@ uint32_t ena_storage_detections_count(void) return count; } -void ena_storage_write_detection(uint32_t timestamp, uint8_t rpi[], uint8_t aem[], int rssi) +void ena_storage_write_detection(uint32_t timestamp, uint8_t *rpi, uint8_t *aem, int rssi) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write_detection"); ESP_LOG_BUFFER_HEXDUMP(ENA_STORAGE_LOG, rpi, ENA_KEY_LENGTH, ESP_LOG_DEBUG); @@ -286,7 +294,7 @@ void ena_storage_write_detection(uint32_t timestamp, uint8_t rpi[], uint8_t aem[ ESP_LOGD(ENA_STORAGE_LOG, "END ena_storage_write_detection"); } -void ena_storage_read_detection(uint32_t index, uint32_t *timestamp, uint8_t rpi[], uint8_t aem[], int *rssi) +void ena_storage_read_detection(uint32_t index, uint32_t *timestamp, uint8_t *rpi, uint8_t *aem, int *rssi) { ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_read_detection"); size_t address = ENA_STORAGE_DETECTIONS_START_ADDRESS + index * ENA_STORAGE_DETECTION_LENGTH; @@ -374,7 +382,7 @@ void ena_storage_erase(void) ESP_LOGD(ENA_STORAGE_LOG, "END ena_storage_erase"); } -void ena_storage_dump_hash_array(uint8_t data[], size_t size) +void ena_storage_dump_hash_array(uint8_t *data, size_t size) { for (int i = 0; i < size; i++) { diff --git a/main/ena-storage.h b/main/ena-storage.h index 3a5d68f..7fe55fd 100644 --- a/main/ena-storage.h +++ b/main/ena-storage.h @@ -5,17 +5,16 @@ #define ENA_STORAGE_LOG "ESP-ENA-storage" // TAG for Logging #define PARTITION_NAME "ena" -#define ENA_STOARGE_TEK_STORE_PERIOD (14) // Period of storing TEKs -#define ENA_STORAGE_TEK_COUNT_ADDRESS (0) // starting address for TEK COUNT -#define ENA_STORAGE_TEK_START_ADDRESS (ENA_STORAGE_TEK_COUNT_ADDRESS + 1) // starting address for TEKs -#define ENA_STORAGE_TEK_LENGTH (ENA_KEY_LENGTH + 4) // length of a stored TEK -> TEK keysize + 4 Bytes for ENIN -#define ENA_STORAGE_DETECTION_LENGTH (ENA_KEY_LENGTH + ENA_AEM_METADATA_LENGTH + 4 + sizeof(int)) // length of a stored detection -> RPI keysize + AEM size + 4 Bytes for ENIN + 4 Bytes for RSSI -#define ENA_STOARGE_TEMP_DETECTIONS_MAX (1000) // Maximum number of temporary stored detections -#define ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS (ENA_STORAGE_TEK_START_ADDRESS + ENA_STORAGE_TEK_LENGTH * ENA_STOARGE_TEK_STORE_PERIOD) // starting address for temporary detections COUNT (offset from max. stored TEKs) -#define ENA_STORAGE_TEMP_DETECTIONS_START_ADDRESS (ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS + 4) // starting address for temporary detections +#define ENA_STOARGE_TEK_STORE_PERIOD (14) // Period of storing TEKs +#define ENA_STORAGE_TEK_COUNT_ADDRESS (0) // starting address for TEK COUNT +#define ENA_STORAGE_TEK_START_ADDRESS (ENA_STORAGE_TEK_COUNT_ADDRESS + 1) // starting address for TEKs +#define ENA_STORAGE_TEK_LENGTH (ENA_KEY_LENGTH + 4) // length of a stored TEK -> TEK keysize + 4 Bytes for ENIN +#define ENA_STORAGE_DETECTION_LENGTH (ENA_KEY_LENGTH + ENA_AEM_METADATA_LENGTH + 4 + sizeof(int)) // length of a stored detection -> RPI keysize + AEM size + 4 Bytes for ENIN + 4 Bytes for RSSI +#define ENA_STOARGE_TEMP_DETECTIONS_MAX (1000) // Maximum number of temporary stored detections +#define ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS (ENA_STORAGE_TEK_START_ADDRESS + ENA_STORAGE_TEK_LENGTH * ENA_STOARGE_TEK_STORE_PERIOD) // starting address for temporary detections COUNT (offset from max. stored TEKs) +#define ENA_STORAGE_TEMP_DETECTIONS_START_ADDRESS (ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS + 4) // starting address for temporary detections #define ENA_STORAGE_DETECTIONS_COUNT_ADDRESS (ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS + ENA_STORAGE_DETECTION_LENGTH * ENA_STOARGE_TEMP_DETECTIONS_MAX) // starting address for detections COUNT (offset from max. stored temporary detections) -#define ENA_STORAGE_DETECTIONS_START_ADDRESS (ENA_STORAGE_DETECTIONS_COUNT_ADDRESS + 4) // starting address of detections - +#define ENA_STORAGE_DETECTIONS_START_ADDRESS (ENA_STORAGE_DETECTIONS_COUNT_ADDRESS + 4) // starting address of detections /** * read bytes at given address @@ -25,17 +24,17 @@ void ena_storage_read(size_t address, uint8_t *data, size_t size); /** * store bytes at given address */ -void ena_storage_write(size_t address, uint8_t data[], size_t size); +void ena_storage_write(size_t address, uint8_t *data, size_t size); /** * deletes bytes at given address and shift other data back */ -void ena_storage_shift_delete(size_t address, size_t size); +void ena_storage_shift_delete(size_t address, size_t end_address, size_t size); /** * store TEK with ENIN */ -void ena_storage_write_tek(uint32_t enin, uint8_t tek[]); +void ena_storage_write_tek(uint32_t enin, uint8_t *tek); /** * get last stored ENIN @@ -45,7 +44,7 @@ uint32_t ena_storage_read_enin(void); /** * get last stored TEK */ -void ena_storage_read_tek(uint8_t tek[]); +void ena_storage_read_tek(uint8_t *tek); /** * get number of stored temporary detections @@ -57,12 +56,12 @@ uint32_t ena_storage_temp_detections_count(void); * * returns index */ -uint32_t ena_storage_write_temp_detection(uint32_t timestamp, uint8_t rpi[], uint8_t aem[], int rssi); +uint32_t ena_storage_write_temp_detection(uint32_t timestamp, uint8_t *rpi, uint8_t *aem, int rssi); /** * get temporary detection (RPI + AEM + RSSI with UNIX timestamp) at given index */ -void ena_storage_read_temp_detection(uint32_t index, uint32_t *timestamp, uint8_t rpi[], uint8_t aem[], int *rssi); +void ena_storage_read_temp_detection(uint32_t index, uint32_t *timestamp, uint8_t *rpi, uint8_t *aem, int *rssi); /** * remove temporary detection at given index @@ -77,12 +76,12 @@ uint32_t ena_storage_detections_count(void); /** * store detection (RPI + AEM + RSSI with ENIN) */ -void ena_storage_write_detection(uint32_t timestamp, uint8_t rpi[], uint8_t aem[], int rssi); +void ena_storage_write_detection(uint32_t timestamp, uint8_t *rpi, uint8_t *aem, int rssi); /** * get detection (RPI + AEM + RSSI with ENIN) at given index */ -void ena_storage_read_detection(uint32_t index, uint32_t *enin, uint8_t rpi[], uint8_t aem[], int *rssi); +void ena_storage_read_detection(uint32_t index, uint32_t *enin, uint8_t *rpi, uint8_t *aem, int *rssi); uint8_t ena_storage_read_u8(size_t address); @@ -100,7 +99,7 @@ void ena_storage_erase(void); void ena_storage_dump_tek(void); -void ena_storage_dump_temp_detections(void); +void ena_storage_dump_temp_detections(void); void ena_storage_dump_detections(void); diff --git a/main/ena.c b/main/ena.c index 65ba6e9..0dfdc8b 100644 --- a/main/ena.c +++ b/main/ena.c @@ -2,6 +2,10 @@ #include #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" + #include "esp_system.h" #include "esp_log.h" #include "esp_bt.h" @@ -20,7 +24,49 @@ static uint32_t last_enin; // last ENIN static uint8_t tek[ENA_KEY_LENGTH] = {0}; // current TEK -void ena_init(void) +void ena_run(void *pvParameter) +{ + uint32_t unix_timestamp = 0; + uint32_t current_enin = 0; + while (1) + { + unix_timestamp = (uint32_t)time(NULL); + current_enin = ena_crypto_enin(unix_timestamp); + if (current_enin - last_enin >= ENA_TEK_ROLLING_PERIOD) + { + ena_crypto_tek(tek); + ena_storage_write_tek(current_enin, tek); + last_enin = current_enin; + } + + // change RPI + if (unix_timestamp % ENA_TIME_WINDOW == 0) + { + if (ena_bluetooth_scan_get_status() == ENA_SCAN_STATUS_SCANNING) + { + ena_bluetooth_scan_stop(); + } + ena_bluetooth_advertise_stop(); + ena_bluetooth_advertise_set_payload(current_enin, tek); + ena_bluetooth_advertise_start(); + if (ena_bluetooth_scan_get_status() == ENA_SCAN_STATUS_WAITING) + { + ena_bluetooth_scan_start(ENA_SCANNING_TIME); + } + } + + // scan + if (unix_timestamp % ENA_SCANNING_INTERVAL == 0 && ena_bluetooth_scan_get_status() == ENA_SCAN_STATUS_NOT_SCANNING) + { + ena_bluetooth_scan_start(ENA_SCANNING_TIME); + } + + // one second loop correct?! + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +void ena_start(void) { // init NVS for BLE esp_err_t ret; @@ -30,13 +76,30 @@ void ena_init(void) ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_init()); } - // init BLE - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); - ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); - ESP_ERROR_CHECK(esp_bluedroid_init()); - ESP_ERROR_CHECK(esp_bluedroid_enable()); + // init BLE + if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) + { + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); + while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) + { + } + } + + if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED) + { + ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); + } + + if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) + { + ESP_ERROR_CHECK(esp_bluedroid_init()); + } + if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_INITIALIZED) + { + ESP_ERROR_CHECK(esp_bluedroid_enable()); + } // new bluetooth address nesseccary? uint8_t bt_address[ESP_BD_ADDR_LEN]; @@ -77,41 +140,7 @@ void ena_init(void) ena_bluetooth_advertise_start(); // initial scan on every start ena_bluetooth_scan_start(ENA_SCANNING_TIME); -} - -void ena_run(void) -{ - uint32_t unix_timestamp = (uint32_t)time(NULL); - uint32_t current_enin = ena_crypto_enin(unix_timestamp); - if (current_enin - last_enin >= ENA_TEK_ROLLING_PERIOD) - { - ena_crypto_tek(tek); - ena_storage_write_tek(current_enin, tek); - last_enin = current_enin; - } - - // change RPI - if (unix_timestamp % ENA_TIME_WINDOW == 0) - { - - // - - if (ena_bluetooth_scan_get_status() == ENA_SCAN_STATUS_SCANNING) - { - ena_bluetooth_scan_stop(); - } - ena_bluetooth_advertise_stop(); - ena_bluetooth_advertise_set_payload(current_enin, tek); - ena_bluetooth_advertise_start(); - if (ena_bluetooth_scan_get_status() == ENA_SCAN_STATUS_WAITING) - { - ena_bluetooth_scan_start(ENA_SCANNING_TIME); - } - } - - // scan - if (unix_timestamp % ENA_SCANNING_INTERVAL == 0 && ena_bluetooth_scan_get_status() == ENA_SCAN_STATUS_NOT_SCANNING) - { - ena_bluetooth_scan_start(ENA_SCANNING_TIME); - } + + // what is a good stack size here? + xTaskCreate(&ena_run, "ena_run", configMINIMAL_STACK_SIZE * 4, NULL, 5, NULL); } diff --git a/main/ena.h b/main/ena.h index ab53df2..2d01734 100644 --- a/main/ena.h +++ b/main/ena.h @@ -6,11 +6,8 @@ #ifndef _ena_H_ #define _ena_H_ - #define ENA_LOG "ESP-ENA" // TAG for Logging -void ena_init(void); - -void ena_run(void); +void ena_start(void); #endif \ No newline at end of file diff --git a/main/main.c b/main/main.c index 2abf6be..652fccf 100644 --- a/main/main.c +++ b/main/main.c @@ -21,6 +21,7 @@ #include "ena.h" #include "ena-storage.h" +#include "ena-interface.h" #include "sdkconfig.h" @@ -33,13 +34,6 @@ void app_main(void) esp_log_level_set(ENA_STORAGE_LOG, ESP_LOG_INFO); ena_storage_erase(); // only needed on first start! TODO automatically check - ena_init(); - - // one second loop enough? - while (1) - { - ena_run(); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } + ena_interface_start(); + ena_start(); } -