mirror of
https://github.com/CovidBraceletPrj/CovidBracelet.git
synced 2024-12-04 16:45:43 +01:00
Add platformIO files and adapt file structure
This commit is contained in:
parent
bd01478bd8
commit
760ceca785
46
.gitignore
vendored
46
.gitignore
vendored
@ -1 +1,47 @@
|
||||
build/
|
||||
|
||||
# Random seed file created by test scripts and sample programs
|
||||
seedfile
|
||||
|
||||
# CMake build artifacts:
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CTestTestfile.cmake
|
||||
cmake_install.cmake
|
||||
Testing
|
||||
# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those:
|
||||
*.dir/
|
||||
# MSVC files generated by CMake:
|
||||
/*.sln
|
||||
/*.vcxproj
|
||||
/*.filters
|
||||
|
||||
# Test coverage build artifacts:
|
||||
Coverage
|
||||
*.gcno
|
||||
*.gcda
|
||||
|
||||
# generated by scripts/memory.sh
|
||||
massif-*
|
||||
|
||||
# MSVC build artifacts:
|
||||
*.exe
|
||||
*.pdb
|
||||
*.ilk
|
||||
*.lib
|
||||
|
||||
# Python build artifacts:
|
||||
*.pyc
|
||||
|
||||
# Generated documentation:
|
||||
/apidoc
|
||||
|
||||
# Editor navigation files:
|
||||
/GPATH
|
||||
/GRTAGS
|
||||
/GSYMS
|
||||
/GTAGS
|
||||
/TAGS
|
||||
/tags
|
||||
.pio
|
||||
.vscode
|
@ -1,13 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(bluecovid)
|
||||
|
||||
target_sources(app PRIVATE src/main.c src/contacts.c src/exposure-notification.c src/gatt-service.c src/covid.c)
|
||||
|
||||
zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config)
|
||||
|
||||
#use for testing only, will update keys every X seconds, default is 600
|
||||
#add_definitions(-DEN_INTERVAL_LENGTH=11)
|
||||
#add_definitions(-DEN_INTERVAL_LENGTH=1)
|
46
lib/README
Normal file
46
lib/README
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
52
lib/exposure-notification/examples/tracking.c
Normal file
52
lib/exposure-notification/examples/tracking.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include "exposure-notification.h"
|
||||
#include "time.h"
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
// first init everything
|
||||
// TODO: More randomization, we init with NULL to let en init mbdet entropy for us
|
||||
en_init(NULL);
|
||||
|
||||
// get the currentTime
|
||||
time_t currentTime = time(NULL);
|
||||
|
||||
// The periodKey changes each EN_TEK_ROLLING_PERIOD intervals
|
||||
ENIntervalNumber periodInterval = en_get_interval_number_at_period_start(currentTime);
|
||||
|
||||
ENPeriodKey periodKey;
|
||||
ENPeriodIdentifierKey periodIdentifierKey;
|
||||
ENPeriodMetadataEncryptionKey periodMetadaEncryptionKey;
|
||||
|
||||
// setup period keys at the beginning
|
||||
// in theory you could let them generate automatically setting periodInterval to 0
|
||||
en_generate_and_derive_period_keys(&periodKey, &periodIdentifierKey, &periodMetadaEncryptionKey);
|
||||
|
||||
char metadata[128] = "";
|
||||
|
||||
while(1) {
|
||||
// we check the current time to know if we actually need to regenerate anything
|
||||
currentTime = time(NULL);
|
||||
ENIntervalNumber currentInterval = en_get_interval_number(currentTime);
|
||||
|
||||
// we check if we need to generate new keys
|
||||
if (currentInterval - periodInterval >= EN_TEK_ROLLING_PERIOD) {
|
||||
periodInterval = en_get_interval_number_at_period_start(currentTime);
|
||||
en_generate_and_derive_period_keys(&periodKey, &periodIdentifierKey, &periodMetadaEncryptionKey);
|
||||
// TODO: Store new periodKey with periodInterval
|
||||
}
|
||||
|
||||
// we now generate the new interval identifier and re-encrypt the metadata
|
||||
ENIntervalIdentifier intervalIdentifier;
|
||||
en_derive_interval_identifier(&intervalIdentifier, &periodIdentifierKey, currentInterval);
|
||||
|
||||
char encryptedMetadata[sizeof(metadata)];
|
||||
en_encrypt_interval_metadata(&periodMetadaEncryptionKey, &intervalIdentifier, metadata, encryptedMetadata, sizeof(metadata));
|
||||
|
||||
// broadcast intervalIdentifier plus encryptedMetada according to specs
|
||||
// TODO: receive packets and store them
|
||||
// repeat for 10-20 minutes
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
14
lib/exposure-notification/library.json
Normal file
14
lib/exposure-notification/library.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"description": "exposure-notification",
|
||||
"frameworks": "*",
|
||||
"keywords": "exposure, notification, contact, tracking, tracing",
|
||||
"name": "exposure-notification",
|
||||
"platforms": "*",
|
||||
"version": "0.1",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "mbedtls",
|
||||
"version": "^2.16.4"
|
||||
}
|
||||
]
|
||||
}
|
@ -4,22 +4,27 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#if EN_INCLUDE_ZEPHYR_DEPS
|
||||
#include <zephyr.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/printk.h>
|
||||
#include <sys/util.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/hkdf.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/hkdf.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/aes.h"
|
||||
|
||||
#include "exposure-notification.h"
|
||||
|
||||
|
||||
|
||||
static mbedtls_ctr_drbg_context ctr_drbg;
|
||||
static ENRandomBytesCallback random_bytes_callback = NULL;
|
||||
|
36
platformio.ini
Normal file
36
platformio.ini
Normal file
@ -0,0 +1,36 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
|
||||
[env:nrf52840_dk]
|
||||
platform = nordicnrf52
|
||||
board = nrf52840_dk
|
||||
framework = zephyr
|
||||
monitor_speed = 115200
|
||||
test_ignore = test_desktop
|
||||
build_flags =
|
||||
-Iinclude/tls_config
|
||||
# For testing: -DUNITY_EXCLUDE_SETJMP_H=1
|
||||
-DEN_INCLUDE_ZEPHYR_DEPS=1
|
||||
-DEN_INIT_MBEDTLS_ENTROPY=0
|
||||
lib_deps = exposure-notification
|
||||
|
||||
|
||||
[env:desktop]
|
||||
platform = native
|
||||
test_ignore = test_embedded
|
||||
lib_compat_mode = off
|
||||
lib_deps = mbedtls@~2
|
||||
build_flags =
|
||||
-Iinclude/desktop
|
||||
-Iinclude/tls_config
|
||||
-Wno-nullability-completeness
|
||||
-DMBEDTLS_USER_CONFIG_FILE='"user-tls.conf"'
|
||||
src_filter = --<.src/>
|
11
test/README
Normal file
11
test/README
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
222
test/test_common/test_common.cpp
Normal file
222
test/test_common/test_common.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include <unity.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exposure-notification.h"
|
||||
|
||||
#define TEST_ASSERT_EQUAL_KEY(k1, k2) TEST_ASSERT_EQUAL(0, memcmp(k1.b, k2.b, sizeof(k1.b)))
|
||||
#define TEST_ASSERT_NOT_EQUAL_KEY(k1, k2) TEST_ASSERT_NOT_EQUAL(0, memcmp(k1.b, k2.b, sizeof(k1.b)))
|
||||
|
||||
|
||||
void test_init(void) {
|
||||
int ret = en_init(NULL);
|
||||
TEST_ASSERT_EQUAL(0, ret);
|
||||
}
|
||||
|
||||
void test_get_interval_number(void) {
|
||||
TEST_ASSERT_EQUAL(0, en_get_interval_number(0));
|
||||
TEST_ASSERT_EQUAL(0, en_get_interval_number(EN_INTERVAL_LENGTH-1));
|
||||
TEST_ASSERT_EQUAL(1, en_get_interval_number(EN_INTERVAL_LENGTH));
|
||||
TEST_ASSERT_EQUAL(42, en_get_interval_number(EN_INTERVAL_LENGTH*42));
|
||||
}
|
||||
|
||||
void test_get_interval_number_at_period_start(void) {
|
||||
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(0));
|
||||
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH-1));
|
||||
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH));
|
||||
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH*42));
|
||||
TEST_ASSERT_EQUAL(EN_TEK_ROLLING_PERIOD, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH*EN_TEK_ROLLING_PERIOD));
|
||||
TEST_ASSERT_EQUAL(EN_TEK_ROLLING_PERIOD, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH*EN_TEK_ROLLING_PERIOD+1));
|
||||
}
|
||||
|
||||
void test_generate_period_key(void) {
|
||||
ENPeriodKey p1, p2;
|
||||
en_generate_period_key(&p1);
|
||||
en_generate_period_key(&p2);
|
||||
// yes there is a minimal chance that both are the same ;)
|
||||
TEST_ASSERT_NOT_EQUAL_KEY(p1, p2);
|
||||
}
|
||||
|
||||
void test_get_period_identifier_key(void) {
|
||||
|
||||
ENPeriodKey pk;
|
||||
en_generate_period_key(&pk);
|
||||
|
||||
ENPeriodIdentifierKey k1, k2;
|
||||
en_derive_period_identifier_key(&k1, &pk);
|
||||
en_derive_period_identifier_key(&k2, &pk);
|
||||
|
||||
// This time both should be the same key as the depent on the period key
|
||||
TEST_ASSERT_EQUAL_KEY(k1, k2);
|
||||
|
||||
// BUT: they should be different than the period key itself
|
||||
TEST_ASSERT_NOT_EQUAL_KEY(k1, pk);
|
||||
}
|
||||
|
||||
|
||||
void test_get_interval_identifier(void) {
|
||||
|
||||
ENPeriodKey pk;
|
||||
en_generate_period_key(&pk);
|
||||
|
||||
ENIntervalNumber iv = en_get_interval_number(0);
|
||||
|
||||
ENIntervalIdentifier id1, id2;
|
||||
en_derive_interval_identifier(&id1, &pk, iv);
|
||||
en_derive_interval_identifier(&id2, &pk, iv);
|
||||
|
||||
// identities should be the same for the same intervalnumber and period key
|
||||
|
||||
TEST_ASSERT_EQUAL_KEY(id1, id2);
|
||||
|
||||
iv = en_get_interval_number(EN_INTERVAL_LENGTH);
|
||||
en_derive_interval_identifier(&id2, &pk, iv);
|
||||
|
||||
// BUT: they should be different when we are using another interval number
|
||||
TEST_ASSERT_NOT_EQUAL_KEY(id1, id2);
|
||||
|
||||
// They should also be different for another period key but the the same interval number
|
||||
en_generate_period_key(&pk);
|
||||
en_derive_interval_identifier(&id1, &pk, iv);
|
||||
|
||||
en_generate_period_key(&pk);
|
||||
en_derive_interval_identifier(&id2, &pk, iv);
|
||||
|
||||
TEST_ASSERT_NOT_EQUAL_KEY(id1, id2);
|
||||
}
|
||||
|
||||
void test_get_period_metadata_encryption_key(void) {
|
||||
|
||||
ENPeriodKey pk;
|
||||
en_generate_period_key(&pk);
|
||||
ENPeriodMetadataEncryptionKey k1, k2;
|
||||
en_derive_period_metadata_encryption_key(&k1, &pk);
|
||||
en_derive_period_metadata_encryption_key(&k2, &pk);
|
||||
|
||||
// This time both should be the same key as the depent on the period key
|
||||
TEST_ASSERT_EQUAL_KEY(k1, k2);
|
||||
|
||||
// BUT: they should be different than the period key itself
|
||||
TEST_ASSERT_NOT_EQUAL_KEY(k1, pk);
|
||||
|
||||
// and they should also be different than the periodIdentifierKey
|
||||
ENPeriodIdentifierKey pik;
|
||||
en_derive_period_identifier_key(&pik, &pk);
|
||||
TEST_ASSERT_NOT_EQUAL_KEY(k1, pik);
|
||||
}
|
||||
|
||||
|
||||
void test_en_encrypt_interval_metadata(void) {
|
||||
|
||||
ENPeriodKey pk;
|
||||
en_generate_period_key(&pk);
|
||||
ENPeriodMetadataEncryptionKey k1;
|
||||
en_derive_period_metadata_encryption_key(&k1, &pk);
|
||||
|
||||
ENIntervalNumber iv = en_get_interval_number(0);
|
||||
ENIntervalIdentifier id;
|
||||
en_derive_interval_identifier(&id, &pk, iv);
|
||||
|
||||
unsigned char testData[42] = "This is some test data :)";
|
||||
unsigned char encryptedData[42] = "";
|
||||
|
||||
en_encrypt_interval_metadata(&k1, &id, testData, encryptedData, sizeof(testData));
|
||||
|
||||
// the original data should not be changed
|
||||
TEST_ASSERT_EQUAL_CHAR_ARRAY("This is some test data :)", testData, sizeof("This is some test data :)")-1);
|
||||
|
||||
// but the encrypted one should be changed
|
||||
TEST_ASSERT_NOT_EQUAL(0, memcmp(testData, encryptedData, sizeof(testData)));
|
||||
|
||||
unsigned char decryptedData[42] = "";
|
||||
en_decrypt_interval_metadata(&k1, &id, encryptedData, decryptedData, sizeof(testData));
|
||||
|
||||
// the decrypted metadata should be the same as the testData
|
||||
TEST_ASSERT_EQUAL_CHAR_ARRAY(testData, decryptedData, sizeof(testData));
|
||||
}
|
||||
|
||||
void test_identifier_generation_performance(void) {
|
||||
|
||||
int runs = 1000000;
|
||||
|
||||
for(int i = 0; i < runs; i++) {
|
||||
ENPeriodKey pk;
|
||||
en_generate_period_key(&pk);
|
||||
ENPeriodIdentifierKey ik;
|
||||
en_derive_period_identifier_key(&ik, &pk);
|
||||
|
||||
for(int iv = 0; iv < EN_TEK_ROLLING_PERIOD; iv++) {
|
||||
ENIntervalNumber intervalNumber = en_get_interval_number(iv);
|
||||
ENIntervalIdentifier id;
|
||||
en_derive_interval_identifier(&id, &ik, intervalNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_generate_and_derive_period_keys(void) {
|
||||
// Test multiple generation
|
||||
ENPeriodKey periodKey;
|
||||
ENPeriodIdentifierKey periodIdentifierKey;
|
||||
ENPeriodMetadataEncryptionKey periodMetadaEncryptionKey;
|
||||
for(int i = 0; i < 10; i++) {
|
||||
en_generate_and_derive_period_keys(&periodKey, &periodIdentifierKey, &periodMetadaEncryptionKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_against_fixtures(void) {
|
||||
// First define base values
|
||||
ENIntervalNumber intervalNumber = 2642976;
|
||||
ENPeriodKey periodKey = {.b = {0x75, 0xc7, 0x34, 0xc6, 0xdd, 0x1a, 0x78, 0x2d, 0xe7, 0xa9, 0x65, 0xda, 0x5e, 0xb9, 0x31, 0x25}};
|
||||
unsigned char metadata[4] = {0x40, 0x08, 0x00, 0x00};
|
||||
|
||||
// define the expected values
|
||||
ENPeriodIdentifierKey expectedPIK = {.b = {0x18, 0x5a, 0xd9, 0x1d, 0xb6, 0x9e, 0xc7, 0xdd, 0x04, 0x89, 0x60, 0xf1, 0xf3, 0xba, 0x61, 0x75}};
|
||||
ENPeriodMetadataEncryptionKey expectedPMEK = {.b = {0xd5, 0x7c, 0x46, 0xaf, 0x7a, 0x1d, 0x83, 0x96, 0x5b, 0x9b, 0xed, 0x8b, 0xd1, 0x52, 0x93, 0x6a}};
|
||||
|
||||
ENIntervalIdentifier expectedIntervalIdentifier = {.b = {0x8b, 0xe6, 0xcd, 0x37, 0x1c, 0x5c, 0x89, 0x16, 0x04, 0xbf, 0xbe, 0x49, 0xdf, 0x84, 0x50, 0x96}};
|
||||
unsigned char expectedEncryptedMetadata[4] = {0x72, 0x03, 0x38, 0x74};
|
||||
|
||||
|
||||
ENPeriodIdentifierKey pik;
|
||||
en_derive_period_identifier_key(&pik, &periodKey);
|
||||
TEST_ASSERT_EQUAL_KEY(expectedPIK, pik);
|
||||
|
||||
ENPeriodMetadataEncryptionKey pmek;
|
||||
en_derive_period_metadata_encryption_key(&pmek, &periodKey);
|
||||
TEST_ASSERT_EQUAL_KEY(expectedPMEK, pmek);
|
||||
|
||||
ENIntervalIdentifier intervalIdentifier;
|
||||
en_derive_interval_identifier(&intervalIdentifier, &pik, intervalNumber);
|
||||
TEST_ASSERT_EQUAL_KEY(expectedIntervalIdentifier, intervalIdentifier);
|
||||
|
||||
|
||||
unsigned char encryptedMetadata[sizeof(metadata)] = {0};
|
||||
en_encrypt_interval_metadata(&pmek, &intervalIdentifier, metadata, encryptedMetadata, sizeof(metadata));
|
||||
TEST_ASSERT_EQUAL_CHAR_ARRAY(expectedEncryptedMetadata, encryptedMetadata, sizeof(expectedEncryptedMetadata));
|
||||
}
|
||||
|
||||
|
||||
void test_exposure_notification() {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_init);
|
||||
RUN_TEST(test_get_interval_number);
|
||||
RUN_TEST(test_get_interval_number_at_period_start);
|
||||
RUN_TEST(test_generate_period_key);
|
||||
RUN_TEST(test_get_period_identifier_key);
|
||||
RUN_TEST(test_get_interval_identifier);
|
||||
RUN_TEST(test_get_period_metadata_encryption_key);
|
||||
RUN_TEST(test_en_encrypt_interval_metadata);
|
||||
RUN_TEST(test_generate_and_derive_period_keys);
|
||||
RUN_TEST(test_against_fixtures);
|
||||
//RUN_TEST(test_identifier_generation_performance);
|
||||
UNITY_END();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
test_exposure_notification();
|
||||
return 0;
|
||||
}
|
6
zephyr/CMakeLists.txt
Normal file
6
zephyr/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(test)
|
||||
|
||||
FILE(GLOB app_sources ../src/*.c*)
|
||||
target_sources(app PRIVATE ${app_sources})
|
@ -8,8 +8,6 @@ CONFIG_BT_DEVICE_NAME="BlueCovid"
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
|
||||
CONFIG_MBEDTLS=y
|
||||
#CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y
|
||||
#CONFIG_MBEDTLS_CFG_FILE="mbedtls_config.h"
|
||||
CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y
|
||||
CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls.conf"
|
||||
|
Loading…
Reference in New Issue
Block a user