1 #include "dnscrypt.h"
2
3 typedef struct Cached_ {
4 uint8_t pk[crypto_box_PUBLICKEYBYTES];
5 uint8_t server_pk[crypto_box_PUBLICKEYBYTES];
6 uint8_t shared[crypto_box_BEFORENMBYTES];
7 } Cached;
8
9 static Cached cache[4096];
10
11 static inline size_t
h12(const uint8_t pk[crypto_box_PUBLICKEYBYTES],const uint8_t server_pk[crypto_box_PUBLICKEYBYTES],bool use_xchacha20)12 h12(const uint8_t pk[crypto_box_PUBLICKEYBYTES],
13 const uint8_t server_pk[crypto_box_PUBLICKEYBYTES], bool use_xchacha20)
14 {
15 uint64_t a, b, c, d, e;
16 uint32_t h;
17
18 memcpy(&a, &pk[0], 8); memcpy(&b, &pk[8], 8);
19 memcpy(&c, &pk[16], 8); memcpy(&d, &pk[24], 8);
20 e = a ^ b ^ c ^ d;
21 memcpy(&a, &server_pk[0], 8); memcpy(&b, &server_pk[8], 8);
22 memcpy(&c, &server_pk[16], 8); memcpy(&d, &server_pk[24], 8);
23 e ^= a ^ b ^ c ^ d;
24 h = ((uint32_t) e) ^ ((uint32_t) (e >> 32));
25 return (size_t) (((h >> 20) ^ (h >> 8) ^ (h << 4) ^ use_xchacha20) & 0xfff);
26 }
27
28 static int
cache_get(Cached ** const cached_p,const uint8_t pk[crypto_box_PUBLICKEYBYTES],const uint8_t server_pk[crypto_box_PUBLICKEYBYTES],const bool use_xchacha20)29 cache_get(Cached ** const cached_p,
30 const uint8_t pk[crypto_box_PUBLICKEYBYTES],
31 const uint8_t server_pk[crypto_box_PUBLICKEYBYTES], const bool use_xchacha20)
32 {
33 Cached *cached = &cache[h12(pk, server_pk, use_xchacha20)];
34
35 *cached_p = cached;
36 if (memcmp(cached->pk, pk, crypto_box_PUBLICKEYBYTES - 1) == 0 &&
37 (cached->pk[crypto_box_PUBLICKEYBYTES - 1] ^ use_xchacha20) == pk[crypto_box_PUBLICKEYBYTES - 1] &&
38 memcmp(cached->server_pk, server_pk, crypto_box_PUBLICKEYBYTES - 1) == 0) {
39 return 1;
40 }
41 return 0;
42 }
43
44 static void
cache_set(const uint8_t shared[crypto_box_BEFORENMBYTES],const uint8_t pk[crypto_box_PUBLICKEYBYTES],const uint8_t server_pk[crypto_box_PUBLICKEYBYTES],const bool use_xchacha20)45 cache_set(const uint8_t shared[crypto_box_BEFORENMBYTES],
46 const uint8_t pk[crypto_box_PUBLICKEYBYTES],
47 const uint8_t server_pk[crypto_box_PUBLICKEYBYTES], const bool use_xchacha20)
48 {
49 Cached *cached;
50
51 cache_get(&cached, pk, server_pk, use_xchacha20);
52 memcpy(cached->pk, pk, crypto_box_PUBLICKEYBYTES);
53 cached->pk[crypto_box_PUBLICKEYBYTES - 1] ^= use_xchacha20;
54 memcpy(cached->server_pk, server_pk, crypto_box_PUBLICKEYBYTES);
55 memcpy(cached->shared, shared, crypto_box_BEFORENMBYTES);
56 }
57
58 const dnsccert *
find_cert(const struct context * c,const unsigned char magic_query[DNSCRYPT_MAGIC_HEADER_LEN],const size_t dns_query_len)59 find_cert(const struct context *c,
60 const unsigned char magic_query[DNSCRYPT_MAGIC_HEADER_LEN],
61 const size_t dns_query_len)
62 {
63 const dnsccert *certs = c->certs;
64 size_t i;
65
66 if (dns_query_len <= DNSCRYPT_QUERY_HEADER_SIZE) {
67 return NULL;
68 }
69 for (i = 0U; i < c->certs_count; i++) {
70 if (memcmp(certs[i].magic_query, magic_query, DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
71 return &certs[i];
72 }
73 }
74 if (memcmp(magic_query, CERT_OLD_MAGIC_HEADER, DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
75 return &certs[0];
76 }
77 return NULL;
78 }
79
80 int
dnscrypt_cmp_client_nonce(const uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],const uint8_t * const buf,const size_t len)81 dnscrypt_cmp_client_nonce(const uint8_t
82 client_nonce[crypto_box_HALF_NONCEBYTES],
83 const uint8_t *const buf, const size_t len)
84 {
85 const size_t client_nonce_offset = sizeof(DNSCRYPT_MAGIC_RESPONSE) - 1;
86
87 if (len < client_nonce_offset + crypto_box_HALF_NONCEBYTES
88 || memcmp(client_nonce, buf + client_nonce_offset,
89 crypto_box_HALF_NONCEBYTES) != 0) {
90 return -1;
91 }
92
93 return 0;
94 }
95
96 uint64_t
dnscrypt_hrtime(void)97 dnscrypt_hrtime(void)
98 {
99 struct timeval tv;
100 uint64_t ts = (uint64_t)0U;
101 int ret;
102
103 ret = evutil_gettimeofday(&tv, NULL);
104 assert(ret == 0);
105 if (ret == 0) {
106 ts = (uint64_t)tv.tv_sec * 1000000U + (uint64_t)tv.tv_usec;
107 }
108 return ts;
109 }
110
111 void
dnscrypt_key_to_fingerprint(char fingerprint[80U],const uint8_t * const key)112 dnscrypt_key_to_fingerprint(char fingerprint[80U], const uint8_t *const key)
113 {
114 const size_t fingerprint_size = 80U;
115 size_t fingerprint_pos = (size_t) 0U;
116 size_t key_pos = (size_t) 0U;
117
118 COMPILER_ASSERT(crypto_box_PUBLICKEYBYTES == 32U);
119 COMPILER_ASSERT(crypto_box_SECRETKEYBYTES == 32U);
120 for (;;) {
121 assert(fingerprint_size > fingerprint_pos);
122 evutil_snprintf(&fingerprint[fingerprint_pos],
123 fingerprint_size - fingerprint_pos, "%02X%02X",
124 key[key_pos], key[key_pos + 1U]);
125 key_pos += 2U;
126 if (key_pos >= crypto_box_PUBLICKEYBYTES) {
127 break;
128 }
129 fingerprint[fingerprint_pos + 4U] = ':';
130 fingerprint_pos += 5U;
131 }
132 }
133
134 static int
_dnscrypt_parse_char(uint8_t key[crypto_box_PUBLICKEYBYTES],size_t * const key_pos_p,int * const state_p,const int c,uint8_t * const val_p)135 _dnscrypt_parse_char(uint8_t key[crypto_box_PUBLICKEYBYTES],
136 size_t * const key_pos_p, int *const state_p,
137 const int c, uint8_t *const val_p)
138 {
139 uint8_t c_val;
140
141 switch (*state_p) {
142 case 0:
143 case 1:
144 if (isspace(c) || (c == ':' && *state_p == 0)) {
145 break;
146 }
147 if (c == '#') {
148 *state_p = 2;
149 break;
150 }
151 if (!isxdigit(c)) {
152 return -1;
153 }
154 c_val = (uint8_t)((c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10);
155 assert(c_val < 16U);
156 if (*state_p == 0) {
157 *val_p = c_val * 16U;
158 *state_p = 1;
159 } else {
160 *val_p |= c_val;
161 key[(*key_pos_p)++] = *val_p;
162 if (*key_pos_p >= crypto_box_PUBLICKEYBYTES) {
163 return 0;
164 }
165 *state_p = 0;
166 }
167 break;
168 case 2:
169 if (c == '\n') {
170 *state_p = 0;
171 }
172 }
173 return 1;
174 }
175
176 int
dnscrypt_fingerprint_to_key(const char * const fingerprint,uint8_t key[crypto_box_PUBLICKEYBYTES])177 dnscrypt_fingerprint_to_key(const char *const fingerprint,
178 uint8_t key[crypto_box_PUBLICKEYBYTES])
179 {
180 const char *p = fingerprint;
181 size_t key_pos = (size_t) 0U;
182 int c;
183 int ret;
184 int state = 0;
185 uint8_t val = 0U;
186
187 if (fingerprint == NULL) {
188 return -1;
189 }
190 while ((c = tolower((int)(unsigned char)*p)) != 0) {
191 ret = _dnscrypt_parse_char(key, &key_pos, &state, c, &val);
192 if (ret <= 0) {
193 return ret;
194 }
195 p++;
196 }
197 return -1;
198 }
199
200 /**
201 * Add random padding to a buffer, according to a client nonce.
202 * The length has to depend on the query in order to avoid reply attacks.
203 *
204 * @param buf a buffer
205 * @param len the initial size of the buffer
206 * @param max_len the maximum size
207 * @param nonce a nonce, made of the client nonce repeated twice
208 * @param secretkey
209 * @return the new size, after padding
210 */
211 size_t
dnscrypt_pad(uint8_t * buf,const size_t len,const size_t max_len,const uint8_t * nonce,const uint8_t * secretkey)212 dnscrypt_pad(uint8_t *buf, const size_t len, const size_t max_len,
213 const uint8_t *nonce, const uint8_t *secretkey)
214 {
215 uint8_t *buf_padding_area = buf + len;
216 size_t padded_len;
217 uint32_t rnd;
218
219 // no padding
220 if (max_len < len + DNSCRYPT_MIN_PAD_LEN)
221 return len;
222
223 assert(nonce[crypto_box_HALF_NONCEBYTES] == nonce[0]);
224
225 crypto_stream((unsigned char *)&rnd, (unsigned long long)sizeof(rnd), nonce,
226 secretkey);
227 padded_len =
228 len + DNSCRYPT_MIN_PAD_LEN + rnd % (max_len - len -
229 DNSCRYPT_MIN_PAD_LEN + 1);
230 padded_len += DNSCRYPT_BLOCK_SIZE - padded_len % DNSCRYPT_BLOCK_SIZE;
231 if (padded_len > max_len)
232 padded_len = max_len;
233
234 memset(buf_padding_area, 0, padded_len - len);
235 *buf_padding_area = 0x80;
236
237 return padded_len;
238 }
239
240 // 8 bytes: magic_query
241 // 32 bytes: the client's DNSCurve public key (crypto_box_PUBLICKEYBYTES)
242 // 12 bytes: a client-selected nonce (crypto_box_HALF_NONCEBYTES)
243 // 16 bytes: Poly1305 MAC (crypto_box_MACBYTES)
244
245 #define DNSCRYPT_QUERY_BOX_OFFSET \
246 (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES)
247
248 int
dnscrypt_server_uncurve(struct context * c,const dnsccert * cert,uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],uint8_t nmkey[crypto_box_BEFORENMBYTES],uint8_t * const buf,size_t * const lenp)249 dnscrypt_server_uncurve(struct context *c, const dnsccert *cert,
250 uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
251 uint8_t nmkey[crypto_box_BEFORENMBYTES],
252 uint8_t *const buf, size_t * const lenp)
253 {
254 size_t len = *lenp;
255
256 if (len <= DNSCRYPT_QUERY_HEADER_SIZE) {
257 return -1;
258 }
259
260 struct dnscrypt_query_header *query_header =
261 (struct dnscrypt_query_header *)buf;
262 Cached *cached;
263
264 if (cache_get(&cached, query_header->publickey, cert->keypair->crypt_publickey, XCHACHA20_CERT(cert))) {
265 memcpy(nmkey, cached->shared, crypto_box_BEFORENMBYTES);
266 } else {
267 memcpy(nmkey, query_header->publickey, crypto_box_PUBLICKEYBYTES);
268 if (XCHACHA20_CERT(cert)) {
269 #ifdef HAVE_CRYPTO_BOX_CURVE25519XCHACHA20POLY1305_OPEN_EASY
270 if (crypto_box_curve25519xchacha20poly1305_beforenm(nmkey, nmkey,
271 cert->keypair->crypt_secretkey) != 0) {
272 return -1;
273 }
274 #endif
275 } else {
276 if (crypto_box_beforenm(nmkey, nmkey,
277 cert->keypair->crypt_secretkey) != 0) {
278 return -1;
279 }
280 }
281 cache_set(nmkey, query_header->publickey, cert->keypair->crypt_publickey, XCHACHA20_CERT(cert));
282 }
283
284 uint8_t nonce[crypto_box_NONCEBYTES];
285 memcpy(nonce, query_header->nonce, crypto_box_HALF_NONCEBYTES);
286 memset(nonce + crypto_box_HALF_NONCEBYTES, 0, crypto_box_HALF_NONCEBYTES);
287
288 if (XCHACHA20_CERT(cert)) {
289 #ifdef HAVE_CRYPTO_BOX_CURVE25519XCHACHA20POLY1305_OPEN_EASY
290 if (crypto_box_curve25519xchacha20poly1305_open_easy_afternm
291 (buf, buf + DNSCRYPT_QUERY_BOX_OFFSET,
292 len - DNSCRYPT_QUERY_BOX_OFFSET, nonce, nmkey) != 0) {
293 return -1;
294 }
295 #endif
296 } else {
297 if (crypto_box_open_easy_afternm
298 (buf, buf + DNSCRYPT_QUERY_BOX_OFFSET,
299 len - DNSCRYPT_QUERY_BOX_OFFSET, nonce, nmkey) != 0) {
300 return -1;
301 }
302 }
303
304 len -= DNSCRYPT_QUERY_HEADER_SIZE;
305 while (len > 0 && buf[--len] == 0);
306 if (buf[len] != 0x80) {
307 return -1;
308 }
309
310 memcpy(client_nonce, nonce, crypto_box_HALF_NONCEBYTES);
311 *lenp = len;
312
313 return 0;
314 }
315
316 void
add_server_nonce(struct context * c,uint8_t * nonce)317 add_server_nonce(struct context *c, uint8_t *nonce)
318 {
319 uint64_t ts;
320 uint64_t tsn;
321 uint32_t suffix;
322 ts = dnscrypt_hrtime();
323 if (ts <= c->nonce_ts_last) {
324 ts = c->nonce_ts_last + 1;
325 }
326 c->nonce_ts_last = ts;
327 tsn = (ts << 10) | (randombytes_random() & 0x3ff);
328 #if (BYTE_ORDER == LITTLE_ENDIAN)
329 tsn =
330 (((uint64_t)htonl((uint32_t)tsn)) << 32) | htonl((uint32_t)(tsn >> 32));
331 #endif
332 memcpy(nonce + crypto_box_HALF_NONCEBYTES, &tsn, 8);
333 suffix = randombytes_random();
334 memcpy(nonce + crypto_box_HALF_NONCEBYTES + 8, &suffix, 4);
335 }
336
337 // 8 bytes: magic header (CERT_MAGIC_HEADER)
338 // 12 bytes: the client's nonce
339 // 12 bytes: server nonce extension
340 // 16 bytes: Poly1305 MAC (crypto_box_MACBYTES)
341
342 #define DNSCRYPT_REPLY_BOX_OFFSET \
343 (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES + crypto_box_HALF_NONCEBYTES)
344
345 int
dnscrypt_server_curve(struct context * c,const dnsccert * cert,uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],uint8_t nmkey[crypto_box_BEFORENMBYTES],uint8_t * const buf,size_t * const lenp,const size_t max_len)346 dnscrypt_server_curve(struct context *c, const dnsccert *cert,
347 uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
348 uint8_t nmkey[crypto_box_BEFORENMBYTES],
349 uint8_t *const buf, size_t * const lenp,
350 const size_t max_len)
351 {
352 uint8_t nonce[crypto_box_NONCEBYTES];
353 uint8_t *boxed;
354 size_t len = *lenp;
355
356 memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
357 memcpy(nonce + crypto_box_HALF_NONCEBYTES, client_nonce,
358 crypto_box_HALF_NONCEBYTES);
359
360 boxed = buf + DNSCRYPT_REPLY_BOX_OFFSET;
361 memmove(boxed + crypto_box_MACBYTES, buf, len);
362 len =
363 dnscrypt_pad(boxed + crypto_box_MACBYTES, len,
364 max_len - DNSCRYPT_REPLY_HEADER_SIZE, nonce,
365 c->keypairs[0].crypt_secretkey);
366 // add server nonce extension
367 add_server_nonce(c, nonce);
368
369 if (XCHACHA20_CERT(cert)) {
370 #ifdef HAVE_CRYPTO_BOX_CURVE25519XCHACHA20POLY1305_OPEN_EASY
371 if (crypto_box_curve25519xchacha20poly1305_easy_afternm
372 (boxed, boxed + crypto_box_MACBYTES, len, nonce, nmkey) != 0) {
373 return -1;
374 }
375 #endif
376 } else {
377 if (crypto_box_easy_afternm(boxed, boxed + crypto_box_MACBYTES,
378 len, nonce, nmkey) != 0) {
379 return -1;
380 }
381 }
382
383 memcpy(buf, DNSCRYPT_MAGIC_RESPONSE, DNSCRYPT_MAGIC_HEADER_LEN);
384 memcpy(buf + DNSCRYPT_MAGIC_HEADER_LEN, nonce, crypto_box_NONCEBYTES);
385 *lenp = len + DNSCRYPT_REPLY_HEADER_SIZE;
386 return 0;
387 }
388
389 /**
390 * Return 0 if served.
391 */
392 int
dnscrypt_self_serve_cert_file(struct context * c,struct dns_header * header,size_t * dns_query_len,size_t max_len)393 dnscrypt_self_serve_cert_file(struct context *c, struct dns_header *header,
394 size_t *dns_query_len, size_t max_len)
395 {
396 unsigned char *p;
397 unsigned char *ansp;
398 int qtype;
399 unsigned int nameoffset;
400 p = (unsigned char *)(header + 1);
401 int anscount = 0;
402
403 if (ntohs(header->qdcount) != 1) {
404 return -1;
405 }
406 /* determine end of questions section (we put answers there) */
407 if (!(ansp = skip_questions(header, *dns_query_len))) {
408 return -2;
409 }
410
411 /* save pointer to name for copying into answers */
412 nameoffset = p - (unsigned char *)header;
413
414 if (!extract_name(header, *dns_query_len, &p, c->namebuff, 1, 4)) {
415 return -3;
416 }
417 GETSHORT(qtype, p);
418 logger(LOG_DEBUG, "qtype: %d, c->provider_name: %s, c->namebuff: %s", qtype, c->provider_name, c->namebuff);
419 if (qtype == T_TXT && strcasecmp(c->provider_name, c->namebuff) == 0) {
420 // reply with signed certificate
421 const size_t size = 1 + sizeof(struct SignedCert);
422 static uint8_t **txt;
423
424 // Allocate static buffers containing the certificates.
425 // This is only called once the first time a TXT request is made.
426 if(!txt) {
427 txt = calloc(c->signed_certs_count, sizeof(uint8_t *));
428 if (!txt) {
429 return -4;
430 }
431 for (int i=0; i < c->signed_certs_count; i++) {
432 *(txt + i) = malloc(size);
433 if (!*(txt + i))
434 return -5;
435 **(txt + i) = sizeof(struct SignedCert);
436 memcpy(*(txt + i) + 1, c->signed_certs + i, sizeof(struct SignedCert));
437 }
438 }
439
440 for (int i=0; i < c->signed_certs_count; i++) {
441 if (add_resource_record
442 (header, nameoffset, max_len, &ansp, 0, NULL, T_TXT, C_IN, "t", size,
443 *(txt + i))) {
444 anscount++;
445 } else {
446 return -6;
447 }
448 }
449 /* done all questions, set up header and return length of result */
450 /* clear authoritative and truncated flags, set QR flag */
451 header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
452 /* set RA flag */
453 header->hb4 |= HB4_RA;
454
455 SET_RCODE(header, NOERROR);
456 header->ancount = htons(anscount);
457 header->nscount = htons(0);
458 header->arcount = htons(0);
459 *dns_query_len = ansp - (unsigned char *)header;
460
461 return 0;
462 }
463
464 return -7;
465 }
466
467