djbdnscurve6 45
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 "response.h"
14
15#define TXT_LABLEN 255
16
17void curve_nonce(uint8 nonce[12])
18{
19 int i; // the choice of static x was bad
20
21 for (i = 0; i < 12; i++)
22 nonce[i] = dns_random(256);
23}
24
25/* DNSCurve stream query messages have a fixed layout:
26
27 1. Dedicated header: 8 byte
28 2. Encoded client pubkey: 32 byte
29 3. Client nonce: 12 byte
30 4. Cryptobox with query: variable size
31*/
32
33int dns_curve_query(const char *buf,const unsigned int len,const unsigned int pos)
34{
35 if (len < 68) return 0;
36 if (byte_diff(buf + pos,8,"Q6fnvWj8")) return 0;
37
38 return (pos + 8);
39}
40
41int dns_curve_pubkey(uint8 *pubkey,const char *buf,const unsigned int pos)
42{
43 byte_copy(pubkey,32,buf + pos);
44 return (pos + 32);
45}
46
47int dns_curve_nonce(uint8 *nonce,const char *buf,const unsigned int pos)
48{
49 byte_copy(nonce,12,buf + pos);
50 return (pos + 12);
51}
52
53int dns_curve_cryptobox(uint8 *cryptobox,const char *buf,const unsigned int len,const unsigned int pos)
54{
55 if (pos >= len) return 0;
56 byte_copy(cryptobox,len - pos,buf + pos);
57 return (len - pos);
58}
59
60/* DNSCurve alternate/txt query messages have a different layout:
61
62 1. Header: 12 byte ('curvetxtq')
63 2. Qname expressed in the DNS label format:
64 a) Client nonce: 12 byte
65 +
66 b) Cryptobox: variable sized
67 -> Base32 encoded
68 -> broken down in 'n' fixed sized 50 byte labels (except smaller final)
69 c) New label: Meta information: 4 byte ('36xla')
70 d) appended with Base32 encoded client pubkey: 50 byte => 54 byte
71 3. Zone (or 0)
72
73 Note: Case is irrelevant.
74*/
75
76char curvetxtq[10] = { '\x00','\x00','\x00','\x01','\x00','\x00','\x00','\x00','\x00','\x00' };
77
78int dns_curve_txtquery(const char *buf,const unsigned int len,const unsigned int pos)
79{
80 int i;
81
82 if (buf[pos] & 0xfe) return 0; // auth/trunc set
83
84 if (!byte_equal(buf + pos,10,curvetxtq)) return 0;
85 if (!byte_equal(buf + len - 4,2,DNS_T_TXT)) return 0;
86
87 // Look for pubkey
88
89 for (i = 12; i < len; i++) {
90 if (*(buf + i) == 54 && (*(buf + i + 1) & ~0x20) == 'X' &&
91 *(buf + i + 2) == '1' && (*(buf + i + 3) & ~0x20) == 'A') return i;
92 }
93
94 return 0;
95}
96
97/* The decoded client nonce + cryptobox (query) ; returns to following box */
98
99static unsigned char *qname;
100
101int dns_curve_txtqname(uint8 *base32box,const char *buf,const unsigned int len)
102{
103 uint8 box[MAXMSGSIZE];
104 unsigned int boxlen = 0;
105 unsigned int lablen;
106 int i;
107
108 i = dns_packet_getname(buf,len,12,&qname);
109 if (!i) return 0;
110
111 i = 0;
112 for (;;) {
113 lablen = *(qname + i);
114 if (lablen == 54) break; // final label with pubkey
115 else if (lablen > 50) return 0;
116 else if (lablen == 0) return 0;
117
118 byte_copy(box + boxlen,lablen,qname + i + 1);
119 boxlen += lablen;
120 i += lablen + 1;
121 }
122
123 return base32_decode(base32box,box,boxlen,0);
124}
125
126/* The decoded client pubkey; returns the position of zone in buffer */
127
128int dns_curve_txtpubkey(uint8 *pubkey,const char *buf,const unsigned int pos)
129{
130 if (base32_decode(pubkey,buf + pos,51,1) != 32) return 0;
131
132 return (pos + 52); // beginning of *zone
133}
134
135int dns_curve_txtnonce(uint8 *nonce,const uint8 *base32box)
136{
137 byte_copy(nonce,12,base32box);
138 return 12;
139}
140
141/* DNSCurve streamline response:
142
143 1. Crafted header: 8 byte (R6 fn vW J8)
144 2. Client nonce: 12 byte
145 3. Server nonce: 12 byte
146 4. Cryptobox with response: variable sized
147*/
148
149static uint8 cryptobox[4099];
150static uint8 fullnonce[24];
151
152int response_stream(const uint8 *secret,const uint8 *nonce)
153{
154 unsigned int boxlen = response_len;
155
156 byte_copy(fullnonce,12,nonce);
157 curve_nonce(fullnonce + 12);
158 byte_zero(cryptobox,32);
159 byte_copy(cryptobox + 32,response_len,response);
160 if (crypto_box_afternm(cryptobox,cryptobox,response_len + 32,fullnonce,secret)) return 0;
161
162 response_len = 0;
163 if (!response_addbytes("R6fnvWJ8",8)) return 0;
164 if (!response_addbytes(fullnonce,24)) return 0;
165 if (!response_addbytes(cryptobox + 16,boxlen + 16)) return 0;
166
167 return 1;
168}
169
170char curvetxtr[14] = { '\x00','\x10', // question type: TXT
171 '\x00','\x01', // question class: IN
172 '\xc0','\x0c', // pointer to qname in question part
173 '\x00','\x10', // response RR type: TXT
174 '\x00','\x01', // response RR class: IN
175 '\x00','\x00',
176 '\x00','\x00' }; // response RR TTL: 0
177
178char txtheader[10] = { '\x84','\x00',
179 '\x00','\x01',
180 '\x00','\x01',
181 '\x00','\x00',
182 '\x00','\x00' };
183
184/* Alt TXT response format:
185
186 1. Header: 12 byte
187 2. *Name from query (Qname)
188 3. Meta information: 14 byte + 2 byte RDLEN
189 4. Server nonce: 12
190 5. Cryptobox with response: variable size
191*/
192
193/* Original query needs to be included */
194
195int response_alttxt(const uint8 *secret,const uint8 *nonce,const char id[2],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(fullnonce,12,nonce);
204 curve_nonce(fullnonce + 12);
205
206 byte_zero(cryptobox,32);
207 byte_copy(cryptobox + 32,response_len,response);
208
209 if (crypto_box_afternm(cryptobox,cryptobox,response_len + 32,fullnonce,secret)) return 0;
210 byte_copy(cryptobox + 4,12,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) / TXT_LABLEN);
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 = TXT_LABLEN;
230 if (boxlen < TXT_LABLEN) 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:319
char buf[MSGSIZE]
Definition: axfrdns.c:318
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:78
int dns_curve_txtpubkey(uint8 *pubkey, const char *buf, const unsigned int pos)
Definition: curve.c:128
#define TXT_LABLEN
Definition: curve.c:15
int dns_curve_cryptobox(uint8 *cryptobox, const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:53
int dns_curve_pubkey(uint8 *pubkey, const char *buf, const unsigned int pos)
Definition: curve.c:41
int dns_curve_query(const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:33
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:195
char curvetxtr[14]
Definition: curve.c:170
int dns_curve_nonce(uint8 *nonce, const char *buf, const unsigned int pos)
Definition: curve.c:47
char curvetxtq[10]
Definition: curve.c:76
int dns_curve_txtqname(uint8 *base32box, const char *buf, const unsigned int len)
Definition: curve.c:101
char txtheader[10]
Definition: curve.c:178
void curve_nonce(uint8 nonce[12])
Definition: curve.c:17
int dns_curve_txtnonce(uint8 *nonce, const uint8 *base32box)
Definition: curve.c:135
int response_stream(const uint8 *secret, const uint8 *nonce)
Definition: curve.c:152
#define crypto_box_afternm
Definition: curve.h:14
#define DNS_T_TXT
Definition: dns.h:63
#define MAXMSGSIZE
Definition: dns.h:40
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:56
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:56