ed925cbb74a54bbe1aade2f076c5c69b28e1db08
3 * @author David Llewellyn-Jones
11 * @section DESCRIPTION
25 #include <openssl/crypto.h>
26 #include <openssl/rand.h>
27 #include <openssl/err.h>
29 #include "contrac/log.h"
30 #include "contrac/utils.h"
31 #include "contrac/rpi.h"
33 #include "contrac/contrac.h"
37 #define STATUS_TK (1 << 0)
38 #define STATUS_DTK (1 << 1)
39 #define STATUS_RPI (1 << 2)
41 #define STATUS_INITIALISED (STATUS_TK | STATUS_DTK | STATUS_RPI)
46 unsigned char tk
[TK_SIZE
];
49 // Rolling proximity identifier
55 // Function prototypes
57 // Function definitions
59 Contrac
* contrac_new() {
62 data
= calloc(sizeof(Contrac
), 1);
63 data
->dtk
= dtk_new();
64 data
->rpi
= rpi_new();
69 void contrac_delete(Contrac
* data
) {
71 dtk_delete(data
->dtk
);
72 rpi_delete(data
->rpi
);
74 // Clear the data for security
75 memset(data
, 0, sizeof(Contrac
));
81 bool contrac_generate_tracing_key(Contrac
* data
) {
85 result
= RAND_bytes(data
->tk
, TK_SIZE
);
88 data
->status
|= STATUS_TK
;
91 LOG(LOG_ERR
, "Error generating tracing key: %lu\n", ERR_get_error());
97 bool contrac_set_day_number(Contrac
* data
, uint32_t day_number
) {
100 result
= ((data
->status
& STATUS_TK
) != 0);
103 result
= dtk_generate_daily_key(data
->dtk
, data
, day_number
);
107 data
->status
|= STATUS_DTK
;
113 bool contrac_set_time_interval_number(Contrac
* data
, uint8_t time_interval_number
) {
116 result
= ((data
->status
& STATUS_DTK
) != 0);
119 result
= rpi_generate_proximity_id(data
->rpi
, data
->dtk
, time_interval_number
);
123 data
->status
|= STATUS_RPI
;
129 bool contrac_get_initialised(Contrac
const * data
) {
130 return ((data
->status
& STATUS_INITIALISED
) == STATUS_INITIALISED
);
133 void contrac_set_tracing_key(Contrac
* data
, unsigned char const * tracing_key
) {
134 memcpy(data
->tk
, tracing_key
, TK_SIZE
);
135 data
->status
|= STATUS_TK
;
138 const unsigned char * contrac_get_tracing_key(Contrac
const * data
) {
142 // base64 buffer must be at least 45 bytes (TK_SIZE_BASE64 + 1)
143 void contrac_get_tracing_key_base64(Contrac
const * data
, char * base64
) {
144 size_t size
= TK_SIZE_BASE64
+ 1;
145 base64_encode_binary_to_base64(data
->tk
, TK_SIZE
, (unsigned char *)base64
, &size
);
147 if (size
!= (TK_SIZE_BASE64
+ 1)) {
148 LOG(LOG_ERR
, "Base64 tracing key has incorrect size of %d bytes.\n", size
);
152 // tracing_key input must be 44 bytes long
153 bool contrac_set_tracing_key_base64(Contrac
* data
, char const * tracing_key
) {
155 unsigned char tk
[TK_SIZE
];
158 if (strlen(tracing_key
) != TK_SIZE_BASE64
) {
159 LOG(LOG_ERR
, "Base64 tracing key has incorrect size. Should be %d bytes.\n", TK_SIZE_BASE64
);
165 base64_decode_base64_to_binary((unsigned char *)tracing_key
, TK_SIZE_BASE64
, tk
, &size
);
167 if (size
< TK_SIZE
) {
168 LOG(LOG_ERR
, "Base64 tracking key output is too short %d bytes.\n", size
);
174 contrac_set_tracing_key(data
, tk
);
180 const unsigned char * contrac_get_daily_key(Contrac
const * data
) {
181 return dtk_get_daily_key(data
->dtk
);
184 // base64 buffer must be at least 25 bytes (DTK_SIZE_BASE64 + 1)
185 void contrac_get_daily_key_base64(Contrac
const * data
, char * base64
) {
186 size_t size
= DTK_SIZE_BASE64
+ 1;
187 base64_encode_binary_to_base64(dtk_get_daily_key(data
->dtk
), DTK_SIZE
, (unsigned char *)base64
, &size
);
189 if (size
!= (DTK_SIZE_BASE64
+ 1)) {
190 LOG(LOG_ERR
, "Base64 daily key has incorrect size of %d bytes.\n", size
);
194 const unsigned char * contrac_get_proximity_id(Contrac
const * data
) {
195 return rpi_get_proximity_id(data
->rpi
);
198 // base64 buffer must be at least 25 bytes (RPI_SIZE_BASE64 + 1)
199 void contrac_get_proximity_id_base64(Contrac
const * data
, char * base64
) {
200 size_t size
= RPI_SIZE_BASE64
+ 1;
201 base64_encode_binary_to_base64(rpi_get_proximity_id(data
->rpi
), RPI_SIZE
, (unsigned char *)base64
, &size
);
203 if (size
!= (RPI_SIZE_BASE64
+ 1)) {
204 LOG(LOG_ERR
, "Base64 proximity id has incorrect size of %d bytes.\n", size
);
208 bool contrac_update_current_time(Contrac
* data
) {
218 if ((data
->status
& STATUS_TK
) == 0) {
219 // No Tracing Key has been set, so generate a random key
220 result
= contrac_generate_tracing_key(data
);
226 dn_now
= epoch_to_day_number(epoch
);
227 dn_stored
= dtk_get_day_number(data
->dtk
);
229 // Only set again if uninitialised or the time has changed
230 if ((dn_now
!= dn_stored
) || ((data
->status
& STATUS_DTK
) == 0)) {
231 result
= contrac_set_day_number(data
, dn_now
);
236 tn_now
= epoch_to_time_interval_number(epoch
);
237 tn_stored
= rpi_get_time_interval_number(data
->rpi
);
239 // Only set again if uninitialised or the time has changed
240 if ((tn_now
!= tn_stored
) || (dn_now
!= dn_stored
) || ((data
->status
& STATUS_RPI
) == 0)) {
241 result
= contrac_set_time_interval_number(data
, tn_now
);