From 37e2b9b3573a05390190a25052ceb23d8dab0132 Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Tue, 21 Apr 2020 00:09:57 +0300 Subject: [PATCH] Add time functions, simplify API Add functions for calculating time values, and for configuringthe keys based on the current time, Simplifies the match api so Rpi and Dtk structures don't need to be created separately before being added to a list. --- README.md | 15 ++---- include/contrac/contrac.h | 4 ++ include/contrac/contrac_private.h | 3 -- include/contrac/dtk.h | 2 +- include/contrac/dtk_list.h | 2 + include/contrac/rpi_list.h | 1 + include/contrac/utils.h | 5 ++ src/contrac.c | 44 +++++++++++++--- src/dtk.c | 2 +- src/dtk_list.c | 5 ++ src/rpi.c | 2 +- src/rpi_list.c | 8 +++ src/utils.c | 28 ++++++++++ tests/test_contrac.c | 85 +++++++++++++++++++++++++------ 14 files changed, 167 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 9df42ae..51017a0 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,8 @@ should be set appropriately. ``` Contrac * contrac = contrac_new(); -contrac_generate_tracing_key(contrac); -contrac_set_day_number(contrac, 23); -contrac_set_time_interval_number(contrac, 76); +// Generates a random Tracing Key if one hasn't yet been set +contrac_update_current_time(data); ``` Get the Rolling Proximity Identifier for broadcast in Bluetooth beacons. @@ -60,21 +59,15 @@ const unsigned char * dtk = contrac_get_daily_key(contrac); Add RPIs captured via Bluetooth to an RPI list. ``` RpiList * rpis = rpi_list_new(); - // Add bytes captured at a given time to the list -Rpi * rpi = rpi_new(); -rpi_assign(rpi, captured_bytes, time_interval_number); -rpi_list_append(rpis, rpi); +rpi_list_add_beacon(rpis, captured_bytes, time_interval_number); ``` Construct a list of DTKs from data downloaded from a Diagnosis Server. ``` DtkList * dtks = dtk_list_new(); - // Add data downloaded from the server to the list -Dtk * dtk = dtk_new(); -dtk_assign(dtk, dtk_bytes, day_number); -dtk_list_append(dtks, dtk); +dtk_list_add_diagnosis(dtks, dtk_bytes, day_number); ``` Having collected these two lists any matches can be tested for as follows. diff --git a/include/contrac/contrac.h b/include/contrac/contrac.h index 9478054..ca29847 100644 --- a/include/contrac/contrac.h +++ b/include/contrac/contrac.h @@ -40,11 +40,15 @@ void contrac_delete(Contrac * data); bool contrac_generate_tracing_key(Contrac * data); bool contrac_set_day_number(Contrac * data, uint32_t day_number); bool contrac_set_time_interval_number(Contrac * data, uint8_t time_interval_number); +bool contrac_update_current_time(Contrac * data); bool contrac_get_initialised(Contrac const * data); const unsigned char * contrac_get_tracing_key(Contrac const * data); void contrac_get_tracing_key_base64(Contrac const * data, char * base64); +void contrac_set_tracing_key(Contrac * data, unsigned char const * tracing_key); +bool contrac_set_tracing_key_base64(Contrac * data, char const * tracing_key); + const unsigned char * contrac_get_daily_key(Contrac const * data); void contrac_get_daily_key_base64(Contrac const * data, char * base64); diff --git a/include/contrac/contrac_private.h b/include/contrac/contrac_private.h index 68d5aad..7a72d76 100644 --- a/include/contrac/contrac_private.h +++ b/include/contrac/contrac_private.h @@ -29,9 +29,6 @@ // Function prototypes -void contrac_set_tracing_key(Contrac * data, unsigned char const * tracing_key); -bool contrac_set_tracing_key_base64(Contrac * data, char const * tracing_key); - // Function definitions #endif // __CONTRAC_PRIVATE_H diff --git a/include/contrac/dtk.h b/include/contrac/dtk.h index 1525ebb..c263fe2 100644 --- a/include/contrac/dtk.h +++ b/include/contrac/dtk.h @@ -33,7 +33,7 @@ typedef struct _Dtk Dtk; Dtk * dtk_new(); void dtk_delete(Dtk * data); -bool contrac_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_number); +bool dtk_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_number); const unsigned char * dtk_get_daily_key(Dtk const * data); uint32_t dtk_get_day_number(Dtk const * data); void dtk_assign(Dtk * data, unsigned char const * dtk_bytes, uint32_t day_number); diff --git a/include/contrac/dtk_list.h b/include/contrac/dtk_list.h index 2eacb68..a681229 100644 --- a/include/contrac/dtk_list.h +++ b/include/contrac/dtk_list.h @@ -35,6 +35,8 @@ DtkList * dtk_list_new(); void dtk_list_delete(DtkList * data); void dtk_list_append(DtkList * data, Dtk * dtk); +void dtk_list_add_diagnosis(DtkList * data, unsigned char const * dtk_bytes, uint32_t day_number); + DtkListItem const * dtk_list_first(DtkList const * data); DtkListItem const * dtk_list_next(DtkListItem const * data); Dtk const * dtk_list_get_dtk(DtkListItem const * data); diff --git a/include/contrac/rpi_list.h b/include/contrac/rpi_list.h index 7814708..efe2f7c 100644 --- a/include/contrac/rpi_list.h +++ b/include/contrac/rpi_list.h @@ -35,6 +35,7 @@ RpiList * rpi_list_new(); void rpi_list_delete(RpiList * data); void rpi_list_append(RpiList * data, Rpi * rpi); +void rpi_list_add_beacon(RpiList * data, unsigned char const * rpi_bytes, uint8_t time_interval_number); RpiListItem const * rpi_list_first(RpiList const * data); RpiListItem const * rpi_list_next(RpiListItem const * data); diff --git a/include/contrac/utils.h b/include/contrac/utils.h index 38b0c3f..41df6d1 100644 --- a/include/contrac/utils.h +++ b/include/contrac/utils.h @@ -20,6 +20,8 @@ // Includes +#include + // Defines #define MAX(a,b) \ @@ -41,6 +43,9 @@ size_t base64_decode_size(size_t base64_input); void base64_encode_binary_to_base64(unsigned char const *input, size_t input_size, unsigned char *output, size_t *output_size); void base64_decode_base64_to_binary(unsigned char const *input, size_t input_size, unsigned char *output, size_t *output_size); +uint32_t epoch_to_day_number(time_t epoch); +uint8_t epoch_to_time_interval_number(time_t epoch); + // Function definitions #endif // __UTILS_H diff --git a/src/contrac.c b/src/contrac.c index 47070d3..ed925cb 100644 --- a/src/contrac.c +++ b/src/contrac.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -48,9 +49,6 @@ struct _Contrac { // Rolling proximity identifier Rpi * rpi; - uint32_t day_number; - uint8_t time_interval_number; - uint32_t status; }; @@ -102,11 +100,10 @@ bool contrac_set_day_number(Contrac * data, uint32_t day_number) { result = ((data->status & STATUS_TK) != 0); if (result) { - result = contrac_generate_daily_key(data->dtk, data, day_number); + result = dtk_generate_daily_key(data->dtk, data, day_number); } if (result) { - data->day_number = day_number; data->status |= STATUS_DTK; } @@ -123,7 +120,6 @@ bool contrac_set_time_interval_number(Contrac * data, uint8_t time_interval_numb } if (result) { - data->time_interval_number = time_interval_number; data->status |= STATUS_RPI; } @@ -209,8 +205,44 @@ void contrac_get_proximity_id_base64(Contrac const * data, char * base64) { } } +bool contrac_update_current_time(Contrac * data) { + bool result; + time_t epoch; + uint32_t dn_stored; + uint32_t dn_now; + uint8_t tn_stored; + uint8_t tn_now; + + result = true; + + if ((data->status & STATUS_TK) == 0) { + // No Tracing Key has been set, so generate a random key + result = contrac_generate_tracing_key(data); + } + + epoch = time(NULL); + + if (result) { + dn_now = epoch_to_day_number(epoch); + dn_stored = dtk_get_day_number(data->dtk); + + // Only set again if uninitialised or the time has changed + if ((dn_now != dn_stored) || ((data->status & STATUS_DTK) == 0)) { + result = contrac_set_day_number(data, dn_now); + } + } + if (result) { + tn_now = epoch_to_time_interval_number(epoch); + tn_stored= rpi_get_time_interval_number(data->rpi); + // Only set again if uninitialised or the time has changed + if ((tn_now != tn_stored) || (dn_now != dn_stored) || ((data->status & STATUS_RPI) == 0)) { + result = contrac_set_time_interval_number(data, tn_now); + } + } + return result; +} diff --git a/src/dtk.c b/src/dtk.c index 3febd9f..e0c8eeb 100644 --- a/src/dtk.c +++ b/src/dtk.c @@ -65,7 +65,7 @@ void dtk_delete(Dtk * data) { } } -bool contrac_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_number) { +bool dtk_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_number) { int result = 1; char encode[sizeof(DTK_INFO_PREFIX) + sizeof(day_number)]; size_t out_length = 0; diff --git a/src/dtk_list.c b/src/dtk_list.c index 9ef41f7..daa03d0 100644 --- a/src/dtk_list.c +++ b/src/dtk_list.c @@ -98,4 +98,9 @@ Dtk const * dtk_list_get_dtk(DtkListItem const * data) { return data->dtk; } +void dtk_list_add_diagnosis(DtkList * data, unsigned char const * dtk_bytes, uint32_t day_number) { + Dtk * dtk = dtk_new(); + dtk_assign(dtk, dtk_bytes, day_number); + dtk_list_append(data, dtk); +} diff --git a/src/rpi.c b/src/rpi.c index 7523ba4..abef1bd 100644 --- a/src/rpi.c +++ b/src/rpi.c @@ -66,7 +66,7 @@ void rpi_delete(Rpi * data) { bool rpi_generate_proximity_id(Rpi * data, Dtk const * dtk, uint8_t time_interval_number) { int result = 1; - unsigned char encode[sizeof(RPI_INFO_PREFIX) + sizeof(uint16_t)]; + unsigned char encode[sizeof(RPI_INFO_PREFIX) + sizeof(time_interval_number)]; unsigned char output[EVP_MAX_MD_SIZE]; unsigned int out_length = 0; unsigned int pos; diff --git a/src/rpi_list.c b/src/rpi_list.c index fb482ba..a21b0da 100644 --- a/src/rpi_list.c +++ b/src/rpi_list.c @@ -99,4 +99,12 @@ Rpi const * rpi_list_get_rpi(RpiListItem const * data) { return data->rpi; } +void rpi_list_add_beacon(RpiList * data, unsigned char const * rpi_bytes, uint8_t time_interval_number) { + Rpi * rpi = rpi_new(); + rpi_assign(rpi, rpi_bytes, time_interval_number); + rpi_list_append(data, rpi); +} + + + diff --git a/src/utils.c b/src/utils.c index 1fbb716..443f2a2 100644 --- a/src/utils.c +++ b/src/utils.c @@ -66,4 +66,32 @@ void base64_decode_base64_to_binary(unsigned char const *input, size_t input_siz EVP_DecodeBlock(output, input, size_in); } +uint32_t epoch_to_day_number(time_t epoch) { + uint32_t day_number; + + // DayNumber <- (Number of Seconds since Epoch) / 60 × 60 × 24 + day_number = epoch / (60 * 60 * 24); + + return day_number; +} + +uint8_t epoch_to_time_interval_number(time_t epoch) { + uint8_t time_interval_number; + uint32_t day_number; + uint32_t seconds; + + // TimeNumberInterval <- (Seconds Since Start of DayNumber) / 60 × 10 + day_number = epoch_to_day_number(epoch); + seconds = epoch - (day_number * (60 * 60 * 24)); + + time_interval_number = seconds / (60 * 10); + + // Falls in interval [0,143] + if (time_interval_number > 143) { + time_interval_number = 143; + } + + return time_interval_number; +} + diff --git a/tests/test_contrac.c b/tests/test_contrac.c index b697a94..65bcc4f 100644 --- a/tests/test_contrac.c +++ b/tests/test_contrac.c @@ -34,6 +34,12 @@ // Function prototypes +// Override time function +static time_t fake_time = 0; +time_t time(time_t *__timer) { + return fake_time; +} + // Function definitions START_TEST (check_base64) { @@ -210,19 +216,19 @@ START_TEST (check_rpi) { ck_assert(result); contrac_get_proximity_id_base64(contrac, rpi_base64); ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64); - ck_assert_str_eq(rpi_base64, "++ucH9hoIkGwCzM+J09faQ=="); + ck_assert_str_eq(rpi_base64, "yStiu899O+6xvdLiUdrpsA=="); result = contrac_set_time_interval_number(contrac, 82); ck_assert(result); contrac_get_proximity_id_base64(contrac, rpi_base64); ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64); - ck_assert_str_eq(rpi_base64, "GrqeroryZQ+Uvhx10zfKWw=="); + ck_assert_str_eq(rpi_base64, "aFTYIeEUGYKELi8TUUql+Q=="); result = contrac_set_time_interval_number(contrac, 143); ck_assert(result); contrac_get_proximity_id_base64(contrac, rpi_base64); ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64); - ck_assert_str_eq(rpi_base64, "+9eL1UlYZ9buUCFF5qRDUA=="); + ck_assert_str_eq(rpi_base64, "MK9mDdgTsgsh6Vxp0XhasA=="); contrac_set_tracing_key_base64(contrac, tracing_key_base64[1]); @@ -233,19 +239,19 @@ START_TEST (check_rpi) { ck_assert(result); contrac_get_proximity_id_base64(contrac, rpi_base64); ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64); - ck_assert_str_eq(rpi_base64, "XmePWi0HlgHyBcVUb0KhjQ=="); + ck_assert_str_eq(rpi_base64, "layNswS/rQxovfYnBhjXJg=="); result = contrac_set_time_interval_number(contrac, 27); ck_assert(result); contrac_get_proximity_id_base64(contrac, rpi_base64); ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64); - ck_assert_str_eq(rpi_base64, "LlPznz6D044ZKYsY3sHJew=="); + ck_assert_str_eq(rpi_base64, "BJyzAC3hyVfcWOhQ9paEFA=="); result = contrac_set_time_interval_number(contrac, 143); ck_assert(result); contrac_get_proximity_id_base64(contrac, rpi_base64); ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64); - ck_assert_str_eq(rpi_base64, "QDG50cy9NTXZ3zDAUGkePQ=="); + ck_assert_str_eq(rpi_base64, "ItETUQc372fOzJKHvF8z6w=="); // Clean up contrac_delete(contrac); @@ -268,8 +274,6 @@ START_TEST (check_match) { int pos; const unsigned char * rpi_bytes; const unsigned char * dtk_bytes; - Rpi * rpi; - Dtk * dtk; MatchList * matches; MatchListItem const * match; @@ -293,10 +297,7 @@ START_TEST (check_match) { ck_assert(result); rpi_bytes = contrac_get_proximity_id(contrac); - rpi = rpi_new(); - rpi_assign(rpi, rpi_bytes, beacon_times[pos]); - - rpi_list_append(beacon_list, rpi); + rpi_list_add_beacon(beacon_list, rpi_bytes, beacon_times[pos]); } // Generate some diagnosis data (as if provided by a diagnosis server) @@ -307,10 +308,7 @@ START_TEST (check_match) { ck_assert(result); dtk_bytes = contrac_get_daily_key(contrac); - dtk = dtk_new(); - dtk_assign(dtk, dtk_bytes, diagnosis_days[pos]); - - dtk_list_append(diagnosis_list, dtk); + dtk_list_add_diagnosis(diagnosis_list, dtk_bytes, diagnosis_days[pos]); } // Check that the matching algorithm identifies the beacons that match @@ -342,6 +340,60 @@ START_TEST (check_match) { } END_TEST +START_TEST (check_time) { + bool result; + char const *tracing_key_base64 = "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc="; + uint32_t dn; + uint8_t tn; + time_t base = 1587415596; + time_t check; + Contrac * contrac; + char dtk_base64[DTK_SIZE_BASE64 + 1]; + char rpi_base64[RPI_SIZE_BASE64 + 1]; + + check = base; + dn = epoch_to_day_number(check); + ck_assert_int_eq(dn, 18372); + tn = epoch_to_time_interval_number(check); + ck_assert_int_eq(tn, 124); + + check = base + (24 * 60 * 60); + dn = epoch_to_day_number(check); + ck_assert_int_eq(dn, 18372 + 1); + tn = epoch_to_time_interval_number(check); + ck_assert_int_eq(tn, 124); + + check = base - 675 * (24 * 60 * 60); + dn = epoch_to_day_number(check); + ck_assert_int_eq(dn, 18372 - 675); + tn = epoch_to_time_interval_number(check); + ck_assert_int_eq(tn, 124); + + check = base + 15 * (10 * 60); + dn = epoch_to_day_number(check); + ck_assert_int_eq(dn, 18372); + tn = epoch_to_time_interval_number(check); + ck_assert_int_eq(tn, 124 + 15); + + fake_time = 1587415596; + + contrac = contrac_new(); + contrac_set_tracing_key_base64(contrac, tracing_key_base64); + + contrac_update_current_time(contrac); + result = contrac_get_initialised(contrac); + ck_assert(result); + + contrac_get_daily_key_base64(contrac, dtk_base64); + ck_assert_str_eq(dtk_base64, "6GMXmeDAR5XU0AEtZQJ+tA=="); + + contrac_get_proximity_id_base64(contrac, rpi_base64); + ck_assert_str_eq(rpi_base64, "ysbjVuF7xf9eDH2y2T8VpQ=="); + + contrac_delete(contrac); +} +END_TEST + int main(void) { int failed; Suite * s; @@ -356,6 +408,7 @@ int main(void) { tcase_add_test(tc, check_dtk); tcase_add_test(tc, check_rpi); tcase_add_test(tc, check_match); + tcase_add_test(tc, check_time); suite_add_tcase(s, tc); sr = srunner_create(s); -- 2.25.1