Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnscrypt / src / proxy / dnscrypt.c
blob1055ed95ed9741ab126d7e33ba9fd39e394ab8cd
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 "salsa20_random.h"
18 #include "randombytes.h"
19 #include "utils.h"
21 size_t
22 dnscrypt_response_header_size(void)
24 return sizeof DNSCRYPT_MAGIC_RESPONSE - 1U
25 + crypto_box_NONCEBYTES + crypto_box_MACBYTES;
28 size_t
29 dnscrypt_query_header_size(void)
31 return DNSCRYPT_MAGIC_QUERY_LEN
32 + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES
33 + crypto_box_MACBYTES;
36 static int
37 dnscrypt_memcmp(const void * const b1_, const void * const b2_,
38 const size_t size)
40 const uint8_t *b1 = b1_;
41 const uint8_t *b2 = b2_;
42 size_t i = (size_t) 0U;
43 uint8_t d = (uint8_t) 0U;
45 assert(size > (size_t) 0U);
46 do {
47 d |= b1[i] ^ b2[i];
48 } while (++i < size);
50 return (int) d;
53 int
54 dnscrypt_cmp_client_nonce(const uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
55 const uint8_t * const buf, const size_t len)
57 const size_t client_nonce_offset = sizeof DNSCRYPT_MAGIC_RESPONSE - 1U;
59 if (len < client_nonce_offset + crypto_box_HALF_NONCEBYTES ||
60 dnscrypt_memcmp(client_nonce, buf + client_nonce_offset,
61 crypto_box_HALF_NONCEBYTES) != 0) {
62 return -1;
64 return 0;
67 size_t
68 dnscrypt_pad(uint8_t *buf, const size_t len, const size_t max_len)
70 uint8_t *buf_padding_area = buf + len;
71 size_t padded_len, padding_len;
73 if (max_len < len + DNSCRYPT_MIN_PAD_LEN) {
74 return len;
76 padded_len = len + DNSCRYPT_MIN_PAD_LEN + salsa20_random_uniform
77 ((uint32_t) (max_len - len - DNSCRYPT_MIN_PAD_LEN + 1U));
78 padded_len += DNSCRYPT_BLOCK_SIZE - padded_len % DNSCRYPT_BLOCK_SIZE;
79 if (padded_len > max_len) {
80 padded_len = max_len;
82 assert(padded_len >= len);
83 padding_len = padded_len - len;
84 memset(buf_padding_area, 0, padding_len);
85 *buf_padding_area = 0x80;
86 assert(max_len >= padded_len);
88 return padded_len;
91 void
92 randombytes(unsigned char * const buf, const unsigned long long buf_len)
94 assert(buf_len <= SIZE_MAX);
95 salsa20_random_buf(buf, buf_len);
98 void
99 dnscrypt_key_to_fingerprint(char fingerprint[80U], const uint8_t * const key)
101 const size_t fingerprint_size = 80U;
102 size_t fingerprint_pos = (size_t) 0U;
103 size_t key_pos = (size_t) 0U;
105 COMPILER_ASSERT(crypto_box_PUBLICKEYBYTES == 32U);
106 COMPILER_ASSERT(crypto_box_SECRETKEYBYTES == 32U);
107 for (;;) {
108 assert(fingerprint_size > fingerprint_pos);
109 evutil_snprintf(&fingerprint[fingerprint_pos],
110 fingerprint_size - fingerprint_pos, "%02X%02X",
111 key[key_pos], key[key_pos + 1U]);
112 key_pos += 2U;
113 if (key_pos >= crypto_box_PUBLICKEYBYTES) {
114 break;
116 fingerprint[fingerprint_pos + 4U] = ':';
117 fingerprint_pos += 5U;
121 static int
122 _dnscrypt_parse_char(uint8_t key[crypto_box_PUBLICKEYBYTES],
123 size_t * const key_pos_p, int * const state_p,
124 const int c, uint8_t * const val_p)
126 uint8_t c_val;
128 switch (*state_p) {
129 case 0:
130 case 1:
131 if (isspace(c) || (c == ':' && *state_p == 0)) {
132 break;
134 if (c == '#') {
135 *state_p = 2;
136 break;
138 if (!isxdigit(c)) {
139 return -1;
141 c_val = (uint8_t) ((c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10);
142 assert(c_val < 16U);
143 if (*state_p == 0) {
144 *val_p = c_val * 16U;
145 *state_p = 1;
146 } else {
147 *val_p |= c_val;
148 key[(*key_pos_p)++] = *val_p;
149 if (*key_pos_p >= crypto_box_PUBLICKEYBYTES) {
150 return 0;
152 *state_p = 0;
154 break;
155 case 2:
156 if (c == '\n') {
157 *state_p = 0;
160 return 1;
164 dnscrypt_fingerprint_to_key(const char * const fingerprint,
165 uint8_t key[crypto_box_PUBLICKEYBYTES])
167 const char *p = fingerprint;
168 size_t key_pos = (size_t) 0U;
169 int c;
170 int ret;
171 int state = 0;
172 uint8_t val = 0U;
174 if (fingerprint == NULL) {
175 return -1;
177 while ((c = tolower((int) (unsigned char) *p)) != 0) {
178 ret = _dnscrypt_parse_char(key, &key_pos, &state, c, &val);
179 if (ret <= 0) {
180 return ret;
182 p++;
184 return -1;