From e48c390a86b448137a87d0d0a5863c202ba66abd Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Wed, 22 Apr 2020 22:13:21 +0300 Subject: [PATCH] Add remaining documentation Add documentation to the remaining source files, as well as a main index page. --- include/contrac/contrac.h | 2 + include/contrac/contrac_private.h | 17 ++- include/contrac/dtk.h | 6 +- include/contrac/dtk_list.h | 30 +++++- include/contrac/log.h | 32 +++++- include/contrac/match.h | 30 +++++- include/contrac/rpi.h | 42 ++++++-- include/contrac/rpi_list.h | 30 +++++- include/contrac/utils.h | 19 ++-- src/contrac.c | 97 ++++++++++++----- src/dtk.c | 59 ++++++++-- src/dtk_list.c | 93 +++++++++++++++- src/log.c | 16 +++ src/main.dox | 174 ++++++++++++++++++++++++++++++ src/match.c | 137 ++++++++++++++++++++++- src/rpi.c | 114 ++++++++++++++++++-- src/rpi_list.c | 95 ++++++++++++++-- src/utils.c | 109 ++++++++++++++++++- 18 files changed, 1002 insertions(+), 100 deletions(-) create mode 100644 src/main.dox diff --git a/include/contrac/contrac.h b/include/contrac/contrac.h index e9a059e..064bda2 100644 --- a/include/contrac/contrac.h +++ b/include/contrac/contrac.h @@ -67,6 +67,8 @@ 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); +uint32_t contrac_get_day_number(Contrac * data); +uint8_t contrac_get_time_interval_number(Contrac * data); unsigned char const * contrac_get_tracing_key(Contrac const * data); void contrac_get_tracing_key_base64(Contrac const * data, char * base64); diff --git a/include/contrac/contrac_private.h b/include/contrac/contrac_private.h index 7a72d76..570060c 100644 --- a/include/contrac/contrac_private.h +++ b/include/contrac/contrac_private.h @@ -1,19 +1,24 @@ -/** \ingroup contrac +/** \ingroup KeyGeneration * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Private header for the Core Contact Tracing functionality * @section DESCRIPTION * - * + * This provides access to private functionality in the \ref Contrac class. * */ +/** \addtogroup KeyGeneration + * @{ + */ + #ifndef __CONTRAC_PRIVATE_H #define __CONTRAC_PRIVATE_H @@ -33,3 +38,5 @@ #endif // __CONTRAC_PRIVATE_H +/** @} addtogroup KeyGeneration */ + diff --git a/include/contrac/dtk.h b/include/contrac/dtk.h index ee621e5..459fb52 100644 --- a/include/contrac/dtk.h +++ b/include/contrac/dtk.h @@ -11,9 +11,9 @@ * @brief Daily Tracing Key functionality * @section DESCRIPTION * - * This class is used to generate and manage the Daily Tracing Key. It's + * This class is used to generate and manage the Daily Tracing Key (DTK). It's * largely internal. The functionality from \ref Contrac should generally be - * used instead of these functions. + * used in preference to this. * */ @@ -56,7 +56,7 @@ Dtk * dtk_new(); void dtk_delete(Dtk * data); bool dtk_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_number); -const unsigned char * dtk_get_daily_key(Dtk const * data); +unsigned char const * 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 a681229..b54308c 100644 --- a/include/contrac/dtk_list.h +++ b/include/contrac/dtk_list.h @@ -1,17 +1,25 @@ -/** \ingroup contrac +/** \ingroup KeyGeneration * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Provides a list of DTKs * @section DESCRIPTION * + * This class allows the simplified management of lists of Dtk objects. This is + * useful when checking DTKs received from a Diagnosis Server with RPIs + * captured over Bluetooth. Combined with the \ref RpiList class the two can + * be easily stored and passed into the \ref match_list_find_matches() function. * - * + */ + +/** \addtogroup Containers + * @{ */ #ifndef __DTK_LIST_H @@ -26,7 +34,18 @@ // Structures +/** + * An opaque structure that represents the head of the list. + * + * The internal structure can be found in dtk_list.c + */ typedef struct _DtkList DtkList; + +/** + * An opaque structure that represents an item in the list. + * + * The internal structure can be found in dtk_list.c + */ typedef struct _DtkListItem DtkListItem; // Function prototypes @@ -45,4 +64,5 @@ Dtk const * dtk_list_get_dtk(DtkListItem const * data); #endif // __DTK_LIST_H +/** @} addtogroup Containers*/ diff --git a/include/contrac/log.h b/include/contrac/log.h index 0e7abee..8e8dae8 100644 --- a/include/contrac/log.h +++ b/include/contrac/log.h @@ -1,19 +1,25 @@ -/** \ingroup contrac +/** \ingroup Logging * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Allows output to be sent to the log * @section DESCRIPTION * - * + * This is a simple set of functions and macros that allows strings to be + * recorded in the syslog. * */ +/** \addtogroup Logging + * @{ + */ + #ifndef __LOG_H #define __LOG_H @@ -23,6 +29,20 @@ // Defines +/** + * Log a string to syslog. + * + * Constructs a message using the supplied format and parameters and records it + * in the system log. The format is the same as for printf. + * + * The logging levels are the standard syslog levels: + * + * LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, etc. + * + * @param priority The log level priority. + * @param format The format for the message, the same as for printf. + * @param ... parameters to combine with the format to create the message. + */ #define LOG(level, ...) log_priority(level, __VA_ARGS__); // Structures @@ -34,3 +54,5 @@ void log_priority(int priority, const char *format, ...); // Function definitions #endif // __LOG_H + +/** @} addtogroup Logging*/ diff --git a/include/contrac/match.h b/include/contrac/match.h index fe38c74..5523eed 100644 --- a/include/contrac/match.h +++ b/include/contrac/match.h @@ -1,19 +1,29 @@ -/** \ingroup contrac +/** \ingroup Matching * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Provides a way to match collected RPIs with downloaded DTKs * @section DESCRIPTION * + * This class provides functionality allowing RPIs that have been collected + * over Bluetooth to be matched against DTKs downloaded from a Diagnosis + * Server. * + * The list of RPIs and DTKs can be constructed easily using the + * \ref Container functions. * */ +/** \addtogroup Matching + * @{ + */ + #ifndef __MATCH_H #define __MATCH_H @@ -26,7 +36,18 @@ // Structures +/** + * An opaque structure that represents the head of the list. + * + * The internal structure can be found in match.c + */ typedef struct _MatchList MatchList; + +/** + * An opaque structure that represents an item in the list. + * + * The internal structure can be found in match.c + */ typedef struct _MatchListItem MatchListItem; // Function prototypes @@ -49,4 +70,5 @@ void match_list_find_matches(MatchList * data, RpiList * beacons, DtkList * diag #endif // __MATCH_H +/** @} addtogroup Matching*/ diff --git a/include/contrac/rpi.h b/include/contrac/rpi.h index eab1e09..133edf2 100644 --- a/include/contrac/rpi.h +++ b/include/contrac/rpi.h @@ -1,17 +1,24 @@ -/** \ingroup contrac +/** \ingroup RandomProximityIdentifier * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Random Proximity Identifier functionality * @section DESCRIPTION * + * This class is used to generate and manage the Random Proximity Identifier + * (RPI). It's largely internal. The functionality from \ref Contrac should + * generally be used in preference to this. * - * + */ + +/** \addtogroup RandomProximityIdentifier + * @{ */ #ifndef __RPI_H @@ -24,12 +31,34 @@ // Defines +/** + * The size in bytes of an RPI in binary format. + * + */ #define RPI_SIZE (16) + +/** + * The size in bytes of an RPI in base64 format, not including the null + * terminator. + * + */ #define RPI_SIZE_BASE64 (24) + +/** + * The maximum value a time interval number can take. Time interval numbers + * are measured from the start of the day and increment every 10 minutes, so + * must fall within the interval [0, 143]. + * + */ #define RPI_INTERVAL_MAX (144) // Structures +/** + * An opaque structure for representing a DTK. + * + * The internal structure can be found in rpi.c + */ typedef struct _Rpi Rpi; // Function prototypes @@ -38,7 +67,7 @@ Rpi * rpi_new(); void rpi_delete(Rpi * data); bool rpi_generate_proximity_id(Rpi * data, Dtk const * dtk, uint8_t time_interval_number); -const unsigned char * rpi_get_proximity_id(Rpi const * data); +unsigned char const * rpi_get_proximity_id(Rpi const * data); uint8_t rpi_get_time_interval_number(Rpi const * data); void rpi_assign(Rpi * data, unsigned char const * rpi_bytes, uint8_t time_interval_number); bool rpi_compare(Rpi const * data, Rpi const * comparitor); @@ -47,4 +76,5 @@ bool rpi_compare(Rpi const * data, Rpi const * comparitor); #endif // __RPI_H +/** @} addtogroup RandomProximityIdentifier */ diff --git a/include/contrac/rpi_list.h b/include/contrac/rpi_list.h index efe2f7c..03584d4 100644 --- a/include/contrac/rpi_list.h +++ b/include/contrac/rpi_list.h @@ -1,17 +1,25 @@ -/** \ingroup contrac +/** \ingroup KeyGeneration * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Provides a list of RPIs * @section DESCRIPTION * + * This class allows the simplified management of lists of Rpi objects. This is + * useful when checking DTKs received from a Diagnosis Server with RPIs + * captured over Bluetooth. Combined with the \ref DtkList class the two can + * be easily stored and passed into the \ref match_list_find_matches() function. * - * + */ + +/** \addtogroup Containers + * @{ */ #ifndef __RPI_LIST_H @@ -26,7 +34,18 @@ // Structures +/** + * An opaque structure that represents the head of the list. + * + * The internal structure can be found in rpi_list.c + */ typedef struct _RpiList RpiList; + +/** + * An opaque structure that represents an item in the list. + * + * The internal structure can be found in rpi_list.c + */ typedef struct _RpiListItem RpiListItem; // Function prototypes @@ -45,4 +64,5 @@ Rpi const * rpi_list_get_rpi(RpiListItem const * data); #endif // __RPI_LIST_H +/** @} addtogroup Containers*/ diff --git a/include/contrac/utils.h b/include/contrac/utils.h index 41df6d1..0f40c8c 100644 --- a/include/contrac/utils.h +++ b/include/contrac/utils.h @@ -1,19 +1,26 @@ -/** \ingroup contrac +/** \ingroup Utils * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Static utility functions * @section DESCRIPTION * + * Provides various static utitlity functions. In particular: * + * base64 encoding and decoding functionality. + * Time conversion: from epoch to day numbers and time interval numbers. * */ +/** \addtogroup Utils + * @{ + */ #ifndef __UTILS_H #define __UTILS_H @@ -50,7 +57,5 @@ uint8_t epoch_to_time_interval_number(time_t epoch); #endif // __UTILS_H - - - +/** @} addtogroup Utils */ diff --git a/src/contrac.c b/src/contrac.c index 3ffdebd..9532114 100644 --- a/src/contrac.c +++ b/src/contrac.c @@ -8,7 +8,7 @@ * Copyright David Llewellyn-Jones, 2020 * Released under the GPLv2. * - * @brief Core Contact Tracing functionality + * @brief Core Contact Tracing functionality * @section DESCRIPTION * * This class provides the core Contact Tracing functionality. It provides an @@ -47,7 +47,7 @@ // Defines /** - * Inernal flag mask. + * A mask used internally with the status flags. * * When set the flag indicates that the Tracing Key has been correctly * initialised. @@ -55,7 +55,7 @@ #define STATUS_TK (1 << 0) /** - * Inernal flag mask. + * A mask used internally with the status flags. * * When set the flag indicates that the Daily Tracing Key has been correctly * initialised. @@ -63,7 +63,7 @@ #define STATUS_DTK (1 << 1) /** - * Inernal flag mask. + * A mask used internally with the status flags. * * When set the flag indicates that the Rolling Proximity Identifier has been * correctly initialised. @@ -71,7 +71,7 @@ #define STATUS_RPI (1 << 2) /** - * Inernal flag mask. + * A mask used internally with the status flags. * * When all of these flags are set it indicates that the structure is fully * initialised. @@ -105,7 +105,7 @@ struct _Contrac { // Function definitions /** - * Create a new instance of the class. + * Creates a new instance of the class. * * @return The newly created object. */ @@ -120,7 +120,7 @@ Contrac * contrac_new() { } /** - * Delete an instance of the class, freeing up the memory allocated to it. + * Deletes an instance of the class, freeing up the memory allocated to it. * * @param data The instance to free. */ @@ -137,7 +137,7 @@ void contrac_delete(Contrac * data) { } /** - * Generate a random Contact Tracing Key. + * Generates a random Contact Tracing Key. * * The operation may fail under certain circumstances, such as there being * insufficient entropy in the system to guarantee a random result. @@ -162,7 +162,7 @@ bool contrac_generate_tracing_key(Contrac * data) { } /** - * Set the current day number. + * Sets the current day number. * * This will result in a new Daily Tracing Key being generated based on the * day provided. If neither the Tracing Key nor the day have changed, the DTK @@ -171,12 +171,13 @@ bool contrac_generate_tracing_key(Contrac * data) { * The day number is calculated as: * (Number of Seconds since Epoch) / (60 * 60 * 24) * - * Which can be caluclated from the current epoch using the + * Which can be calculated from the current epoch using the * epoch_to_day_number() function. * * The operation may fail if a Tracing Key has yet to be configured. * * @param data The context object to work with. + * @param day_number The day number used to generate the DTK. * @return true if the operation completed successfully, false otherwise. */ bool contrac_set_day_number(Contrac * data, uint32_t day_number) { @@ -196,7 +197,7 @@ bool contrac_set_day_number(Contrac * data, uint32_t day_number) { } /** - * Set the current time interval number. + * Sets the current time interval number. * * This will result in a new Rolling Proximity Idetifier being generated based * on the time interval number. If none of the Tracing Key, day nor time @@ -207,7 +208,7 @@ bool contrac_set_day_number(Contrac * data, uint32_t day_number) { * * and must fall in the interval [0, 143]. * - * It can be caluclated from the current epoch using the + * It can be calculated from the current epoch using the * epoch_to_time_interval_number() function. * * The operation may fail if a Tracing Key or Daily Tracing Key have yet to be @@ -234,7 +235,7 @@ bool contrac_set_time_interval_number(Contrac * data, uint8_t time_interval_numb } /** - * Get whether the internal state has been fully configured or not. + * Gets whether the internal state has been fully configured or not. * * The internal state must be fully configured before a Daily Tracing Key or * Rolling Proximity Identifier can be calculated. This function returns whether @@ -258,7 +259,45 @@ bool contrac_get_initialised(Contrac const * data) { } /** - * Set the Tracing Key for the device in binary format. + * Gets the current day number. + * + * Gets the current day number used to generate the most recent DTK. + * + * The day number is calculated as: + * (Number of Seconds since Epoch) / (60 * 60 * 24) + * + * Which can be caluclated from the current epoch using the + * epoch_to_day_number() function. + * + * @param data The context object to work with. + * @return The day number most recently used to generate the DTK. + */ +uint32_t contrac_get_day_number(Contrac * data) { + return dtk_get_day_number(data->dtk); +} + +/** + * Gets the current time interval number. + * + * Gets the current time interval number used to generate the most recent RPI. + * + * The time interval number is calculated as: + * (Seconds Since Start of DayNumber) / (60 * 10) + * + * and must fall in the interval [0, 143]. + * + * It can be caluclated from the current epoch using the + * epoch_to_time_interval_number() function. + * + * @param data The context object to work with. + * @return The time interval number most recently used to generate the RPI. + */ +uint8_t contrac_get_time_interval_number(Contrac * data) { + return rpi_get_time_interval_number(data->rpi); +} + +/** + * Sets the Tracing Key for the device in binary format. * * When first configuring a system, the Tracing Key must be generated * randomly, e.g. using contrac_generate_tracing_key(). @@ -267,7 +306,7 @@ bool contrac_get_initialised(Contrac const * data) { * In this case the key can be restored using this function. * * The tracing_key buffer passed in must contain exactly TK_SIZE (32) bytes of - * data. + * data.It doen't have to be null terminated. * * @param data The context object to work with. * @param tracing_key The Tracing Key to set in binary format. @@ -278,7 +317,7 @@ void contrac_set_tracing_key(Contrac * data, unsigned char const * tracing_key) } /** - * Get the Tracing Key for the device in binary format. + * Gets the Tracing Key for the device in binary format. * * This allows the Tracing Key to be extracted. The Tracing Key should be kept * secret (to maintain privacy), however it still may need to be extracted, for @@ -286,7 +325,9 @@ void contrac_set_tracing_key(Contrac * data, unsigned char const * tracing_key) * * The buffer returned will contain exactly TK_SIZE (32) bytes of data in binary * format. This may therefore contain null bytes, and the buffer will not - * necessarily be null terminated. + * necessarily be null terminated. Future operations may cause the data to + * change, so the caller should make a copy of the buffer rather than keeping + * the pointer to it. * * @param data The context object to work with. * @return The Tracing Key in binary format, not null terminated. @@ -296,7 +337,7 @@ unsigned char const * contrac_get_tracing_key(Contrac const * data) { } /** - * Get the Tracing Key for the device in base64 format. + * Gets the Tracing Key for the device in base64 format. * * This allows the Tracing Key to be extracted. The Tracing Key should be kept * secret (to maintain privacy), however it still may need to be extracted, for @@ -319,7 +360,7 @@ void contrac_get_tracing_key_base64(Contrac const * data, char * base64) { } /** - * Set the Tracing Key for the device in base64 format. + * Sets the Tracing Key for the device in base64 format. * * When first configuring a system, the Tracing Key must be generated * randomly, e.g. using contrac_generate_tracing_key(). @@ -362,7 +403,7 @@ bool contrac_set_tracing_key_base64(Contrac * data, char const * tracing_key) { } /** - * Get the Daily Tracing Key for the device in binary format. + * Gets the Daily Tracing Key for the device in binary format. * * This allows the Daily Tracing Key to be extracted. The Daily Tracing Key * should be kept secret (to maintain privacy) until a positive test is @@ -371,7 +412,9 @@ bool contrac_set_tracing_key_base64(Contrac * data, char const * tracing_key) { * * The buffer returned will contain exactly DTK_SIZE (16) bytes of data in * binary format. This may therefore contain null bytes, and the buffer will not - * necessarily be null terminated. + * necessarily be null terminated. Future operations may cause the data to + * change, so the caller should make a copy of the buffer rather than keeping + * the pointer to it. * * @param data The context object to work with. * @return The Daily Tracing Key in binary format, not null terminated. @@ -381,7 +424,7 @@ unsigned char const * contrac_get_daily_key(Contrac const * data) { } /** - * Get the Daily Tracing Key for the device in base64 format. + * Gets the Daily Tracing Key for the device in base64 format. * * This allows the Daily Tracing Key to be extracted. The Daily Tracing Key * should be kept secret (to maintain privacy) until a positive test is @@ -405,7 +448,7 @@ void contrac_get_daily_key_base64(Contrac const * data, char * base64) { } /** - * Get the Rolling Proximity Identifier for the device in binary format. + * Gets the Rolling Proximity Identifier for the device in binary format. * * This allows the Rolling Proximity Identifier to be extracted. The Rolling * Proximity Identifier is for broadcast to other devices using BLE and changes @@ -413,7 +456,9 @@ void contrac_get_daily_key_base64(Contrac const * data, char * base64) { * * The buffer returned will contain exactly RPI_SIZE (16) bytes of data in * binary format. This may therefore contain null bytes, and the buffer will not - * necessarily be null terminated. + * necessarily be null terminated. Future operations may cause the data to + * change, so the caller should make a copy of the buffer rather than keeping + * the pointer to it. * * @param data The context object to work with. * @return The Rolling Proximity Identifier in binary format, not null @@ -424,7 +469,7 @@ unsigned char const * contrac_get_proximity_id(Contrac const * data) { } /** - * Get the Rolling Proximity Identifier for the device in base64 format. + * Gets the Rolling Proximity Identifier for the device in base64 format. * * This allows the Rolling Proximity Identifier to be extracted. The Rolling * Proximity Identifier is for broadcast to other devices using BLE and changes @@ -447,7 +492,7 @@ void contrac_get_proximity_id_base64(Contrac const * data, char * base64) { } /** - * Update the Daily Tracing Key and Random Proxmity Identifer. + * Updates the Daily Tracing Key and Random Proxmity Identifer. * * The Daily Tracing Key changes every day, the Random Proximity Identifier * changes every 10 minutes. diff --git a/src/dtk.c b/src/dtk.c index a6db274..5faffd7 100644 --- a/src/dtk.c +++ b/src/dtk.c @@ -11,9 +11,9 @@ * @brief Daily Tracing Key functionality * @section DESCRIPTION * - * This class is used to generate and manage the Daily Tracing Key. It's + * This class is used to generate and manage the Daily Tracing Key (DTK). It's * largely internal. The functionality from \ref Contrac should generally be - * used instead of these functions. + * used in preference to this. * */ @@ -71,7 +71,7 @@ struct _Dtk { // Function definitions /** - * Create a new instance of the class. + * Creates a new instance of the class. * * @return The newly created object. */ @@ -84,7 +84,7 @@ Dtk * dtk_new() { } /** - * Delete an instance of the class, freeing up the memory allocated to it. + * Deletes an instance of the class, freeing up the memory allocated to it. * * @param data The instance to free. */ @@ -98,7 +98,7 @@ void dtk_delete(Dtk * data) { } /** - * Generate a random Daily Tracing Key. + * Generates a Daily Tracing Key based on the day number provided. * * The operation may fail under certain circumstances, such as if the * HKDF operation fails for some reason. @@ -107,6 +107,7 @@ void dtk_delete(Dtk * data) { * contrac_set_day_number() function instead. * * @param data The context object to work with. + * @param day_number The day number to use to generate the key. * @return true if the operation completed successfully, false otherwise. */ bool dtk_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_number) { @@ -114,7 +115,7 @@ bool dtk_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_nu char encode[sizeof(DTK_INFO_PREFIX) + sizeof(day_number)]; size_t out_length = 0; EVP_PKEY_CTX *pctx = NULL; - const unsigned char * tk; + unsigned char const * tk; // dtk_i <- HKDF(tk, NULL, (UTF8("CT-DTK") || D_i), 16) @@ -167,14 +168,58 @@ bool dtk_generate_daily_key(Dtk * data, Contrac const * contrac, uint32_t day_nu return (result > 0); } -const unsigned char * dtk_get_daily_key(Dtk const * data) { +/** + * Gets the Daily Tracing Key for the device in binary format. + * + * For internal use. It generally makes more sense to use the + * contrac_get_daily_key() function instead. + * + * This allows the Daily Tracing Key to be extracted. The Daily Tracing Key + * should be kept secret (to maintain privacy) until a positive test is + * confirmed, at which point the user may choose to upload the key to a + * Diagnosis Server, so that others can be notified. + * + * The buffer returned will contain exactly DTK_SIZE (16) bytes of data in + * binary format. This may therefore contain null bytes, and the buffer will not + * necessarily be null terminated. Future operations may cause the data to + * change, so the caller should make a copy of the buffer rather than keeping + * a pointer to it. + * + * @param data The context object to work with. + * @return The Daily Tracing Key in binary format, not null terminated. + */ +unsigned char const * dtk_get_daily_key(Dtk const * data) { return data->dtk; } +/** + * Gets the day number that applies to the current DTK. + * + * For internal use. It generally makes more sense to use the + * contrac_get_day_number() function instead. + * + * @param data The context object to work with. + * @return The day number stored in the object.. + */ uint32_t dtk_get_day_number(Dtk const * data) { return data->day_number; } +/** + * Populates the data structure. + * + * Allows the DTK and day number values of the object to be set explicitly. + * + * For internal use. To set the DTK it generally makes more sense to use one of + * eiher contrac_set_day_number() or contrac_update_current_time() instead. + * + * The dtk_bytes buffer passed in must contain exactly DTK_SIZE (16) bytes of + * data. It doen't have to be null terminated. + * + * @param data The context object to work with. + * @param dtk_bytes The DTK value to set, in binary format. + * @param day_number The day number to associate with this DTK. + */ void dtk_assign(Dtk * data, unsigned char const * dtk_bytes, uint32_t day_number) { memcpy(data->dtk, dtk_bytes, DTK_SIZE); data->day_number = day_number; diff --git a/src/dtk_list.c b/src/dtk_list.c index daa03d0..f7ab67b 100644 --- a/src/dtk_list.c +++ b/src/dtk_list.c @@ -1,17 +1,25 @@ -/** \ingroup contrac +/** \ingroup KeyGeneration * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Provides a list of DTKs * @section DESCRIPTION * + * This class allows the simplified management of lists of Dtk objects. This is + * useful when checking DTKs received from a Diagnosis Server with RPIs + * captured over Bluetooth. Combined with the \ref RpiList class the two can + * be easily stored and passed into the \ref match_list_find_matches() function. * - * + */ + +/** \addtogroup Containers + * @{ */ // Includes @@ -31,11 +39,30 @@ // Structures +/** + * @brief A DTK list element + * + * This is an opaque structure that represents a single item in the list and + * contains a Dtk instance. + * + * The structure typedef is in dtk_list.h + */ struct _DtkListItem { Dtk * dtk; DtkListItem * next; }; +/** + * @brief The head of a DTK list + * + * This is an opaque structure that represents the head of a list of Dtk + * items. + * + * This is the object usually passed as the first parameter of every non-static + * function. + * + * The structure typedef is in dtk_list.h + */ struct _DtkList { DtkListItem * first; DtkListItem * last; @@ -45,6 +72,11 @@ struct _DtkList { // Function definitions +/** + * Creates a new instance of the class. + * + * @return The newly created object. + */ DtkList * dtk_list_new() { DtkList * data; @@ -53,6 +85,13 @@ DtkList * dtk_list_new() { return data; } +/** + * Deletes an instance of the class, freeing up the memory allocated to it. + * + * This will also delete all items contained in the list. + * + * @param data The instance to free. + */ void dtk_list_delete(DtkList * data) { DtkListItem * item; DtkListItem * next; @@ -70,6 +109,16 @@ void dtk_list_delete(DtkList * data) { } } +/** + * Adds an item to the list. + * + * This adds a Dtk item to the list. It's primarily for internal use and when + * adding DTKs to the list it's usually more appropriate to use the + * \ref dtk_list_add_diagnosis() function. + * + * @param data The list to append to. + * @param dtk The DTK to append. + */ void dtk_list_append(DtkList * data, Dtk * dtk) { DtkListItem * item; @@ -86,21 +135,55 @@ void dtk_list_append(DtkList * data, Dtk * dtk) { } } +/** + * Returns the first item in the list. + * + * Useful for iterating through the items in the list. + * + * @param data The list to operate on. + * @return The first item of the list. + */ DtkListItem const * dtk_list_first(DtkList const * data) { return data->first; } +/** + * Returns the next item in the list. + * + * Useful for iterating through the items in the list. + * + * @param data The current item in the list. + * @return The next item in the list following the current item. + */ DtkListItem const * dtk_list_next(DtkListItem const * data) { return data->next; } +/** + * Returns the Dtk item contained in this list item. + * + * @param data The current item in the list. + * @return The Dtk instance stored in the list element. + */ Dtk const * dtk_list_get_dtk(DtkListItem const * data) { return data->dtk; } +/** + * Adds Dtk data to the list. + * + * The dtk_bytes buffer passed in must contain exactly DTK_SIZE (16) bytes of + * data. It doen't have to be null terminated. + * + * @param data The current list to operate on. + * @param dtk_bytes The DTK value to add, in binary format. + * @param day_number The day number to associate with the 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); } +/** @} addtogroup Containers*/ + diff --git a/src/log.c b/src/log.c index 599b945..a57d470 100644 --- a/src/log.c +++ b/src/log.c @@ -29,6 +29,22 @@ // Function prototypes +/** + * Log a string to syslog. + * + * In generl, the LOG macro should be used instead. + * + * Constructs a message using the supplied format and parameters and records it + * in the system log. The format is the same as for printf. + * + * The logging levels are the standard syslog levels: + * + * LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, etc. + * + * @param priority The log level priority. + * @param format The format for the message, the same as for printf. + * @param ... parameters to combine with the format to create the message. + */ void log_priority(int priority, const char *format, ...) { va_list args; int length; diff --git a/src/main.dox b/src/main.dox new file mode 100644 index 0000000..9b7d560 --- /dev/null +++ b/src/main.dox @@ -0,0 +1,174 @@ +/** + * @mainpage + * + * @version $(VERSION) + * + * libcontrac is an implementation of the Apple/Google Contact Tracing API. + * + * See the draft specs: https://www.apple.com/covid19/contacttracing/ + * + * ## Install + * + * If you have autoconf you can install as follows. + * + * ``` + * autoreconf --install + * ./configure + * make + * make check + * make install + * ``` + * + * ## Usage + * + * Include header files. + * ``` + * #include "contrac/contrac.h" + * #include "contrac/rpi.h" + * #include "contrac/dtk.h" + * #include "contrac/rpi_list.h" + * #include "contrac/rpi_list.h" + * #include "contrac/matches.h" + * ``` + * + * ### Broadcasting and uploading keys + * + * Most of the functionality is managed through the opaque `Contrac` structure. + * + * Create and initialise the structure as follows. The update call updates the + * Daily Tracing Key and Rolling Proximity Identifier based on the current time. + * + * ``` + * Contrac * contrac = contrac_new(); + * // 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. + * ``` + * // Returns a buffer containing RPI_SIZE bytes of data + * unsigned char const * rpi = contrac_get_proximity_id(contrac); + * ``` + * + * Get the Daily Tracing Key to upload to a Diagnosis Server in case of a positive + * test result. + * ``` + * // Returns a buffer containing DTK_SIZE bytes of data + * unsigned char const * dtk = contrac_get_daily_key(contrac); + * ``` + * + * ### Receiving and matching keys + * + * 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_list_add_beacon(rpis, captured_bytes, time_interval_number); + * ``` + * + * Construct a list of DTKs using data downloaded from a Diagnosis Server. + * ``` + * DtkList * dtks = dtk_list_new(); + * // Add data downloaded from a Diagnosis Server to the list + * dtk_list_add_diagnosis(dtks, dtk_bytes, day_number); + * ``` + * + * Having collected these two lists any matches can be tested for as follows. + * + * ``` + * MatchList * matches = match_list_new(); + * match_list_find_matches(matches, rpis, dtks); + * + * if (match_list_count(matches) > 0) { + * printf("Exposure identified, follow medical advice\n"); + * } + * ``` + * + * ### Cleaning up + * + * Finally, clean up. + * ``` + * match_list_delete(matches); + * rpi_list_delete(rpis); + * dtk_list_delete(dtks); + * contrac_delete(contrac); + * ``` + */ + +/** + * @defgroup KeyGeneration Key Generation + * @brief Core Contact Tracing functionality + * + * This class provides the core Contact Tracing functionality. It provides an + * interfaces for: + * 1. Generating a random Tracing Key. + * 2. Generating a Daily Tracing Key based on the current day number. + * 3. Generating a Rolling Proximity Identifier based on the current time + * interval number. + * + * Values can be extracted and set in binary or base64 format. + * + */ + +/** + * @defgroup Utils Utilities + * @brief Static utility functions + * + * Provides various static utitlity functions. In particular: + * + * base64 encoding and decoding functionality. + * Time conversion: from epoch to day numbers and time interval numbers. + * + */ + +/** + * @defgroup DailyTracingKey Daily Tracing Key + * @brief Daily Tracing Key functionality + * + * This class is used to generate and manage the Daily Tracing Key (DTK). It's + * largely internal. The functionality from \ref Contrac should generally be + * used in preference to this. + * + */ + +/** + * @defgroup RandomProximityIdentifier Random Proximity Identifier + * @brief Proximity Identifier functionality + * + * This class is used to generate and manage the Random Proximity Identifier + * (RPI). It's largely internal. The functionality from \ref Contrac should + * generally be used in preference to this. + * + */ + +/** + * @defgroup Containers Containers + * @brief Provides containers for managing lists of items + * + * This allows the simplified management of lists of Dtk and Rpi objects. This + * is useful when checking DTKs received from a Diagnosis Server with RPIs + * captured over Bluetooth. The two can be easily stored and passed into the + * \ref match_list_find_matches() function. + * + */ + +/** + * @defgroup Matching Matching + * @brief Provides a way to match collected RPIs with downloaded DTKs. + * + * This class provides functionality allowing RPIs that have been collected + * over Bluetooth to be matched against DTKs downloaded from a Diagnosis + * Server. + * + */ + +/** + * @defgroup Logging Logging + * @brief Allows output to be sent to the log + * + * This is a simple set of functions and macros that allows strings to be + * recorded in the syslog. + * + */ + + diff --git a/src/match.c b/src/match.c index c65da52..d9d7689 100644 --- a/src/match.c +++ b/src/match.c @@ -1,19 +1,29 @@ -/** \ingroup contrac +/** \ingroup Matching * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Provides a way to match collected RPIs with downloaded DTKs. * @section DESCRIPTION * + * This class provides functionality allowing RPIs that have been collected + * over Bluetooth to be matched against DTKs downloaded from a Diagnosis + * Server. * + * The list of RPIs and DTKs can be constructed easily using the + * \ref Container functions. * */ +/** \addtogroup Matching + * @{ + */ + // Includes #include @@ -37,6 +47,14 @@ // Structures +/** + * @brief A match list element + * + * This is an opaque structure that represents a single item in the list and + * captures a match between an RPI and a DTK. + * + * The structure typedef is in match.h + */ struct _MatchListItem { uint32_t day_number; uint8_t time_interval_number; @@ -44,6 +62,17 @@ struct _MatchListItem { MatchListItem * next; }; +/** + * @brief The head of a match list + * + * This is an opaque structure that represents the head of the list. Each item + * in the list captures a match between an RPI and a DTK. + * + * This is the object usually passed as the first parameter of every non-static + * function. + * + * The structure typedef is in match.h + */ struct _MatchList { size_t count; MatchListItem * first; @@ -58,6 +87,11 @@ void match_list_append(MatchList * data, MatchListItem * item); // Function definitions +/** + * Creates a new instance of the class. + * + * @return The newly created object. + */ MatchList * match_list_new() { MatchList * data; @@ -66,6 +100,13 @@ MatchList * match_list_new() { return data; } +/** + * Deletes an instance of the class, freeing up the memory allocated to it. + * + * This will also delete all items contained in the list. + * + * @param data The instance to free. + */ void match_list_delete(MatchList * data) { if (data) { match_list_clear(data); @@ -74,6 +115,11 @@ void match_list_delete(MatchList * data) { } } +/** + * Creates a new instance of the class. + * + * @return The newly created object. + */ MatchListItem * match_list_item_new() { MatchListItem * data; @@ -82,12 +128,25 @@ MatchListItem * match_list_item_new() { return data; } +/** + * Deletes an instance of the class, freeing up the memory allocated to it. + * + * @param data The instance to free. + */ void match_list_item_delete(MatchListItem * data) { if (data) { free(data); } } +/** + * Clears all items from the list. + * + * Removes all items from the list to create an empty list. The memory + * associated with the items in the list is freed. + * + * @param data The list to operate on. + */ void match_list_clear(MatchList * data) { MatchListItem * item; MatchListItem * next; @@ -104,27 +163,79 @@ void match_list_clear(MatchList * data) { data->count = 0; } +/** + * Returns the number of items in the list. + * + * Immediately after creation, or after the \ref match_list_clear() function + * has been called, this will return zero. + * + * @param data The list to operate on. + */ size_t match_list_count(MatchList * data) { return data->count; } +/** + * Returns the first item in the list. + * + * Useful for iterating through the items in the list. + * + * @param data The list to operate on. + * @return The first item of the list. + */ MatchListItem const * match_list_first(MatchList const * data) { return data->first; } +/** + * Returns the next item in the list. + * + * Useful for iterating through the items in the list. + * + * @param data The current item in the list. + * @return The next item in the list following the current item. + */ MatchListItem const * match_list_next(MatchListItem const * data) { return data->next; } +/** + * Returns the day number of the item in the list. + * + * This will represent the day number of when an interaction occurred with + * someone who has subsequently uploaded their DTK to a diagnosis server due to + * testing positive. + * + * @param data The list to operate on. + * @return The day number for this item. + */ uint32_t match_list_get_day_number(MatchListItem const * data) { return data->day_number; } +/** + * Returns the time interval number of the item in the list. + * + * This will represent the time interval number of when an interaction occurred + * with someone who has subsequently uploaded their DTK to a diagnosis server + * due to testing positive. + * + * @param data The list to operate on. + * @return The time interval number for this item. + */ uint8_t match_list_get_time_interval_number(MatchListItem const * data) { return data->time_interval_number; } +/** + * Adds an item to the list. + * + * This adds a match to the list. It's primarily for internal use. + * + * @param data The list to append to. + * @param item The match to append. + */ void match_list_append(MatchList * data, MatchListItem * item) { if (data->last == NULL) { data->first = item; @@ -137,6 +248,23 @@ void match_list_append(MatchList * data, MatchListItem * item) { data->count++; } +/** + * Returns a list of matches found between the beacons and diagnoses. + * + * This searches through the list of DTKs and the list of RPIs provided, and + * returns a list of matches. + * + * If the returned list has any elements in, this would suggest that the user + * has been in contact with someone who tested positive and uploaded their DTK + * to a Diagnosis Server. + * + * The match list isn't cleared by this call and so any new values will be + * appended to it. + * + * @param data The list that any matches will be appended to. + * @param beacons A list of RPIs extracted from overheard BLE beacons. + * @param diagnosis_keys A list of DTKs downloaed from a Diagnosis Server. + */ void match_list_find_matches(MatchList * data, RpiList * beacons, DtkList * diagnosis_keys) { // For each diagnosis key, generate the RPIs and compare them against the captured RPI beacons DtkListItem const * dtk_item; @@ -188,4 +316,5 @@ void match_list_find_matches(MatchList * data, RpiList * beacons, DtkList * diag rpi_delete(generated); } +/** @} addtogroup Matching*/ diff --git a/src/rpi.c b/src/rpi.c index abef1bd..dce9f44 100644 --- a/src/rpi.c +++ b/src/rpi.c @@ -1,19 +1,26 @@ -/** \ingroup contrac +/** \ingroup RandomProximityIdentifier * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Random Proximity Identifier functionality * @section DESCRIPTION * - * + * This class is used to generate and manage the Random Proximity Identifier + * (RPI). It's largely internal. The functionality from \ref Contrac should + * generally be used in preference to this. * */ +/** \addtogroup RandomProximityIdentifier + * @{ + */ + // Includes #include @@ -33,10 +40,25 @@ // Defines +/** + * Used internally. + * + * This is the prefix for the Info parameter provided to the HMAC and used to + * generate the RPI. + */ #define RPI_INFO_PREFIX "CT-RPI" // Structures +/** + * @brief The structure used to represent a Rolling Proximity Identifier. + * + * This is an opaque structure that contains information about the RPI.. + * + * This must be passed as the first parameter of every non-static function. + * + * The structure typedef is in dtk.h + */ struct _Rpi { // Rolling proximity identifier unsigned char rpi[RPI_SIZE]; @@ -47,6 +69,11 @@ struct _Rpi { // Function definitions +/** + * Creates a new instance of the class. + * + * @return The newly created object. + */ Rpi * rpi_new() { Rpi * data; @@ -55,6 +82,11 @@ Rpi * rpi_new() { return data; } +/** + * Deletes an instance of the class, freeing up the memory allocated to it. + * + * @param data The instance to free. + */ void rpi_delete(Rpi * data) { if (data) { // Clear the data for security @@ -64,6 +96,21 @@ void rpi_delete(Rpi * data) { } } +/** + * Generates a Rolling Proximity Identifier based on the time interval number + * provided. + * + * The operation may fail under certain circumstances, such as if the + * HMAC operation fails for some reason. + * + * For internal use. It generally makes more sense to use the + * contrac_set_time_interval_number() function instead. + * + * @param data The context object to work with. + * @param time_interval_number The time interval number to use to generate the + * key. + * @return true if the operation completed successfully, false otherwise. + */ 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(time_interval_number)]; @@ -110,20 +157,72 @@ bool rpi_generate_proximity_id(Rpi * data, Dtk const * dtk, uint8_t time_interva return (result > 0); } -const unsigned char * rpi_get_proximity_id(Rpi const * data) { +/** + * Gets the Rolling Proximity Identifier for the device in binary format. + * + * For internal use. It generally makes more sense to use the + * contrac_get_proximity_id() function instead. + * + * This allows the Rolling Proximity Identifier to be extracted. The Rolling + * Proximity Identifier is public, in the sense that it is usual to broadcast + * the value in Bluetooth beacons. + * + * The buffer returned will contain exactly RPI_SIZE (16) bytes of data in + * binary format. This may therefore contain null bytes, and the buffer will not + * necessarily be null terminated. Future operations may cause the data to + * change, so the caller should make a copy of the buffer rather than keeping + * a pointer to it. + * + * @param data The context object to work with. + * @return The Rolling Proximity Identifier in binary format, not null + * terminated. + */ +unsigned char const * rpi_get_proximity_id(Rpi const * data) { return data->rpi; } +/** + * Gets the time interval number that applies to the current RPI. + * + * For internal use. It generally makes more sense to use the + * contrac_set_time_interval_number() function instead. + * + * @param data The context object to work with. + * @return The time interval number stored in the object. + */ uint8_t rpi_get_time_interval_number(Rpi const * data) { return data->time_interval_number; } - +/** + * Populates the data structure. + * + * Allows the RPI and time interval number values of the object to be set + * explicitly. + * + * For internal use. To set the RPI it generally makes more sense to use one of + * eiher contrac_set_time_interval_number() or contrac_update_current_time() + * instead. + * + * The rpi_bytes buffer passed in must contain exactly RPI_SIZE (16) bytes of + * data. It doen't have to be null terminated. + * + * @param data The context object to work with. + * @param rpi_bytes The RPI value to set, in binary format. + * @param day_number The time interval number to associate with this RPI. + */ void rpi_assign(Rpi * data, unsigned char const * rpi_bytes, uint8_t time_interval_number) { memcpy(data->rpi, rpi_bytes, RPI_SIZE); data->time_interval_number = time_interval_number; } +/** + * Compares two RPI values. + * + * @param data The RPI to compare with. + * @param comparitor The RPI to compare against. + * @return true if the two RPIs are the same, false otherwise. + */ bool rpi_compare(Rpi const * data, Rpi const * comparitor) { unsigned char left[RPI_SIZE_BASE64 + 1]; unsigned char right[RPI_SIZE_BASE64 + 1]; @@ -138,4 +237,5 @@ bool rpi_compare(Rpi const * data, Rpi const * comparitor) { return (memcmp(data, comparitor, RPI_SIZE) == 0); } +/** @} addtogroup RandomProximityIdentifier */ diff --git a/src/rpi_list.c b/src/rpi_list.c index a21b0da..a74e0a9 100644 --- a/src/rpi_list.c +++ b/src/rpi_list.c @@ -1,17 +1,25 @@ -/** \ingroup contrac +/** \ingroup KeyGeneration * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Provides a list of RPIs * @section DESCRIPTION * + * This class allows the simplified management of lists of Rpi objects. This is + * useful when checking DTKs received from a Diagnosis Server with RPIs + * captured over Bluetooth. Combined with the \ref DtkList class the two can + * be easily stored and passed into the \ref match_list_find_matches() function. * - * + */ + +/** \addtogroup Containers + * @{ */ // Includes @@ -32,11 +40,30 @@ // Structures +/** + * @brief An RPI list element + * + * This is an opaque structure that represents a single item in the list and + * contains an Rpi instance. + * + * The structure typedef is in rpi_list.h + */ struct _RpiListItem { Rpi * rpi; RpiListItem * next; }; +/** + * @brief The head of an RPI list + * + * This is an opaque structure that represents the head of a list of Rpi + * items. + * + * This is the object usually passed as the first parameter of every non-static + * function. + * + * The structure typedef is in dtk_list.h + */ struct _RpiList { RpiListItem * first; RpiListItem * last; @@ -46,6 +73,11 @@ struct _RpiList { // Function definitions +/** + * Creates a new instance of the class. + * + * @return The newly created object. + */ RpiList * rpi_list_new() { RpiList * data; @@ -54,6 +86,13 @@ RpiList * rpi_list_new() { return data; } +/** + * Deletes an instance of the class, freeing up the memory allocated to it. + * + * This will also delete all items contained in the list. + * + * @param data The instance to free. + */ void rpi_list_delete(RpiList * data) { RpiListItem * item; RpiListItem * next; @@ -71,6 +110,16 @@ void rpi_list_delete(RpiList * data) { } } +/** + * Adds an item to the list. + * + * This adds an Rpi item to the list. It's primarily for internal use and when + * adding RPIs to the list it's usually more appropriate to use the + * \ref rpi_list_add_beacon() function. + * + * @param data The list to append to. + * @param rpi The RPI to append. + */ void rpi_list_append(RpiList * data, Rpi * rpi) { RpiListItem * item; @@ -87,24 +136,56 @@ void rpi_list_append(RpiList * data, Rpi * rpi) { } } +/** + * Returns the first item in the list. + * + * Useful for iterating through the items in the list. + * + * @param data The list to operate on. + * @return The first item of the list. + */ RpiListItem const * rpi_list_first(RpiList const * data) { return data->first; } +/** + * Returns the next item in the list. + * + * Useful for iterating through the items in the list. + * + * @param data The current item in the list. + * @return The next item in the list following the current item. + */ RpiListItem const * rpi_list_next(RpiListItem const * data) { return data->next; } +/** + * Returns the Rpi item contained in this list item. + * + * @param data The current item in the list. + * @return The Rpi instance stored in the list element. + */ Rpi const * rpi_list_get_rpi(RpiListItem const * data) { return data->rpi; } +/** + * Adds Rpi data to the list. + * + * The rpi_bytes buffer passed in must contain exactly RPI_SIZE (16) bytes of + * data. It doen't have to be null terminated. + * + * @param data The current list to operate on. + * @param rpi_bytes The RPI value to add, in binary format. + * @param time_interval_number The time interval number to associate with the + * 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); } - - +/** @} addtogroup Containers*/ diff --git a/src/utils.c b/src/utils.c index d71aafc..cab4cf1 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,19 +1,27 @@ -/** \ingroup contrac +/** \ingroup Utils * @file - * @author David Llewellyn-Jones + * @author David Llewellyn-Jones * @version $(VERSION) * * @section LICENSE * + * Copyright David Llewellyn-Jones, 2020 + * Released under the GPLv2. * - * - * @brief + * @brief Static utitlity functions. * @section DESCRIPTION * + * Provides various static utitlity functions. In particular: * + * base64 encoding and decoding functionality. + * Time conversion: from epoch to day numbers and time interval numbers. * */ +/** \addtogroup Utils + * @{ + */ + // Includes #include @@ -28,14 +36,62 @@ // Function definitions +/** + * Returns the amount of space needed to store the base64 equivalent of a binary + * input. + * + * When converting to base64 it's often useful to know how much space will be + * needed to store the result, for example so that a buffer of the correct size + * can be allocated for it. + * + * This function returns the size needed for a buffer that will be large enough + * to store the result, including a terminating null character. The returned + * value may be larger than the size actually needed. + * + * @param binary_input The length of binary input that would be encoded. + * @return The buffer size needed to store the base64 version of the same data. + */ size_t base64_encode_size(size_t binary_input) { return (((size_t)((binary_input + 2) / 3)) * 4) + 1; } +/** + * Returns the amount of space needed to store the binary equivalent of a base64 + * string. + * + * When converting from base64 it's often useful to know how much space will be + * needed to store the result, for example so that a buffer of the correct size + * can be allocated for it. + * + * This function returns the size needed for a buffer that will be large enough + * to store the result. The returned value may be larger than the size actually + * needed. + * + * @param base64_input The length of a base64 string that would be decoded. + * @return The buffer size needed to store the binary version of the same data. + */ size_t base64_decode_size(size_t base64_input) { return (((size_t)((base64_input + 3) / 4)) * 3) + 1; } +/** + * Encodes binary data to base64 format string. + * + * Encodes the binary data provided into a base64 string, storing the result + * in the output buffer provided. The output buffer must be pre-allocated + * with enough space to store the result. The size needed can be found by + * calling the \ref base64_encode_size() function. + * + * If the output buffer is too small (based on the size provided) then the + * base64 string may be only partially written. + * + * @param input The binary data to encode. This doesn't need to be zero + * terminated. + * @param input_size The size of the input buffer to be converted. + * @param output A pre-allocated buffer to store the result. + * @param output_size The size of the allocated buffer, which will be updated + * to the number of bytes written to the buffer. + */ void base64_encode_binary_to_base64(unsigned char const *input, size_t input_size, unsigned char *output, size_t *output_size) { size_t size_in; size_t size_out; @@ -51,6 +107,24 @@ void base64_encode_binary_to_base64(unsigned char const *input, size_t input_siz EVP_EncodeBlock(output, input, size_in); } +/** + * Decodes a base64 string into the original binary data it represents. + * + * Decodes the base64 string provided into binary, storing the result in the + * output buffer provided. The output buffer must be pre-allocated with enough + * space to store the result. The size needed can be found by calling the + * \ref base64_decode_size() function. + * + * If the output buffer is too small (based on the size provided) then the + * binary output may be only partially written. + * + * @param input The base64 string to encode. This doesn't need to be zero + * terminated. + * @param input_size The size of the input buffer to be converted. + * @param output A pre-allocated buffer to store the result. + * @param output_size The size of the allocated buffer, which will be updated + * to the number of bytes written to the buffer. + */ void base64_decode_base64_to_binary(unsigned char const *input, size_t input_size, unsigned char *output, size_t *output_size) { size_t size_in; size_t size_out; @@ -66,6 +140,18 @@ void base64_decode_base64_to_binary(unsigned char const *input, size_t input_siz EVP_DecodeBlock(output, input, size_in); } +/** + * Converts a time in epoch format into a day number. + * + * Returns the day number for the given epoch time. The epoch time represents + * the number of seconds since 00:00:00 UTC on 01/01/1970. + * + * The day number is calculated as: + * (Number of Seconds since Epoch) / (60 * 60 * 24) + * + * @param epoch The epoch time in seconds. + * @return The day number for this epoch time. + */ uint32_t epoch_to_day_number(time_t epoch) { uint32_t day_number; @@ -75,6 +161,20 @@ uint32_t epoch_to_day_number(time_t epoch) { return day_number; } +/** + * Converts a time in epoch format into a time interval number. + * + * Returns the time interval number for the given epoch time. The epoch time + * represents the number of seconds since 00:00:00 UTC on 01/01/1970. + * + * The time interval number is calculated as: + * (Seconds Since Start of DayNumber) / (60 * 10) + * + * and must fall in the interval [0, 143]. + * + * @param epoch The epoch time in seconds. + * @return The time interval number for this epoch time. + */ uint8_t epoch_to_time_interval_number(time_t epoch) { uint8_t time_interval_number; uint32_t day_number; @@ -94,4 +194,5 @@ uint8_t epoch_to_time_interval_number(time_t epoch) { return time_interval_number; } +/** @} addtogroup Utils */ -- 2.25.1