Add initial crypto functionality
[libcontrac.git] / src / 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 <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stddef.h>
23
24 #include <openssl/crypto.h>
25 #include <openssl/rand.h>
26 #include <openssl/err.h>
27
28 #include "contrac/log.h"
29 #include "contrac/utils.h"
30 #include "contrac/rpi.h"
31
32 #include "contrac/contrac.h"
33
34 // Defines
35
36 #define STATUS_TK (1 << 0)
37 #define STATUS_DTK (1 << 1)
38 #define STATUS_RPI (1 << 2)
39
40 #define STATUS_INITIALISED (STATUS_TK | STATUS_DTK | STATUS_RPI)
41 // Structures
42
43 struct _Contrac {
44 // Tracing key
45 unsigned char tk[TK_SIZE];
46 // Daily key
47 Dtk * dtk;
48 // Rolling proximity identifier
49 Rpi * rpi;
50
51 uint32_t day_number;
52 uint8_t time_interval_number;
53
54 uint32_t status;
55 };
56
57 // Function prototypes
58
59 // Function definitions
60
61 Contrac * contrac_new() {
62 Contrac * data;
63
64 data = calloc(sizeof(Contrac), 1);
65 data->dtk = dtk_new();
66 data->rpi = rpi_new();
67
68 return data;
69 }
70
71 void contrac_delete(Contrac * data) {
72 if (data) {
73 dtk_delete(data->dtk);
74 rpi_delete(data->rpi);
75
76 // Clear the data for security
77 memset(data, 0, sizeof(Contrac));
78
79 free(data);
80 }
81 }
82
83 bool contrac_generate_tracing_key(Contrac * data) {
84 int result;
85
86 // tk <- CRNG(32)
87 result = RAND_bytes(data->tk, TK_SIZE);
88
89 if (result == 1) {
90 data->status |= STATUS_TK;
91 }
92 else {
93 LOG(LOG_ERR, "Error generating tracing key: %lu\n", ERR_get_error());
94 }
95
96 return (result == 1);
97 }
98
99 bool contrac_set_day_number(Contrac * data, uint32_t day_number) {
100 bool result;
101
102 result = ((data->status & STATUS_TK) != 0);
103
104 if (result) {
105 result = contrac_generate_daily_key(data->dtk, data, day_number);
106 }
107
108 if (result) {
109 data->day_number = day_number;
110 data->status |= STATUS_DTK;
111 }
112
113 return result;
114 }
115
116 bool contrac_set_time_interval_number(Contrac * data, uint8_t time_interval_number) {
117 bool result;
118
119 result = ((data->status & STATUS_DTK) != 0);
120
121 if (result) {
122 result = rpi_generate_proximity_id(data->rpi, data->dtk, time_interval_number);
123 }
124
125 if (result) {
126 data->time_interval_number = time_interval_number;
127 data->status |= STATUS_RPI;
128 }
129
130 return result;
131 }
132
133 bool contrac_get_initialised(Contrac const * data) {
134 return ((data->status & STATUS_INITIALISED) == STATUS_INITIALISED);
135 }
136
137 void contrac_set_tracing_key(Contrac * data, unsigned char const * tracing_key) {
138 memcpy(data->tk, tracing_key, TK_SIZE);
139 data->status |= STATUS_TK;
140 }
141
142 const unsigned char * contrac_get_tracing_key(Contrac const * data) {
143 return data->tk;
144 }
145
146 // base64 buffer must be at least 45 bytes (TK_SIZE_BASE64 + 1)
147 void contrac_get_tracing_key_base64(Contrac const * data, char * base64) {
148 size_t size = TK_SIZE_BASE64 + 1;
149 base64_encode_binary_to_base64(data->tk, TK_SIZE, (unsigned char *)base64, &size);
150
151 if (size != (TK_SIZE_BASE64 + 1)) {
152 LOG(LOG_ERR, "Base64 tracing key has incorrect size of %d bytes.\n", size);
153 }
154 }
155
156 // tracing_key input must be 44 bytes long
157 bool contrac_set_tracing_key_base64(Contrac * data, char const * tracing_key) {
158 bool result = true;
159 unsigned char tk[TK_SIZE];
160 size_t size;
161
162 if (strlen(tracing_key) != TK_SIZE_BASE64) {
163 LOG(LOG_ERR, "Base64 tracing key has incorrect size. Should be %d bytes.\n", TK_SIZE_BASE64);
164 result = false;
165 }
166
167 if (result) {
168 size = TK_SIZE;
169 base64_decode_base64_to_binary((unsigned char *)tracing_key, TK_SIZE_BASE64, tk, &size);
170
171 if (size < TK_SIZE) {
172 LOG(LOG_ERR, "Base64 tracking key output is too short %d bytes.\n", size);
173 result = false;
174 }
175 }
176
177 if (result) {
178 contrac_set_tracing_key(data, tk);
179 }
180
181 return result;
182 }
183
184 const unsigned char * contrac_get_daily_key(Contrac const * data) {
185 return dtk_get_daily_key(data->dtk);
186 }
187
188 // base64 buffer must be at least 25 bytes (DTK_SIZE_BASE64 + 1)
189 void contrac_get_daily_key_base64(Contrac const * data, char * base64) {
190 size_t size = DTK_SIZE_BASE64 + 1;
191 base64_encode_binary_to_base64(dtk_get_daily_key(data->dtk), DTK_SIZE, (unsigned char *)base64, &size);
192
193 if (size != (DTK_SIZE_BASE64 + 1)) {
194 LOG(LOG_ERR, "Base64 daily key has incorrect size of %d bytes.\n", size);
195 }
196 }
197
198 const unsigned char * contrac_get_proximity_id(Contrac const * data) {
199 return rpi_get_proximity_id(data->rpi);
200 }
201
202 // base64 buffer must be at least 25 bytes (RPI_SIZE_BASE64 + 1)
203 void contrac_get_proximity_id_base64(Contrac const * data, char * base64) {
204 size_t size = RPI_SIZE_BASE64 + 1;
205 base64_encode_binary_to_base64(rpi_get_proximity_id(data->rpi), RPI_SIZE, (unsigned char *)base64, &size);
206
207 if (size != (RPI_SIZE_BASE64 + 1)) {
208 LOG(LOG_ERR, "Base64 proximity id has incorrect size of %d bytes.\n", size);
209 }
210 }
211
212
213
214
215
216