djbdnscurve6 53
djbdnscurve6
Loading...
Searching...
No Matches
curve.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <string.h>
3#include <unistd.h>
4#include "uint_t.h"
5#include "curve.h"
6#include "logmsg.h"
7#include "open.h"
8#include "taia.h"
9#include "byte.h"
10#include "fmt.h"
11#include "dns.h"
12#include "base32.h"
13#include "query.h"
14#include "response.h"
15
16void curve_nonce(uint8 nonce[12])
17{
18 int i; // the choice of static x was bad
19
20 for (i = 0; i < 12; i++)
21 nonce[i] = dns_random(256);
22}
23
24/* DNSCurve stream query messages have a fixed layout:
25
26 1. Dedicated header: 8 byte
27 2. Encoded client pubkey: 32 byte
28 3. Client nonce: 12 byte
29 4. Cryptobox with query: variable size
30*/
31
32int dns_curve_query(const char *buf,const unsigned int len,const unsigned int pos)
33{
34 if (len < 68) return 0;
35 if (byte_diff(buf + pos,8,"Q6fnvWj8")) return 0;
36
37 return (pos + 8);
38}
39
40int dns_curve_pubkey(uint8 *pubkey,const char *buf,const unsigned int pos)
41{
42 byte_copy((char *)pubkey,KEY_LEN,buf + pos);
43 return (pos + KEY_LEN);
44}
45
46int dns_curve_nonce(uint8 *nonce,const char *buf,const unsigned int pos)
47{
48 byte_copy((char *)nonce,12,buf + pos);
49 return (pos + 12);
50}
51
52int dns_curve_cryptobox(uint8 *cryptobox,const char *buf,const unsigned int len,const unsigned int pos)
53{
54 if (pos >= len) return 0;
55 byte_copy((char *)cryptobox,len - pos,buf + pos);
56 return (len - pos);
57}
58
59/* DNSCurve alternate/txt query messages have a different layout:
60
61 1. Header: 12 byte ('curvetxtq')
62 2. Qname expressed in the DNS label format:
63 a) Client nonce: 12 byte
64 +
65 b) Cryptobox: variable sized
66 -> Base32 encoded
67 -> broken down in 'n' fixed sized 50 byte labels (except smaller final)
68 c) New label: Meta information: 4 byte ('36xla')
69 d) appended with Base32 encoded client pubkey: 50 byte => 54 byte
70 3. Zone (or 0)
71
72 Note: Case is irrelevant.
73*/
74
75char curvetxtq[10] = { '\x00','\x00','\x00','\x01','\x00','\x00','\x00','\x00','\x00','\x00' };
76
77int dns_curve_txtquery(const char *buf,const unsigned int len,const unsigned int pos)
78{
79 int i;
80
81 if (buf[pos] & 0xfe) return 0; // auth/trunc set
82
83 if (!byte_equal(buf + pos,10,curvetxtq)) return 0;
84 if (!byte_equal(buf + len - 4,2,DNS_T_TXT)) return 0;
85
86 // Look for pubkey
87
88 for (i = 12; i < len; i++) {
89 if (*(buf + i) == 54 && (*(buf + i + 1) & ~0x20) == 'X' &&
90 *(buf + i + 2) == '1' && (*(buf + i + 3) & ~0x20) == 'A') return i;
91 }
92
93 return 0;
94}
95
96/* The decoded client nonce + cryptobox (query) ; returns to following box */
97
98static unsigned char *qname;
99
100int dns_curve_txtqname(uint8 *base32box,const char *buf,const unsigned int len)
101{
102 uint8 box[MAXMSGSIZE];
103 unsigned int boxlen = 0;
104 unsigned int lablen;
105 int i;
106
107 i = dns_packet_getname(buf,len,12,(char **)&qname);
108 if (!i) return 0;
109
110 i = 0;
111 for (;;) {
112 lablen = *(qname + i);
113 if (lablen == 54) break; // final label with pubkey
114 else if (lablen > 50) return 0;
115 else if (lablen == 0) return 0;
116
117 byte_copy((char *)box + boxlen,lablen,qname + i + 1);
118 boxlen += lablen;
119 i += lablen + 1;
120 }
121
122 return base32_decode(base32box,box,boxlen,0);
123}
124
125/* The decoded client pubkey; returns the position of zone in buffer */
126
127int dns_curve_txtpubkey(uint8 *pubkey,const char *buf,const unsigned int pos)
128{
129 if (base32_decode(pubkey,buf + pos,51,1) != 32) return 0;
130
131 return (pos + 52); // beginning of *zone
132}
133
134int dns_curve_txtnonce(uint8 *nonce,const uint8 *base32box)
135{
136 byte_copy((char *)nonce,12,(char *)base32box);
137 return 12;
138}
139
140/* DNSCurve streamline response:
141
142 1. Crafted header: 8 byte (R6 fn vW J8)
143 2. Client nonce: 12 byte
144 3. Server nonce: 12 byte
145 4. Cryptobox with response: variable sized
146*/
147
148static uint8 cryptobox[4099];
149static uint8 fullnonce[24];
150
151int response_stream(const uint8 *secret,const uint8 *nonce)
152{
153 unsigned int boxlen = response_len;
154
155 byte_copy((char *)fullnonce,12,(char *)nonce);
156 curve_nonce(fullnonce + 12);
157 byte_zero((char *)cryptobox,KEY_LEN);
158 byte_copy((char *)cryptobox + KEY_LEN,response_len,response);
159 if (crypto_box_afternm(cryptobox,cryptobox,response_len + KEY_LEN,fullnonce,secret)) return 0;
160
161 response_len = 0;
162 if (!response_addbytes("R6fnvWJ8",8)) return 0;
163 if (!response_addbytes(fullnonce,24)) return 0;
164 if (!response_addbytes(cryptobox + 16,boxlen + 16)) return 0;
165
166 return 1;
167}
168
169char curvetxtr[14] = { '\x00','\x10', // question type: TXT
170 '\x00','\x01', // question class: IN
171 '\xc0','\x0c', // pointer to qname in question part
172 '\x00','\x10', // response RR type: TXT
173 '\x00','\x01', // response RR class: IN
174 '\x00','\x00',
175 '\x00','\x00' }; // response RR TTL: 0
176
177char txtheader[10] = { '\x84','\x00',
178 '\x00','\x01',
179 '\x00','\x01',
180 '\x00','\x00',
181 '\x00','\x00' };
182
183/* Alt TXT response format:
184
185 1. Header: 12 byte
186 2. *Name from query (Qname)
187 3. Meta information: 14 byte + 2 byte RDLEN
188 4. Server nonce: 12
189 5. Cryptobox with response: variable size
190*/
191
192/* Original query needs to be included */
193
194int response_alttxt(const uint8 *secret,const uint8 *nonce,const char id[2],\
195 const unsigned char *query,const unsigned int len,const int rd)
196{
197 unsigned int boxlen = response_len;
198 unsigned int rrdatalen;
199 char rdlen[2];
200 unsigned int last;
201 uint8 lablen;
202
203 byte_copy((char *)fullnonce,12,(char *)nonce);
204 curve_nonce(fullnonce + 12);
205
206 byte_zero((char *)cryptobox,KEY_LEN);
207 byte_copy((char *)cryptobox + KEY_LEN,response_len,(char *)response);
208
209 if (crypto_box_afternm(cryptobox,cryptobox,response_len + KEY_LEN,fullnonce,secret)) return 0;
210 byte_copy((char *)cryptobox + 4,12,(char *)fullnonce + 12);
211 if (rd) byte_copy(txtheader,1,"\x85");
212
213 response_len = 0;
214 if (!response_addbytes(id,2)) return 0; // transction id from outer packet
215 if (!response_addbytes(txtheader,10)) return 0; // new header
216 if (!response_addbytes(query,len)) return 0; // org Qname ? EDNS0 !!
217 if (!response_addbytes(curvetxtr,14)) return 0; // Q+A section
218
219 boxlen += (16 + 12); // offset + server nonce
220 rrdatalen = boxlen + ((boxlen + 254) / FQDN_LEN);
221 uint16_pack_big(rdlen,rrdatalen);
222 if (!response_addbytes(rdlen,2)) return 0; // length of answer
223
224/* Start the split-up of RDATA in 255 byte parts (the server nonce + the crypto box):
225 This fits, due to fact we checked this when RR data length was calculated: (MD) */
226
227 last = 4;
228 while (boxlen) {
229 lablen = FQDN_LEN;
230 if (boxlen < FQDN_LEN) lablen = boxlen;
231 uint16_pack_big(rdlen,lablen);
232 if (!response_addbytes(rdlen + 1,1)) return 0;
233 if (!response_addbytes(cryptobox + last,lablen)) return 0;
234 last += lablen;
235 boxlen -= lablen;
236 }
237
238 return 1;
239}
uint16 len
Definition: axfrdns.c:322
char buf[MSGSIZE]
Definition: axfrdns.c:321
unsigned int base32_decode(uint8 *out, const char *in, unsigned int len, int mode)
Definition: base32.c:46
int dns_curve_txtquery(const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:77
int dns_curve_txtpubkey(uint8 *pubkey, const char *buf, const unsigned int pos)
Definition: curve.c:127
int dns_curve_cryptobox(uint8 *cryptobox, const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:52
int dns_curve_pubkey(uint8 *pubkey, const char *buf, const unsigned int pos)
Definition: curve.c:40
int dns_curve_query(const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:32
int response_alttxt(const uint8 *secret, const uint8 *nonce, const char id[2], const unsigned char *query, const unsigned int len, const int rd)
Definition: curve.c:194
char curvetxtr[14]
Definition: curve.c:169
int dns_curve_nonce(uint8 *nonce, const char *buf, const unsigned int pos)
Definition: curve.c:46
char curvetxtq[10]
Definition: curve.c:75
int dns_curve_txtqname(uint8 *base32box, const char *buf, const unsigned int len)
Definition: curve.c:100
char txtheader[10]
Definition: curve.c:177
void curve_nonce(uint8 nonce[12])
Definition: curve.c:16
int dns_curve_txtnonce(uint8 *nonce, const uint8 *base32box)
Definition: curve.c:134
int response_stream(const uint8 *secret, const uint8 *nonce)
Definition: curve.c:151
#define crypto_box_afternm
Definition: curve.h:14
#define KEY_LEN
#define DNS_T_TXT
Definition: dns.h:72
#define MAXMSGSIZE
Definition: dns.h:49
#define FQDN_LEN
Definition: dns.h:57
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
Definition: dns_packet.c:35
unsigned int dns_random(unsigned int n)
Definition: dns_random.c:55
int response_addbytes(const char *, unsigned int)
Definition: response.c:17
char response[]
Definition: response.c:6
unsigned int response_len
Definition: response.c:7
Definition: query.h:60