Add initial crypto functionality
[libcontrac.git] / tests / test_contrac.c
1 /** \ingroup contrac
2 * @file
3 * @author David Llewellyn-Jones
4 * @version $(VERSION)
5 *
6 * @section LICENSE
7 *
8 *
9 *
10 * @brief
11 * @section DESCRIPTION
12 *
13 *
14 *
15 */
16
17 // Includes
18
19 #include <check.h>
20 #include <malloc.h>
21
22 #include "contrac/contrac.h"
23 #include "contrac/contrac_private.h"
24 #include "contrac/utils.h"
25 #include "contrac/dtk.h"
26 #include "contrac/rpi.h"
27 #include "contrac/dtk_list.h"
28 #include "contrac/rpi_list.h"
29 #include "contrac/match.h"
30
31 // Defines
32
33 // Structures
34
35 // Function prototypes
36
37 // Function definitions
38
39 START_TEST (check_base64) {
40 //bool result;
41 //int pos;
42 char *string[4] = {
43 "This is a string", // 16
44 "Maybe upon a time", // 17
45 "And then there was", // 18
46 "In the end there is", // 19
47 };
48 char *base64[4] = {
49 "VGhpcyBpcyBhIHN0cmluZw==", // 24
50 "TWF5YmUgdXBvbiBhIHRpbWU=", // 24
51 "QW5kIHRoZW4gdGhlcmUgd2Fz", // 24
52 "SW4gdGhlIGVuZCB0aGVyZSBpcw==", // 24
53 };
54 size_t size;
55 char * output;
56 int pos;
57
58 for (pos = 0; pos < 4; ++pos) {
59 // Encode
60 size = base64_encode_size(strlen(string[pos]));
61
62 ck_assert(size == (strlen(base64[pos]) + 1));
63 output = calloc(sizeof(char), size);
64
65 base64_encode_binary_to_base64((unsigned char *)string[pos], strlen(string[pos]), (unsigned char *)output, &size);
66
67 ck_assert(size == (strlen(base64[pos]) + 1));
68 ck_assert_str_eq(output, base64[pos]);
69
70 // Decode
71 size = base64_decode_size(strlen(base64[pos]));
72
73 ck_assert(size >= (strlen(string[pos]) + 1));
74 ck_assert(size < (strlen(string[pos]) + 4));
75 output = calloc(sizeof(char), size + 1);
76
77 base64_decode_base64_to_binary((unsigned char *)base64[pos], strlen(base64[pos]), (unsigned char *)output, &size);
78
79 ck_assert(size >= (strlen(string[pos]) + 1));
80 ck_assert(size < (strlen(string[pos]) + 4));
81 ck_assert_str_eq(output, string[pos]);
82 }
83 }
84 END_TEST
85
86 START_TEST (check_contrac) {
87 bool result;
88 unsigned char const *tk;
89 int pos;
90
91 // Generate some keys, check the results
92 Contrac * contrac;
93
94 contrac = contrac_new();
95 ck_assert(contrac != NULL);
96
97 result = contrac_get_initialised(contrac);
98 ck_assert(result == false);
99
100 tk = contrac_get_tracing_key(contrac);
101 // The tracing key will initialise to zero by default
102 for (pos = 0; pos < TK_SIZE; ++pos) {
103 ck_assert(tk[pos] == 0);
104 }
105
106 result = contrac_generate_tracing_key(contrac);
107 ck_assert(result == true);
108
109 result = contrac_get_initialised(contrac);
110 ck_assert(result == false);
111
112 // The random generator could generate all zeros, but we'll take the risk
113 tk = contrac_get_tracing_key(contrac);
114 result = false;
115 for (pos = 0; pos < TK_SIZE; ++pos) {
116 if (tk[pos] != 0) {
117 result = true;
118 }
119 }
120 ck_assert(result == true);
121
122 result = contrac_get_initialised(contrac);
123 ck_assert(result == false);
124
125 result = contrac_set_day_number(contrac, 23);
126 ck_assert(result == true);
127
128 result = contrac_get_initialised(contrac);
129 ck_assert(result == false);
130
131 result = contrac_set_time_interval_number(contrac, 76);
132 ck_assert(result == true);
133
134 result = contrac_get_initialised(contrac);
135 ck_assert(result == true);
136
137 // Clean up
138 contrac_delete(contrac);
139 }
140 END_TEST
141
142 START_TEST (check_dtk) {
143 bool result;
144 char const *tracing_key_base64 = "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
145 char tk_base64[TK_SIZE_BASE64 + 1];
146 char dtk_base64[DTK_SIZE_BASE64 + 1];
147
148 // Generate some keys, check the results
149 Contrac * contrac;
150
151 contrac = contrac_new();
152 ck_assert(contrac != NULL);
153
154 contrac_set_tracing_key_base64(contrac, tracing_key_base64);
155
156 contrac_get_tracing_key_base64(contrac, tk_base64);
157 ck_assert_int_eq(strlen(tk_base64), TK_SIZE_BASE64);
158 ck_assert_str_eq(tracing_key_base64, tk_base64);
159
160 // Check the Daily Tracing Keys are generated correctly
161 // Should use the standard test vectors when they're available
162
163 result = contrac_set_day_number(contrac, 12);
164 ck_assert(result);
165 contrac_get_daily_key_base64(contrac, dtk_base64);
166 ck_assert_int_eq(strlen(dtk_base64), DTK_SIZE_BASE64);
167 ck_assert_str_eq(dtk_base64, "AzZ389DsGecAjZqby1sLNQ==");
168
169
170 result = contrac_set_day_number(contrac, 0);
171 ck_assert(result);
172 contrac_get_daily_key_base64(contrac, dtk_base64);
173 ck_assert_int_eq(strlen(dtk_base64), DTK_SIZE_BASE64);
174 ck_assert_str_eq(dtk_base64, "p7LrsTReTw3k721eIWDjRw==");
175
176 result = contrac_set_day_number(contrac, 143);
177 ck_assert(result);
178 contrac_get_daily_key_base64(contrac, dtk_base64);
179 ck_assert_int_eq(strlen(dtk_base64), DTK_SIZE_BASE64);
180 ck_assert_str_eq(dtk_base64, "f6RZL/2wGCzxSBzZc9xVNQ==");
181
182 // Clean up
183 contrac_delete(contrac);
184 }
185 END_TEST
186
187 START_TEST (check_rpi) {
188 bool result;
189 char const *tracing_key_base64[2] = {
190 "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=",
191 "U3CgpSjF0qFW8DNSTHVWF99few5FOW7RV7kA9j6LFTc=",
192 };
193 char rpi_base64[RPI_SIZE_BASE64 + 1];
194
195 // Generate some keys, check the results
196 Contrac * contrac;
197
198 contrac = contrac_new();
199 ck_assert(contrac != NULL);
200
201 contrac_set_tracing_key_base64(contrac, tracing_key_base64[0]);
202
203 result = contrac_set_day_number(contrac, 9);
204 ck_assert(result);
205
206 // Check the Rolling Proximity Identifiers are generated correctly
207 // Should use the standard test vectors when they're available
208
209 result = contrac_set_time_interval_number(contrac, 0);
210 ck_assert(result);
211 contrac_get_proximity_id_base64(contrac, rpi_base64);
212 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
213 ck_assert_str_eq(rpi_base64, "++ucH9hoIkGwCzM+J09faQ==");
214
215 result = contrac_set_time_interval_number(contrac, 82);
216 ck_assert(result);
217 contrac_get_proximity_id_base64(contrac, rpi_base64);
218 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
219 ck_assert_str_eq(rpi_base64, "GrqeroryZQ+Uvhx10zfKWw==");
220
221 result = contrac_set_time_interval_number(contrac, 143);
222 ck_assert(result);
223 contrac_get_proximity_id_base64(contrac, rpi_base64);
224 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
225 ck_assert_str_eq(rpi_base64, "+9eL1UlYZ9buUCFF5qRDUA==");
226
227 contrac_set_tracing_key_base64(contrac, tracing_key_base64[1]);
228
229 result = contrac_set_day_number(contrac, 500);
230 ck_assert(result);
231
232 result = contrac_set_time_interval_number(contrac, 1);
233 ck_assert(result);
234 contrac_get_proximity_id_base64(contrac, rpi_base64);
235 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
236 ck_assert_str_eq(rpi_base64, "XmePWi0HlgHyBcVUb0KhjQ==");
237
238 result = contrac_set_time_interval_number(contrac, 27);
239 ck_assert(result);
240 contrac_get_proximity_id_base64(contrac, rpi_base64);
241 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
242 ck_assert_str_eq(rpi_base64, "LlPznz6D044ZKYsY3sHJew==");
243
244 result = contrac_set_time_interval_number(contrac, 143);
245 ck_assert(result);
246 contrac_get_proximity_id_base64(contrac, rpi_base64);
247 ck_assert_int_eq(strlen(rpi_base64), RPI_SIZE_BASE64);
248 ck_assert_str_eq(rpi_base64, "QDG50cy9NTXZ3zDAUGkePQ==");
249
250 // Clean up
251 contrac_delete(contrac);
252 }
253 END_TEST
254
255 START_TEST (check_match) {
256 bool result;
257 char const *tracing_key_base64 = "3UmKrtcQ2tfLE8UPSXHb4PtgRfE0E2xdSs+PGVIS8cc=";
258 RpiList * beacon_list;
259 DtkList * diagnosis_list;
260 // There are four matches in amongst this lot
261 // (day, time) = (12, 15), (1175, 142), (1175, 67), (12, 93)
262 uint32_t beacon_days[8] = {55, 12, 0, 8787, 1175, 1175, 187, 12};
263 uint8_t beacon_times[8] = {1, 15, 5, 101, 142, 67, 51, 93};
264 uint32_t diagnosis_days[2] = {1175, 12};
265 // Summarise the four matches
266 uint32_t match_days[4] = {12, 1175, 1175, 12};
267 uint8_t match_times[4] = {15, 142, 67, 93};
268 int pos;
269 const unsigned char * rpi_bytes;
270 const unsigned char * dtk_bytes;
271 Rpi * rpi;
272 Dtk * dtk;
273 MatchList * matches;
274 MatchListItem const * match;
275 int match_count;
276
277 // Generate some keys, check the results
278 Contrac * contrac;
279
280 contrac = contrac_new();
281 ck_assert(contrac != NULL);
282
283 contrac_set_tracing_key_base64(contrac, tracing_key_base64);
284
285 // Generate some beacons (as if collected over BlueTooth)
286
287 beacon_list = rpi_list_new();
288
289 for (pos = 0; pos < 8; ++pos) {
290 result = contrac_set_day_number(contrac, beacon_days[pos]);
291 ck_assert(result);
292
293 result = contrac_set_time_interval_number(contrac, beacon_times[pos]);
294 ck_assert(result);
295
296 rpi_bytes = contrac_get_proximity_id(contrac);
297 rpi = rpi_new();
298 rpi_assign(rpi, rpi_bytes, beacon_times[pos]);
299
300 rpi_list_append(beacon_list, rpi);
301 }
302
303 // Generate some diagnosis data (as if provided by a diagnosis server)
304
305 diagnosis_list = dtk_list_new();
306 for (pos = 0; pos < 2; ++pos) {
307 result = contrac_set_day_number(contrac, diagnosis_days[pos]);
308 ck_assert(result);
309
310 dtk_bytes = contrac_get_daily_key(contrac);
311 dtk = dtk_new();
312 dtk_assign(dtk, dtk_bytes, diagnosis_days[pos]);
313
314 dtk_list_append(diagnosis_list, dtk);
315 }
316
317 // Check that the matching algorithm identifies the beacons that match
318
319 matches = match_list_new();
320 match_list_find_matches(matches, beacon_list, diagnosis_list);
321
322 match = match_list_first(matches);
323
324 match_count = 0;
325 while (match) {
326 result = false;
327 for (pos = 0; pos < 4; ++pos) {
328 if ((match_list_get_day_number(match) == match_days[pos]) && (match_list_get_time_interval_number(match) == match_times[pos])) {
329 result = true;
330 }
331 }
332
333 ck_assert(result);
334
335 match_count++;
336 match = match_list_next(match);
337 }
338 ck_assert_int_eq(match_count, 4);
339
340 // Clean up
341 match_list_delete(matches);
342 rpi_list_delete(beacon_list);
343 dtk_list_delete(diagnosis_list);
344 contrac_delete(contrac);
345 }
346 END_TEST
347
348 int main(void) {
349 int failed;
350 Suite * s;
351 SRunner *sr;
352 TCase * tc;
353
354 s = suite_create("libcontrac");
355
356 tc = tcase_create("Contrac");
357 tcase_add_test(tc, check_base64);
358 tcase_add_test(tc, check_contrac);
359 tcase_add_test(tc, check_dtk);
360 tcase_add_test(tc, check_rpi);
361 tcase_add_test(tc, check_match);
362 suite_add_tcase(s, tc);
363 sr = srunner_create(s);
364
365 srunner_run_all(sr, CK_NORMAL);
366 failed = srunner_ntests_failed(sr);
367 srunner_free(sr);
368
369 return (failed == 0) ? 0 : -1;
370 }
371