summaryrefslogtreecommitdiff
path: root/toxdns/toxdns.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-06-14 09:54:40 -0400
committerirungentoo <irungentoo@gmail.com>2014-06-14 09:54:40 -0400
commit9c11c15385ff44609ac8438378a5bcb05d47c572 (patch)
treebcf8664079689ce23c810499ecc4d74a5951c652 /toxdns/toxdns.c
parent0b4640a508d6ceeb8983aa819cd70f01ceeec481 (diff)
Added toxdns.
toxdns currently contains functions to make it easier for clients to create tox dns3 requests and handle tox dns3 responses: an encrypted way of querying Tox DNS id servers for Tox ids from usernames.
Diffstat (limited to 'toxdns/toxdns.c')
-rw-r--r--toxdns/toxdns.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/toxdns/toxdns.c b/toxdns/toxdns.c
new file mode 100644
index 00000000..20a4486c
--- /dev/null
+++ b/toxdns/toxdns.c
@@ -0,0 +1,224 @@
1/* toxdns.c
2 *
3 * Tox secure username DNS toxid resolving functions.
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include "../toxcore/Messenger.h"
29
30static const char base32[32] = {"abcdefghijklmnopqrstuvwxyz012345"};
31
32#define _encode(a, b, c) \
33{ \
34uint8_t i = 0; \
35 while(i != c) { \
36 *a++ = base32[((b[0] >> bits) | (b[1] << (8 - bits))) & 0x1F]; \
37 bits += 5; \
38 if(bits >= 8) { \
39 bits -= 8; \
40 b++; \
41 i++; \
42 } \
43 } \
44} \
45
46typedef struct {
47 uint8_t temp_pk[crypto_box_PUBLICKEYBYTES];
48 uint8_t temp_sk[crypto_box_SECRETKEYBYTES];
49 uint8_t server_public_key[crypto_box_PUBLICKEYBYTES];
50 uint8_t shared_key[crypto_box_KEYBYTES];
51 uint32_t nonce;
52 uint32_t nonce_start;
53} DNS_Object;
54
55static void dns_new_temp_keys(DNS_Object *d)
56{
57 d->nonce = d->nonce_start = random_int();
58 crypto_box_keypair(d->temp_pk, d->temp_sk);
59 encrypt_precompute(d->server_public_key, d->temp_sk, d->shared_key);
60}
61
62/* Create a new tox_dns3 object for server with server_public_key.
63 *
64 * return Null on failure.
65 * return pointer object on success.
66 */
67void *tox_dns3_new(uint8_t *server_public_key)
68{
69 DNS_Object *d = malloc(sizeof(DNS_Object));
70
71 if (d == NULL)
72 return NULL;
73
74 memcpy(d->server_public_key, server_public_key, crypto_box_PUBLICKEYBYTES);
75 dns_new_temp_keys(d);
76 return d;
77}
78
79/* Destroy the tox dns3 object.
80 */
81void tox_dns3_kill(void *dns3_object)
82{
83 memset(dns3_object, 0, sizeof(DNS_Object));
84 free(dns3_object);
85}
86
87/* Generate a dns3 string of string_max_len used to query the dns server reffered to by to
88 * dns3_object for a tox id registered to user with name of name_len.
89 *
90 * This is what the string returned looks like:
91 * 4haaaaipr1o3mz0bxweox541airydbovqlbju51mb4p0ebxq.rlqdj4kkisbep2ks3fj2nvtmk4daduqiueabmexqva1jc
92 *
93 * returns length of string on sucess.
94 * returns -1 on failure.
95 */
96int tox_generate_dns3_string(void *dns3_object, uint8_t *string, uint16_t string_max_len, uint8_t *name,
97 uint8_t name_len)
98{
99#define DOT_INTERVAL (6 * 5)
100 int base = (sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + name_len + crypto_box_MACBYTES);
101 int end_len = ((base * 8) / 5) + (base / DOT_INTERVAL) + !!(base % 5);
102
103 if (end_len > string_max_len)
104 return -1;
105
106 DNS_Object *d = dns3_object;
107 uint8_t buffer[1024];
108 uint8_t nonce[crypto_box_NONCEBYTES] = {0};
109 memcpy(nonce, &d->nonce, sizeof(uint32_t));
110 memcpy(buffer, &d->nonce, sizeof(uint32_t));
111 memcpy(buffer + sizeof(uint32_t), d->temp_pk, crypto_box_PUBLICKEYBYTES);
112 int len = encrypt_data_symmetric(d->shared_key, nonce, name, name_len,
113 buffer + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES);
114
115 if (len == -1)
116 return -1;
117
118 int total_len = len + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES;
119 uint8_t *buff = buffer, *old_str = string;
120 buffer[total_len] = 0;
121 uint8_t bits = 0;
122 int i;
123
124 for (i = 0; i < (total_len / DOT_INTERVAL); ++i) {
125 _encode(string, buff, DOT_INTERVAL);
126 *string = '.';
127 ++string;
128 }
129
130 _encode(string, buff, total_len % DOT_INTERVAL);
131#undef DOT_INTERVAL
132 ++d->nonce;
133
134 if (d->nonce == d->nonce_start) {
135 dns_new_temp_keys(d);
136 }
137
138 if (end_len != string - old_str) {
139 printf("tox_generate_dns3_string Fail\n");
140 return -1;
141 }
142
143 return string - old_str;
144}
145
146
147static int decode(uint8_t *dest, uint8_t *src)
148{
149 uint8_t *p = src, *op = dest, bits = 0;
150 *op = 0;
151
152 while (*p) {
153 uint8_t ch = *p++;
154
155 switch (ch) {
156 case 'A' ... 'Z': {
157 ch = ch - 'A';
158 break;
159 }
160
161 case 'a' ... 'z': {
162 ch = ch - 'a';
163 break;
164 }
165
166 case '0' ... '5': {
167 ch = ch - '0' + 26;
168 break;
169 }
170
171 default: {
172 return - 1;
173 }
174 }
175
176 *op |= (ch << bits);
177 bits += 5;
178
179 if (bits >= 8) {
180 bits -= 8;
181 ++op;
182 *op = (ch >> (5 - bits));
183 }
184 }
185
186 return op - dest;
187}
188
189/* Decode and decrypt the id_record returned of length id_record_len into
190 * tox_id (needs to be at least TOX_FRIEND_ADDRESS_SIZE).
191 *
192 * the id_record passed to this function should look somewhat like this:
193 * 4haaaa2vgcxuycbuctvauik3plsv3d3aadv4zfjfhi3thaizwxinelrvigchv0ah3qjcsx5qhmaksb2lv2hm5cwbtx0yp
194 *
195 * returns -1 on failure.
196 * returns 0 on success.
197 *
198 */
199int tox_decrypt_dns3_TXT(void *dns3_object, uint8_t *tox_id, uint8_t *id_record, uint32_t id_record_len)
200{
201 DNS_Object *d = dns3_object;
202
203 if (id_record_len != 93)
204 return -1;
205
206 /*if (id_record_len > 255 || id_record_len <= (sizeof(uint32_t) + crypto_box_MACBYTES))
207 return -1;*/
208
209 uint8_t data[id_record_len];
210 int length = decode(data, id_record);
211
212 if (length == -1)
213 return -1;
214
215 uint8_t nonce[crypto_box_NONCEBYTES] = {0};
216 memcpy(nonce, data, sizeof(uint32_t));
217 nonce[sizeof(uint32_t)] = 1;
218 int len = decrypt_data_symmetric(d->shared_key, nonce, data + sizeof(uint32_t), length - sizeof(uint32_t), tox_id);
219
220 if (len != FRIEND_ADDRESS_SIZE)
221 return -1;
222
223 return 0;
224} \ No newline at end of file