prepare interface, moved from loop to tasks, replace loops with memcpy, fixed shift_deletion

This commit is contained in:
Lurkars 2020-07-12 14:14:06 +02:00
parent 7bdbe82914
commit 30be89fedb
16 changed files with 308 additions and 180 deletions

View File

@ -5,9 +5,11 @@
Implementation of the Covid-19 Exposure Notification API by Apple and Google on an ESP32 (with ESP-IDF). 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. 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): 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 * send tokens
* store send tokens on flash (last 14 tokens) * store TEKs on flash (last 14 tokens)
* receive tokens * receive tokens
* received tokens are stored after 5 minutes threshold (storage is limited, ~100k tokens can be stored) * received tokens are stored after 5 minutes threshold (storage is limited, ~100k tokens can be stored)
@ -23,7 +25,7 @@ Extensions planned:
* delete tokens * delete tokens
* show status * show status
* report infection? * 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)) * send infected status (will test [Corona Warn App](https://github.com/corona-warn-app))
* battery support * battery support
* 3d print case * 3d print case

View File

@ -1,4 +1,4 @@
idf_component_register( 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 "" INCLUDE_DIRS ""
) )

View File

@ -19,7 +19,7 @@ void ena_bluetooth_advertise_start(void)
ESP_ERROR_CHECK(esp_ble_gap_start_advertising(&ena_adv_params)); 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 rpik[ENA_KEY_LENGTH] = {0};
uint8_t rpi[ENA_KEY_LENGTH] = {0}; uint8_t rpi[ENA_KEY_LENGTH] = {0};

View File

@ -21,7 +21,7 @@
void ena_bluetooth_advertise_start(void); 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); void ena_bluetooth_advertise_stop(void);

View File

@ -1,5 +1,4 @@
#include <string.h>
#include <stdio.h>
#include <time.h> #include <time.h>
#include "esp_log.h" #include "esp_log.h"
@ -10,6 +9,8 @@
static int scan_status = ENA_SCAN_STATUS_NOT_SCANNING; 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 = { static esp_ble_scan_params_t ena_scan_params = {
.scan_type = BLE_SCAN_TYPE_ACTIVE, .scan_type = BLE_SCAN_TYPE_ACTIVE,
.own_addr_type = BLE_ADDR_TYPE_RANDOM, .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: case ESP_GAP_BLE_SCAN_RESULT_EVT:
if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_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 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; break;
} }
int flag_offset = 0; uint8_t *rpi = malloc(ENA_KEY_LENGTH);
// received payload from Google does not contain flag specified in Bluetooth Specification!? So check for length and then add offset memcpy(rpi, &service_data[sizeof(ENA_SERVICE_UUID)], ENA_KEY_LENGTH);
if (p->scan_rst.adv_data_len == 31) uint8_t *aem = malloc(ENA_AEM_METADATA_LENGTH);
{ memcpy(aem, &service_data[sizeof(ENA_SERVICE_UUID) + ENA_KEY_LENGTH], ENA_AEM_METADATA_LENGTH);
// 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];
}
ena_detection((uint32_t)time(NULL), rpi, aem, p->scan_rst.rssi); 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) else if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT)

View File

