dnscrypto-proxy: Update to release 1.3.0
[tomato.git] / release / src / router / dnscrypt / src / proxy / dnscrypt.c
blob5df99b2f786e49192bf7d2d0b738b305946c7d7b
2 #include <config.h>
3 #include <sys/types.h>
5 #include <assert.h>
6 #include <ctype.h>
7 #include <errno.h>
8 #include <limits.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include <event2/util.h>
16 #include "dnscrypt.h"
17 #include "sodium.h"
18 #include "utils.h"
20 size_t
21 dnscrypt_response_header_size(void)
23 return sizeof DNSCRYPT_MAGIC_RESPONSE - 1U
24 + crypto_box_NONCEBYTES + crypto_box_MACBYTES;
27 size_t
28 dnscrypt_query_header_size(void)
30 return DNSCRYPT_MAGIC_QUERY_LEN
31 + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES
32 + crypto_box_MACBYTES;
35 int
36 dnscrypt_cmp_client_nonce(const uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
37 const uint8_t * const buf, const size_t len)
39 const size_t client_nonce_offset = sizeof DNSCRYPT_MAGIC_RESPONSE - 1U;
41 if (len < client_nonce_offset + crypto_box_HALF_NONCEBYTES ||
42 sodium_memcmp(client_nonce, buf + client_nonce_offset,
43 crypto_box_HALF_NONCEBYTES) != 0) {
44 return -1;
46 return 0;
49 size_t
50 dnscrypt_pad(uint8_t *buf, const size_t len, const size_t max_len)
52 uint8_t *buf_padding_area = buf + len;
53 size_t padded_len, padding_len;
55 if (max_len < len + DNSCRYPT_MIN_PAD_LEN) {
56 return len;
58 padded_len = len + DNSCRYPT_MIN_PAD_LEN + randombytes_uniform
59 ((uint32_t) (max_len - len - DNSCRYPT_MIN_PAD_LEN + 1U));
60 padded_len += DNSCRYPT_BLOCK_SIZE - padded_len % DNSCRYPT_BLOCK_SIZE;
61 if (padded_len > max_len) {
62 padded_len = max_len;
64 assert(padded_len >= len);
65 padding_len = padded_len - len;
66 memset(buf_padding_area, 0, padding_len);
67 *buf_padding_area = 0x80;
68 assert(max_len >= padded_len);
70 return padded_len;
73 void
74 dnscrypt_key_to_fingerprint(char fingerprint[80U], const uint8_t * const key)
76 const size_t fingerprint_size = 80U;
77 size_t fingerprint_pos = (size_t) 0U;
78 size_t key_pos = (size_t) 0U;
80 COMPILER_ASSERT(crypto_box_PUBLICKEYBYTES == 32U);
81 COMPILER_ASSERT(crypto_box_SECRETKEYBYTES == 32U);
82 for (;;) {
83 assert(fingerprint_size > fingerprint_pos);
84 evutil_snprintf(&fingerprint[fingerprint_pos],
85 fingerprint_size - fingerprint_pos, "%02X%02X",
86 key[key_pos], key[key_pos + 1U]);
87 key_pos += 2U;
88 if (key_pos >= crypto_box_PUBLICKEYBYTES) {
89 break;
91 fingerprint[fingerprint_pos + 4U] = ':';
92 fingerprint_pos += 5U;
96 static int
97 _dnscrypt_parse_char(uint8_t key[crypto_box_PUBLICKEYBYTES],
98 size_t * const key_pos_p, int * const state_p,
99 const int c, uint8_t * const val_p)
101 uint8_t c_val;
103 switch (*state_p) {
104 case 0:
105 case 1:
106 if (isspace(c) || (c == ':' && *state_p == 0)) {
107 break;
109 if (c == '#') {
110 *state_p = 2;
111 break;
113 if (!isxdigit(c)) {
114 return -1;
116 c_val = (uint8_t) ((c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10);
117 assert(c_val < 16U);
118 if (*state_p == 0) {
119 *val_p = c_val * 16U;
120 *state_p = 1;
121 } else {
122 *val_p |= c_val;
123 key[(*key_pos_p)++] = *val_p;
124 if (*key_pos_p >= crypto_box_PUBLICKEYBYTES) {
125 return 0;
127 *state_p = 0;
129 break;
130 case 2:
131 if (c == '\n') {
132 *state_p = 0;
135 return 1;
139 dnscrypt_fingerprint_to_key(const char * const fingerprint,
140 uint8_t key[crypto_box_PUBLICKEYBYTES])
142 const char *p = fingerprint;
143 size_t key_pos = (size_t) 0U;
144 int c;
145 int ret;
146 int state = 0;
147 uint8_t val = 0U;
149 if (fingerprint == NULL) {
150 return -1;
152 while ((c = tolower((int) (unsigned char) *p)) != 0) {
153 ret = _dnscrypt_parse_char(key, &key_pos, &state, c, &val);
154 if (ret <= 0) {
155 return ret;
157 p++;
159 return -1;