Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnscrypt / src / proxy / cert.c
blobbca29a61a8b7506274801286d28a245dc6adc622
2 #include <config.h>
3 #include <sys/types.h>
5 #include <assert.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
11 #include <event2/dns.h>
12 #include <event2/event.h>
14 #include "cert.h"
15 #include "cert_p.h"
16 #include "crypto_sign_ed25519.h"
17 #include "dnscrypt_proxy.h"
18 #include "logger.h"
19 #include "probes.h"
20 #include "salsa20_random.h"
21 #include "utils.h"
23 static int cert_updater_update(ProxyContext * const proxy_context);
25 static int
26 cert_parse_version(ProxyContext * const proxy_context,
27 const SignedBincert * const signed_bincert,
28 const size_t signed_bincert_len)
30 if (signed_bincert_len <= (size_t) (signed_bincert->signed_data -
31 signed_bincert->magic_cert) ||
32 memcmp(signed_bincert->magic_cert, CERT_MAGIC_CERT,
33 sizeof signed_bincert->magic_cert) != 0) {
34 logger_noformat(proxy_context, LOG_DEBUG,
35 "TXT record with no certificates received");
36 return -1;
38 if (signed_bincert->version_major[0] != 0U ||
39 signed_bincert->version_major[1] != 1U) {
40 logger_noformat(proxy_context, LOG_WARNING,
41 "Unsupported certificate version");
42 return -1;
44 return 0;
47 static int
48 cert_parse_bincert(ProxyContext * const proxy_context,
49 const Bincert * const bincert,
50 const Bincert * const previous_bincert)
52 uint32_t serial;
53 memcpy(&serial, bincert->serial, sizeof serial);
54 serial = htonl(serial);
55 logger(proxy_context, LOG_INFO, "Certificate #%lu received",
56 (unsigned long) serial);
58 uint32_t ts_begin;
59 memcpy(&ts_begin, bincert->ts_begin, sizeof ts_begin);
60 ts_begin = htonl(ts_begin);
62 uint32_t ts_end;
63 memcpy(&ts_end, bincert->ts_end, sizeof ts_end);
64 ts_end = htonl(ts_end);
66 uint32_t now_u32 = (uint32_t) time(NULL);
68 if (now_u32 < ts_begin) {
69 logger_noformat(proxy_context, LOG_INFO,
70 "Certificate not activated yet");
71 return -1;
73 if (now_u32 > ts_end) {
74 logger_noformat(proxy_context, LOG_INFO,
75 "Certificate expired");
76 return -1;
78 logger_noformat(proxy_context, LOG_INFO, "Certificate valid");
79 if (previous_bincert == NULL) {
80 return 0;
83 uint32_t previous_serial;
84 memcpy(&previous_serial, previous_bincert->serial, sizeof previous_serial);
85 previous_serial = htonl(previous_serial);
86 if (previous_serial > serial) {
87 logger(proxy_context, LOG_INFO,
88 "Certificate #%lu has been superseded by certificate #%lu",
89 (unsigned long) previous_serial, (unsigned long) serial);
90 return -1;
92 logger(proxy_context, LOG_INFO,
93 "This certificates supersedes certificate #%lu",
94 (unsigned long) previous_serial);
96 return 0;
99 static int
100 cert_open_bincert(ProxyContext * const proxy_context,
101 const SignedBincert * const signed_bincert,
102 const size_t signed_bincert_len,
103 Bincert ** const bincert_p)
105 Bincert *bincert;
106 unsigned long long bincert_data_len_ul;
107 size_t bincert_size;
108 size_t signed_data_len;
110 if (cert_parse_version(proxy_context,
111 signed_bincert, signed_bincert_len) != 0) {
112 DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_COMMUNICATION();
113 return -1;
115 bincert_size = signed_bincert_len;
116 if ((bincert = malloc(bincert_size)) == NULL) {
117 DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_COMMUNICATION();
118 return -1;
120 assert(signed_bincert_len >= (size_t) (signed_bincert->signed_data -
121 signed_bincert->magic_cert));
122 signed_data_len = signed_bincert_len -
123 (size_t) (signed_bincert->signed_data - signed_bincert->magic_cert);
124 assert(bincert_size - (size_t) (bincert->server_publickey -
125 bincert->magic_cert) == signed_data_len);
126 if (crypto_sign_ed25519_open(bincert->server_publickey, &bincert_data_len_ul,
127 signed_bincert->signed_data, signed_data_len,
128 proxy_context->provider_publickey) != 0) {
129 free(bincert);
130 logger_noformat(proxy_context, LOG_ERR,
131 "Suspicious certificate received");
132 DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_SECURITY();
133 return -1;
135 if (cert_parse_bincert(proxy_context, bincert, *bincert_p) != 0) {
136 memset(bincert, 0, sizeof *bincert);
137 free(bincert);
138 return -1;
140 if (*bincert_p != NULL) {
141 memset(*bincert_p, 0, sizeof **bincert_p);
142 free(*bincert_p);
144 *bincert_p = bincert;
146 return 0;
149 static void
150 cert_print_server_key(ProxyContext * const proxy_context)
152 char fingerprint[80U];
154 dnscrypt_key_to_fingerprint(fingerprint,
155 proxy_context->resolver_publickey);
156 logger(proxy_context, LOG_INFO,
157 "Server Key genuine fingerprint is %s", fingerprint);
160 static void
161 cert_timer_cb(evutil_socket_t handle, const short event,
162 void * const proxy_context_)
164 ProxyContext * const proxy_context = proxy_context_;
166 (void) handle;
167 (void) event;
168 logger_noformat(proxy_context, LOG_INFO,
169 "Refetching Certificates");
170 cert_updater_update(proxy_context);
173 static void
174 cert_reschedule_query(ProxyContext * const proxy_context,
175 const time_t query_retry_delay)
177 CertUpdater *cert_updater = &proxy_context->cert_updater;
179 if (evtimer_pending(cert_updater->cert_timer, NULL)) {
180 return;
182 const struct timeval tv = { .tv_sec = query_retry_delay, .tv_usec = 0 };
183 evtimer_add(cert_updater->cert_timer, &tv);
186 static void
187 cert_reschedule_query_after_failure(ProxyContext * const proxy_context)
189 CertUpdater *cert_updater = &proxy_context->cert_updater;
190 time_t query_retry_delay;
192 if (evtimer_pending(cert_updater->cert_timer, NULL)) {
193 return;
195 query_retry_delay = (time_t)
196 (CERT_QUERY_RETRY_MIN_DELAY +
197 (time_t) cert_updater->query_retry_step *
198 (CERT_QUERY_RETRY_MAX_DELAY - CERT_QUERY_RETRY_MIN_DELAY) /
199 CERT_QUERY_RETRY_STEPS);
200 if (cert_updater->query_retry_step < CERT_QUERY_RETRY_STEPS) {
201 cert_updater->query_retry_step++;
203 cert_reschedule_query(proxy_context, query_retry_delay);
204 DNSCRYPT_PROXY_CERTS_UPDATE_RETRY();
207 static void
208 cert_reschedule_query_after_success(ProxyContext * const proxy_context)
210 if (evtimer_pending(proxy_context->cert_updater.cert_timer, NULL)) {
211 return;
213 cert_reschedule_query(proxy_context, (time_t)
214 CERT_QUERY_RETRY_DELAY_AFTER_SUCCESS_MIN_DELAY
215 + (time_t) salsa20_random_uniform
216 (CERT_QUERY_RETRY_DELAY_AFTER_SUCCESS_JITTER));
219 static void
220 cert_query_cb(int result, char type, int count, int ttl,
221 void * const txt_records_, void * const arg)
223 Bincert *bincert = NULL;
224 ProxyContext *proxy_context = arg;
225 const struct txt_record *txt_records = txt_records_;
226 int i = 0;
228 (void) type;
229 (void) ttl;
230 DNSCRYPT_PROXY_CERTS_UPDATE_RECEIVED();
231 evdns_base_free(proxy_context->cert_updater.evdns_base, 0);
232 proxy_context->cert_updater.evdns_base = NULL;
233 if (result != DNS_ERR_NONE) {
234 logger_noformat(proxy_context, LOG_ERR,
235 "Unable to retrieve server certificates");
236 cert_reschedule_query_after_failure(proxy_context);
237 DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_COMMUNICATION();
238 return;
240 assert(count == 0 || count == 1);
241 while (i < count) {
242 cert_open_bincert(proxy_context,
243 (const SignedBincert *) txt_records[i].txt,
244 txt_records[i].len, &bincert);
245 i++;
247 if (bincert == NULL) {
248 logger_noformat(proxy_context, LOG_ERR,
249 "No useable certificates found");
250 cert_reschedule_query_after_failure(proxy_context);
251 DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_NOCERTS();
252 return;
254 COMPILER_ASSERT(sizeof proxy_context->resolver_publickey ==
255 sizeof bincert->server_publickey);
256 memcpy(proxy_context->resolver_publickey, bincert->server_publickey,
257 sizeof proxy_context->resolver_publickey);
258 COMPILER_ASSERT(sizeof proxy_context->dnscrypt_magic_query ==
259 sizeof bincert->magic_query);
260 memcpy(proxy_context->dnscrypt_magic_query, bincert->magic_query,
261 sizeof proxy_context->dnscrypt_magic_query);
262 cert_print_server_key(proxy_context);
263 dnscrypt_client_init_magic_query(&proxy_context->dnscrypt_client,
264 bincert->magic_query);
265 memset(bincert, 0, sizeof *bincert);
266 free(bincert);
267 dnscrypt_client_init_nmkey(&proxy_context->dnscrypt_client,
268 proxy_context->resolver_publickey);
269 dnscrypt_proxy_start_listeners(proxy_context);
270 proxy_context->cert_updater.query_retry_step = 0U;
271 cert_reschedule_query_after_success(proxy_context);
272 DNSCRYPT_PROXY_CERTS_UPDATE_DONE((unsigned char *)
273 proxy_context->resolver_publickey);
277 cert_updater_init(ProxyContext * const proxy_context)
279 CertUpdater *cert_updater = &proxy_context->cert_updater;
281 memset(cert_updater, 0, sizeof *cert_updater);
282 assert(proxy_context->event_loop != NULL);
283 assert(cert_updater->cert_timer == NULL);
284 if ((cert_updater->cert_timer =
285 evtimer_new(proxy_context->event_loop,
286 cert_timer_cb, proxy_context)) == NULL) {
287 return -1;
289 cert_updater->query_retry_step = 0U;
290 cert_updater->evdns_base = NULL;
292 return 0;
295 static int
296 cert_updater_update(ProxyContext * const proxy_context)
298 CertUpdater *cert_updater = &proxy_context->cert_updater;
300 DNSCRYPT_PROXY_CERTS_UPDATE_START();
301 if (cert_updater->evdns_base != NULL) {
302 evdns_base_free(cert_updater->evdns_base, 0);
304 if ((cert_updater->evdns_base =
305 evdns_base_new(proxy_context->event_loop, 0)) == NULL) {
306 return -1;
308 if (evdns_base_nameserver_sockaddr_add(cert_updater->evdns_base,
309 (struct sockaddr *)
310 &proxy_context->resolver_sockaddr,
311 proxy_context->resolver_sockaddr_len,
312 DNS_QUERY_NO_SEARCH) != 0) {
313 return -1;
315 if (proxy_context->tcp_only != 0 &&
316 strcmp(proxy_context->resolver_port,
317 DNS_DEFAULT_STANDARD_DNS_PORT) != 0) {
318 (void) evdns_base_nameserver_ip_add(cert_updater->evdns_base,
319 proxy_context->resolver_ip);
321 if (evdns_base_resolve_txt(cert_updater->evdns_base,
322 proxy_context->provider_name,
323 DNS_QUERY_NO_SEARCH,
324 cert_query_cb,
325 proxy_context) == NULL) {
326 return -1;
328 return 0;
332 cert_updater_start(ProxyContext * const proxy_context)
334 evdns_set_random_init_fn(NULL);
335 evdns_set_random_bytes_fn(salsa20_random_buf);
336 cert_updater_update(proxy_context);
338 return 0;
341 void
342 cert_updater_stop(ProxyContext * const proxy_context)
344 CertUpdater * const cert_updater = &proxy_context->cert_updater;
346 assert(cert_updater->cert_timer != NULL);
347 evtimer_del(cert_updater->cert_timer);
350 void
351 cert_updater_free(ProxyContext * const proxy_context)
353 CertUpdater * const cert_updater = &proxy_context->cert_updater;
355 event_free(cert_updater->cert_timer);
356 cert_updater->cert_timer = NULL;
357 if (cert_updater->evdns_base != NULL) {
358 evdns_base_free(cert_updater->evdns_base, 0);
359 cert_updater->evdns_base = NULL;