From 8dc0dd74e4dd2ffb780c98e92b075ba5e94ff8cf Mon Sep 17 00:00:00 2001 From: Patrick Rathje Date: Tue, 10 Nov 2020 17:31:39 +0100 Subject: [PATCH] Use PlatformIO Exposure Notification Library --- lib/exposure-notification/examples/tracking.c | 52 ------ .../include/exposure-notification.h | 170 ------------------ lib/exposure-notification/library.json | 14 -- .../src/exposure-notification.c | 140 --------------- platformio.ini | 8 +- 5 files changed, 5 insertions(+), 379 deletions(-) delete mode 100644 lib/exposure-notification/examples/tracking.c delete mode 100644 lib/exposure-notification/include/exposure-notification.h delete mode 100644 lib/exposure-notification/library.json delete mode 100644 lib/exposure-notification/src/exposure-notification.c diff --git a/lib/exposure-notification/examples/tracking.c b/lib/exposure-notification/examples/tracking.c deleted file mode 100644 index e0b7ffa..0000000 --- a/lib/exposure-notification/examples/tracking.c +++ /dev/null @@ -1,52 +0,0 @@ -#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; -} \ No newline at end of file diff --git a/lib/exposure-notification/include/exposure-notification.h b/lib/exposure-notification/include/exposure-notification.h deleted file mode 100644 index 1cfb337..0000000 --- a/lib/exposure-notification/include/exposure-notification.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2020 Patrick Rathje - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef EXPOSURE_NOTIFICATION_H -#define EXPOSURE_NOTIFICATION_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#include -#include -#include - -#ifndef EN_TEK_ROLLING_PERIOD -#define EN_TEK_ROLLING_PERIOD 144 -#endif - - -#ifndef EN_INTERVAL_LENGTH -#define EN_INTERVAL_LENGTH 600 -#endif - -#ifndef EN_INIT_MBEDTLS_ENTROPY -#define EN_INIT_MBEDTLS_ENTROPY 1 -#endif - -/* - * Type: _ENBaseKey - * -------------------- - * 16 Byte base key definition - */ -typedef struct _ENBaseKey { unsigned char b[16];} _ENBaseKey; - - -/* - * Type: ENIntervalNumber - * -------------------- - * The number of the 10 minute interval - */ -typedef uint32_t ENIntervalNumber; - - -/* - * Type: ENPeriodKey - * -------------------- - * 16 Byte temporary exposure key used throughout a rolling period (one day) - */ -typedef struct _ENBaseKey ENPeriodKey; - - -/* - * Type: ENPeriodIdentifierKey - * -------------------- - * 16 Byte key used throughout each period to encrypt the identifier for each interval - */ -typedef struct _ENBaseKey ENPeriodIdentifierKey; - - -/* - * Type: ENIntervalIdentifier - * -------------------- - * 16 Byte identifier used within the packet - */ -typedef struct _ENBaseKey ENIntervalIdentifier; - - -/* - * Type: ENPeriodMetadataEncryptionKey - * -------------------- - * 16 Byte key used throughout each interval to encrypt the metadata within one period - */ -typedef struct _ENBaseKey ENPeriodMetadataEncryptionKey; - - -/* - * Type: ENPeriodMetadataEncryptionKey - * -------------------- - * 16 Byte key used throughout each interval to encrypt the metadata within one period - */ -typedef struct _ENBaseKey ENPeriodMetadataEncryptionKey; - - -typedef int (*ENRandomBytesCallback)(void *buf, size_t len); - -/* - * Function: en_init - * -------------------- - * Initializes the random number generator. Use NULL to initialize with the fallback random_bytes_func - */ -int en_init(ENRandomBytesCallback user_random_bytes_callback); - -/* - * Function: en_get_interval_number - * -------------------- - * computes the interval number according to the given unix timestamp. Each interval lasts for EN_INTERVAL_LENGTH secs (defaults to 10 minutes). - */ -ENIntervalNumber en_get_interval_number(time_t timestamp); - -/* - * Function: en_get_period_start_interval_number - * -------------------- - * computes the first interval number for the period given by the unix timestamp. - */ -ENIntervalNumber en_get_interval_number_at_period_start(time_t timestamp); - - -/* - * Function: en_generate_period_key - * -------------------- - * Generates a new period key using a cryptographic number generator. Used when the next period is dues (once a day). - */ -void en_generate_period_key(ENPeriodKey* periodKey); - -/* - * Function: en_derive_period_identifier_key - * -------------------- - * Derives the interval identifier key based on the current period key - */ -void en_derive_period_identifier_key(ENPeriodIdentifierKey *periodIdentifierKey, const ENPeriodKey *periodKey); - - -/* - * Function: en_derive_interval_identifier - * -------------------- - * Get the identifier for a specific interval based on the identifierKey - */ -void en_derive_interval_identifier(ENIntervalIdentifier *intervalIdentifier, const ENPeriodIdentifierKey *periodIdentifierKey, const ENIntervalNumber intervalNumber); - -/* - * Function: en_derive_period_metadata_encryption_key - * -------------------- - * Derives the interval metadata encryption key based on the current period key - */ -void en_derive_period_metadata_encryption_key(ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey, const ENPeriodKey *periodKey); - - -/* - * Function: en_encrypt_interval_metadata - * -------------------- - * Encrypts the metadata. - */ -void en_encrypt_interval_metadata(const ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey, const ENIntervalIdentifier *intervalIdentifier, unsigned char *input, unsigned char *output, size_t inputSize); - -/* - * Function: en_decrypt_interval_metadata - * -------------------- - * Decrypts the metadata. - */ -void en_decrypt_interval_metadata(const ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey, const ENIntervalIdentifier *intervalIdentifier, unsigned char *input, unsigned char *output, size_t inputSize); - -/* - * Function: en_generate_period_relevant_keys() - * -------------------- - * This function generates all period keys at once (convenient right?) - */ -static inline void en_generate_and_derive_period_keys(ENPeriodKey *periodKey, ENPeriodIdentifierKey *periodIdentifierKey, ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey) { - en_generate_period_key(periodKey); - en_derive_period_identifier_key(periodIdentifierKey, periodKey); - en_derive_period_metadata_encryption_key(periodMetadataEncryptionKey, periodKey); -} - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/lib/exposure-notification/library.json b/lib/exposure-notification/library.json deleted file mode 100644 index 46c0954..0000000 --- a/lib/exposure-notification/library.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "description": "exposure-notification", - "frameworks": "*", - "keywords": "exposure, notification, contact, tracking, tracing", - "name": "exposure-notification", - "platforms": "*", - "version": "0.1", - "dependencies": [ - { - "name": "mbedtls", - "version": "^2.16.4" - } - ] -} \ No newline at end of file diff --git a/lib/exposure-notification/src/exposure-notification.c b/lib/exposure-notification/src/exposure-notification.c deleted file mode 100644 index 497f14c..0000000 --- a/lib/exposure-notification/src/exposure-notification.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2020 Patrick Rathje - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#if EN_INCLUDE_ZEPHYR_DEPS -#include -#include -#include -#include -#include -#endif - -#include - -#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; - - -int en_mbedtls_random_bytes_fallback(void *buf, size_t len) { - return mbedtls_ctr_drbg_random(&ctr_drbg, buf, len); -} - -#if EN_INIT_MBEDTLS_ENTROPY -int init_mbedtls_entropy() { - mbedtls_entropy_context entropy; - mbedtls_entropy_init( &entropy ); - - static char *personalization = "exposure-notification"; - - mbedtls_ctr_drbg_init( &ctr_drbg ); - - int ret = mbedtls_ctr_drbg_seed( &ctr_drbg , mbedtls_entropy_func, &entropy, - (const unsigned char *) personalization, - strlen( personalization ) ); - return ret; -} -#endif -int en_init(ENRandomBytesCallback user_random_bytes_callback) { - int ret = 0; - - -#if EN_INIT_MBEDTLS_ENTROPY - ret = init_mbedtls_entropy(); -#endif - // Fallback to mbedtls random bytes implementation and init the entropy - if (user_random_bytes_callback == NULL) { - random_bytes_callback = en_mbedtls_random_bytes_fallback; - } else { - random_bytes_callback = user_random_bytes_callback; - } - - return ret; -} - -ENIntervalNumber en_get_interval_number(time_t timestamp) { - return timestamp / EN_INTERVAL_LENGTH; -} - -ENIntervalNumber en_get_interval_number_at_period_start(time_t timestamp) { - ENIntervalNumber current = en_get_interval_number(timestamp); - // round to period start - return (current/EN_TEK_ROLLING_PERIOD)*EN_TEK_ROLLING_PERIOD; -} - -void en_generate_period_key(ENPeriodKey* periodKey) { - // TODO: error handling - random_bytes_callback(periodKey->b, sizeof(periodKey->b)); -} - -void en_derive_period_identifier_key(ENPeriodIdentifierKey *periodIdentifierKey, const ENPeriodKey *periodKey) { - - const mbedtls_md_info_t *sha256_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - // TODO: Include \0 in the string? - // TODO: Check return value - // TODO: Is this utf-8 info correct? - // TODO: Correct erros in en_get_period_metadata_encryption_key as well! - const unsigned char info[7] = "EN-RPIK"; - mbedtls_hkdf(sha256_info, 0, 0, periodKey->b, sizeof(periodKey->b), info, sizeof(info), periodIdentifierKey->b, sizeof(periodIdentifierKey->b)); -} - -void en_derive_interval_identifier(ENIntervalIdentifier *intervalIdentifier, const ENPeriodIdentifierKey *periodIdentifierKey, const ENIntervalNumber intervalNumber) { - unsigned char paddedData[16] = "EN-RPI"; - - // copy intervalNumber in little endian format - paddedData[12] = (intervalNumber >> 0) &0xFF; - paddedData[13] = (intervalNumber >> 8) &0xFF; - paddedData[14] = (intervalNumber >> 16) &0xFF; - paddedData[15] = (intervalNumber >> 24) &0xFF; - - mbedtls_aes_context aes; - mbedtls_aes_init( &aes ); - - // Encrypt the padded data to get the identifier - mbedtls_aes_setkey_enc( &aes, (const unsigned char*) periodIdentifierKey->b, sizeof(periodIdentifierKey->b) * 8 ); - mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, paddedData, intervalIdentifier->b); - mbedtls_aes_free( &aes ); -} - -void en_derive_period_metadata_encryption_key(ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey, const ENPeriodKey *periodKey) { - const mbedtls_md_info_t *sha256_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - const unsigned char info[7] = "EN-AEMK"; - mbedtls_hkdf(sha256_info, 0, 0, periodKey->b, sizeof(periodKey->b), info, sizeof(info), periodMetadataEncryptionKey->b, sizeof(periodMetadataEncryptionKey->b)); -} - - -void en_encrypt_interval_metadata(const ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey, const ENIntervalIdentifier *intervalIdentifier, unsigned char *input, unsigned char *output, size_t inputSize) { - - mbedtls_aes_context aes; - mbedtls_aes_init( &aes ); - - // Encrypt the padded data to get the identifier - size_t nonceOffset = 0; - unsigned char nonceCounter[16]; - unsigned char streamBlock[16]; - - // init nonce/IV to intervalIdentifer - memcpy(nonceCounter, intervalIdentifier->b, sizeof(nonceCounter)); - memset(streamBlock, 0, sizeof(streamBlock)); - - mbedtls_aes_setkey_enc( &aes, (const unsigned char*) periodMetadataEncryptionKey->b, sizeof(periodMetadataEncryptionKey->b) * 8 ); - mbedtls_aes_crypt_ctr(&aes, inputSize, &nonceOffset, nonceCounter, streamBlock, input, output); - mbedtls_aes_free( &aes ); -} - -void en_decrypt_interval_metadata(const ENPeriodMetadataEncryptionKey *periodMetadataEncryptionKey, const ENIntervalIdentifier *intervalIdentifier, unsigned char *input, unsigned char *output, size_t inputSize) { - en_encrypt_interval_metadata(periodMetadataEncryptionKey, intervalIdentifier, input, output, inputSize); -} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 34a54a3..e0b3e84 100644 --- a/platformio.ini +++ b/platformio.ini @@ -22,14 +22,16 @@ build_flags = # For testing: -DUNITY_EXCLUDE_SETJMP_H=1 -DEN_INCLUDE_ZEPHYR_DEPS=1 -DEN_INIT_MBEDTLS_ENTROPY=0 -lib_deps = exposure-notification - +lib_deps = + prathje/exposure-notification @ ^0.1 [env:desktop] platform = native test_ignore = test_embedded lib_compat_mode = off -lib_deps = mbedtls@~2 +lib_deps = + mbedtls@~2 + prathje/exposure-notification @ ^0.1 build_flags = -Iinclude/desktop -Iinclude/tls_config