@ -33,7 +33,7 @@ uint32_t ena_crypto_enin(uint32_t unix_epoch_time)
return unix_epoch_time / ENA_TIME_WINDOW; return unix_epoch_time / ENA_TIME_WINDOW;
} }
void ena_crypto_tek(uint8_t tek[]) void ena_crypto_tek(uint8_t *tek)
{ {
int ret; int ret;
if ((ret = mbedtls_ctr_drbg_random(&ctr_drbg, tek, ENA_KEY_LENGTH)) != 0) 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"; 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); 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[12] = (enin & 0x000000ff);
padded_data[13] = (enin & 0x0000ff00) >> 8; padded_data[13] = (enin & 0x0000ff00) >> 8;
padded_data[14] = (enin & 0x00ff0000) >> 16; 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); 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"; 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); 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]; uint8_t metadata[ENA_AEM_METADATA_LENGTH];
metadata[0] = 0b01000000; metadata[0] = 0b01000000;

View File

@ -35,26 +35,26 @@ uint32_t ena_crypto_enin(uint32_t seconds);
/** /**
* calculate a new random Temporary Exposure Key (TEK) * 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 * 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 * 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 * 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 * 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 #endif

View File

@ -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 uint32_t temp_detection_timestamp_last[ENA_STOARGE_TEMP_DETECTIONS_MAX] = {0};
static int temp_detection_rssi_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++) 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++) 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]); 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 // DEBUG dump
@ -61,7 +62,7 @@ void ena_detections_temp_refresh(uint32_t unix_timestamp)
ena_storage_dump_detections(); 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); uint32_t detection_index = ena_get_temp_detection_index(rpi, aem);

View File

@ -14,6 +14,6 @@
void ena_detections_temp_refresh(uint32_t unix_timestamp); 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 #endif

65
main/ena-interface.c Normal file
View File

@ -0,0 +1,65 @@
#include <stdio.h>
#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;
}

43
main/ena-interface.h Normal file
View File

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

View File

@ -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"); 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"); ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write");
const esp_partition_t *partition = esp_partition_find_first( 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) 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 block1_address = address;
const size_t block2_address = (block_num + 1) * BLOCK_SIZE; const size_t block2_address = (block_num + 1) * BLOCK_SIZE;
const size_t data2_size = address + size - block2_address; 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, "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); 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); uint8_t *data1 = malloc(data1_size);
for (int i = 0; i < data1_size; i++) memcpy(data1, data, data1_size);
{
data1[i] = data[i];
}
uint8_t *data2 = malloc(data2_size);
for (int i = 0; i < data2_size; i++)
{
data2[i] = data[data1_size + i];
}
ena_storage_write(block1_address, data1, data1_size); ena_storage_write(block1_address, data1, data1_size);
free(data1); free(data1);
uint8_t *data2 = malloc(data2_size);
memcpy(data2, &data[data1_size], data2_size);
ena_storage_write(block2_address, data2, data2_size); ena_storage_write(block2_address, data2, data2_size);
free(data2); free(data2);
} }
@ -74,10 +68,8 @@ void ena_storage_write(size_t address, uint8_t data[], size_t size)
vTaskDelay(1); vTaskDelay(1);
ESP_ERROR_CHECK(esp_partition_erase_range(partition, block_start, BLOCK_SIZE)); ESP_ERROR_CHECK(esp_partition_erase_range(partition, block_start, BLOCK_SIZE));
for (int i = 0; i < size; i++) memcpy(&buffer[block_address], data, size);
{
buffer[block_address + i] = data[i];
}
ESP_ERROR_CHECK(esp_partition_write(partition, block_start, buffer, BLOCK_SIZE)); ESP_ERROR_CHECK(esp_partition_write(partition, block_start, buffer, BLOCK_SIZE));
free(buffer); free(buffer);
ESP_LOGD(ENA_STORAGE_LOG, "write data at %u", address); 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"); 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"); ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_shift_delete");
int block_num_start = address / BLOCK_SIZE;
// split if size extends block
if (address + size > (block_num_start + 1) * BLOCK_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 esp_partition_t *partition = esp_partition_find_first( const esp_partition_t *partition = esp_partition_find_first(
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME);
assert(partition); assert(partition);
const int block_num = address / BLOCK_SIZE; int block_num_end = end_address / BLOCK_SIZE;
size_t block_start = address - block_num_start * BLOCK_SIZE;
// split if size extends block TODO this does not work like this!!! Shift puts data back to first block! while (block_num_end >= block_num_start)
if (address + size > (block_num + 1) * BLOCK_SIZE)
{ {
const int block1_address = address;
const int block2_address = (block_num + 1) * BLOCK_SIZE; uint8_t *buffer = malloc(BLOCK_SIZE);
const int data2_size = address + size - block2_address; ESP_ERROR_CHECK(esp_partition_read(partition, block_num_start * BLOCK_SIZE, buffer, BLOCK_SIZE));
const int data1_size = size - data2_size; vTaskDelay(1);
ena_storage_shift_delete(block1_address, data1_size); // shift inside buffer
ena_storage_shift_delete(block2_address, data2_size); 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 else
{ {
const int block_start = block_num * BLOCK_SIZE; // fill end with zeros
const int block_address = address - block_start; ESP_LOGD(ENA_STORAGE_LOG, "fill with zeros %u", size);
uint8_t *buffer = malloc(BLOCK_SIZE); memset(&buffer[BLOCK_SIZE - size], 0, 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];
} }
for (int i = BLOCK_SIZE - size; i < BLOCK_SIZE; i++) 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));
buffer[i] = 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); free(buffer);
block_num_start++;
block_start = 0;
}
} }
ESP_LOGD(ENA_STORAGE_LOG, "END ena_storage_shift_delete"); 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"); ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write_tek");
uint8_t tek_count = ena_storage_read_u8(ENA_STORAGE_TEK_COUNT_ADDRESS); 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; 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"); ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_read_tek");
uint8_t tek_count = ena_storage_read_u8(ENA_STORAGE_TEK_COUNT_ADDRESS); 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; 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"); ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_write_temp_detection");
uint32_t count = ena_storage_temp_detections_count() + 1; 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; 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"); 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; 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"); 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; 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(); 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--; count--;
ena_storage_write_u32(ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS, count); ena_storage_write_u32(ENA_STORAGE_TEMP_DETECTIONS_COUNT_ADDRESS, count);
ESP_LOGD(ENA_STORAGE_LOG, "remove temp detection: %u", index); ESP_LOGD(ENA_STORAGE_LOG, "remove temp detection: %u", index);
@ -265,7 +273,7 @@ uint32_t ena_storage_detections_count(void)
return count; 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_LOGD(ENA_STORAGE_LOG, "START ena_storage_write_detection");
ESP_LOG_BUFFER_HEXDUMP(ENA_STORAGE_LOG, rpi, ENA_KEY_LENGTH, ESP_LOG_DEBUG); 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"); 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"); ESP_LOGD(ENA_STORAGE_LOG, "START ena_storage_read_detection");
size_t address = ENA_STORAGE_DETECTIONS_START_ADDRESS + index * ENA_STORAGE_DETECTION_LENGTH; 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"); 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++) for (int i = 0; i < size; i++)
{ {

View File

@ -16,7 +16,6 @@
#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_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 * 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 * 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 * 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 * 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 * get last stored ENIN
@ -45,7 +44,7 @@ uint32_t ena_storage_read_enin(void);
/** /**
* get last stored TEK * 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 * get number of stored temporary detections
@ -57,12 +56,12 @@ uint32_t ena_storage_temp_detections_count(void);
* *
* returns index * 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 * 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 * remove temporary detection at given index
@ -77,12 +76,12 @@ uint32_t ena_storage_detections_count(void);
/** /**
* store detection (RPI + AEM + RSSI with ENIN) * 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 * 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); uint8_t ena_storage_read_u8(size_t address);

View File

@ -2,6 +2,10 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_bt.h" #include "esp_bt.h"
@ -20,7 +24,49 @@
static uint32_t last_enin; // last ENIN static uint32_t last_enin; // last ENIN
static uint8_t tek[ENA_KEY_LENGTH] = {0}; // current TEK 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 // init NVS for BLE
esp_err_t ret; esp_err_t ret;
@ -30,13 +76,30 @@ void ena_init(void)
ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_erase());
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
} }
// init BLE // 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_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_init(&bt_cfg));
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); 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()); ESP_ERROR_CHECK(esp_bluedroid_init());
}
if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_INITIALIZED)
{
ESP_ERROR_CHECK(esp_bluedroid_enable()); ESP_ERROR_CHECK(esp_bluedroid_enable());
}
// new bluetooth address nesseccary? // new bluetooth address nesseccary?
uint8_t bt_address[ESP_BD_ADDR_LEN]; uint8_t bt_address[ESP_BD_ADDR_LEN];
@ -77,41 +140,7 @@ void ena_init(void)
ena_bluetooth_advertise_start(); ena_bluetooth_advertise_start();
// initial scan on every start // initial scan on every start
ena_bluetooth_scan_start(ENA_SCANNING_TIME); ena_bluetooth_scan_start(ENA_SCANNING_TIME);
}
// what is a good stack size here?
void ena_run(void) xTaskCreate(&ena_run, "ena_run", configMINIMAL_STACK_SIZE * 4, NULL, 5, NULL);
{
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);
}
} }

View File

@ -6,11 +6,8 @@
#ifndef _ena_H_ #ifndef _ena_H_
#define _ena_H_ #define _ena_H_
#define ENA_LOG "ESP-ENA" // TAG for Logging #define ENA_LOG "ESP-ENA" // TAG for Logging
void ena_init(void); void ena_start(void);
void ena_run(void);
#endif #endif

View File

@ -21,6 +21,7 @@
#include "ena.h" #include "ena.h"
#include "ena-storage.h" #include "ena-storage.h"
#include "ena-interface.h"
#include "sdkconfig.h" #include "sdkconfig.h"
@ -33,13 +34,6 @@ void app_main(void)
esp_log_level_set(ENA_STORAGE_LOG, ESP_LOG_INFO); esp_log_level_set(ENA_STORAGE_LOG, ESP_LOG_INFO);
ena_storage_erase(); // only needed on first start! TODO automatically check ena_storage_erase(); // only needed on first start! TODO automatically check
ena_init(); ena_interface_start();
ena_start();
// one second loop enough?
while (1)
{
ena_run();
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
} }