]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dnssec.c
Merge branch 'master' of ssh://central/var/cache/git/dnsmasq
[people/ms/dnsmasq.git] / src / dnssec.c
CommitLineData
8d41ebd8 1/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
0fc2f313 2 and Copyright (c) 2012-2014 Simon Kelley
8d41ebd8
GB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 dated June, 1991, or
7 (at your option) version 3 dated 29 June, 2007.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
e292e93d
GB
17
18#include "dnsmasq.h"
0fc2f313
SK
19
20#ifdef HAVE_DNSSEC
21
86bec2d3
SK
22#include <nettle/rsa.h>
23#include <nettle/dsa.h>
24#include <nettle/nettle-meta.h>
25#include <gmp.h>
c3e0b9b6 26
e292e93d
GB
27#define SERIAL_UNDEF -100
28#define SERIAL_EQ 0
29#define SERIAL_LT -1
30#define SERIAL_GT 1
31
86bec2d3
SK
32/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
33static char *ds_digest_name(int digest)
34{
35 switch (digest)
36 {
37 case 1: return "sha1";
38 case 2: return "sha256";
39 case 3: return "gosthash94";
40 case 4: return "sha384";
41 default: return NULL;
42 }
43}
44
45/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
46static char *algo_digest_name(int algo)
47{
48 switch (algo)
49 {
50 case 1: return "md5";
51 case 3: return "sha1";
52 case 5: return "sha1";
53 case 6: return "sha1";
54 case 7: return "sha1";
55 case 8: return "sha256";
56 case 10: return "sha512";
57 case 12: return "gosthash94";
58 case 13: return "sha256";
59 case 14: return "sha384";
60 default: return NULL;
61 }
62}
63
64/* Find pointer to correct hash function in nettle library */
65static const struct nettle_hash *hash_find(char *name)
66{
67 int i;
68
69 if (!name)
70 return NULL;
71
72 for (i = 0; nettle_hashes[i]; i++)
73 {
74 if (strcmp(nettle_hashes[i]->name, name) == 0)
75 return nettle_hashes[i];
76 }
77
78 return NULL;
79}
80
81/* expand ctx and digest memory allocations if necessary and init hash function */
82static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
83{
84 static void *ctx = NULL;
85 static unsigned char *digest = NULL;
86 static unsigned int ctx_sz = 0;
87 static unsigned int digest_sz = 0;
88
89 void *new;
90
91 if (ctx_sz < hash->context_size)
92 {
93 if (!(new = whine_malloc(hash->context_size)))
94 return 0;
95 if (ctx)
96 free(ctx);
97 ctx = new;
98 ctx_sz = hash->context_size;
99 }
100
101 if (digest_sz < hash->digest_size)
102 {
103 if (!(new = whine_malloc(hash->digest_size)))
104 return 0;
105 if (digest)
106 free(digest);
107 digest = new;
108 digest_sz = hash->digest_size;
109 }
110
111 *ctxp = ctx;
112 *digestp = digest;
113
114 hash->init(ctx);
115
116 return 1;
117}
118
119static int rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
120 unsigned char *digest, int algo)
121{
122 unsigned char *p;
123 size_t exp_len;
124
125 static struct rsa_public_key *key = NULL;
126 static mpz_t sig_mpz;
127
128 if (key == NULL)
129 {
130 if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
131 return 0;
132
133 nettle_rsa_public_key_init(key);
134 mpz_init(sig_mpz);
135 }
136
137 if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
138 return 0;
139
140 key_len--;
141 if ((exp_len = *p++) == 0)
142 {
143 GETSHORT(exp_len, p);
144 key_len -= 2;
145 }
146
147 if (exp_len >= key_len)
148 return 0;
149
150 key->size = key_len - exp_len;
151 mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
152 mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
153
154 mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
155
156 switch (algo)
157 {
158 case 1:
159 return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
160 case 5: case 7:
161 return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
162 case 8:
163 return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
164 case 10:
165 return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
166 }
167
168 return 0;
169}
170
171static int dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
172 unsigned char *digest, int algo)
173{
174 unsigned char *p;
175 unsigned int t;
176
177 static struct dsa_public_key *key = NULL;
178 static struct dsa_signature *sig_struct;
179
180 if (key == NULL)
181 {
182 if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
183 !(key = whine_malloc(sizeof(struct dsa_public_key))))
184 return 0;
185
186 nettle_dsa_public_key_init(key);
187 nettle_dsa_signature_init(sig_struct);
188 }
189
190 if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
191 return 0;
192
193 t = *p++;
194
195 if (key_len < (213 + (t * 24)))
196 return 0;
197
198 mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
199 mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
200 mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
201 mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
202
203 mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
204 mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
205
206 (void)algo;
207
208 return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
209}
210
211static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
212 unsigned char *digest, int algo)
213{
214 switch (algo)
215 {
216 case 1: case 5: case 7: case 8: case 10:
217 return rsa_verify(key_data, key_len, sig, sig_len, digest, algo);
218
219 case 3: case 6:
220 return dsa_verify(key_data, key_len, sig, sig_len, digest, algo);
221 }
222
223 return 0;
224}
225
0fc2f313
SK
226/* Convert from presentation format to wire format, in place.
227 Also map UC -> LC.
228 Note that using extract_name to get presentation format
229 then calling to_wire() removes compression and maps case,
230 thus generating names in canonical form.
231 Calling to_wire followed by from_wire is almost an identity,
232 except that the UC remains mapped to LC.
233*/
234static int to_wire(char *name)
7f0485cf 235{
0fc2f313
SK
236 unsigned char *l, *p, term;
237 int len;
238
239 for (l = (unsigned char*)name; *l != 0; l = p)
240 {
241 for (p = l; *p != '.' && *p != 0; p++)
242 if (*p >= 'A' && *p <= 'Z')
243 *p = *p - 'A' + 'a';
244
245 term = *p;
246
247 if ((len = p - l) != 0)
248 memmove(l+1, l, len);
249 *l = len;
250
251 p++;
252
253 if (term == 0)
254 *p = 0;
255 }
256
257 return l + 1 - (unsigned char *)name;
7f0485cf
GB
258}
259
0fc2f313
SK
260/* Note: no compression allowed in input. */
261static void from_wire(char *name)
13e435eb 262{
0fc2f313
SK
263 unsigned char *l;
264 int len;
13e435eb 265
0fc2f313 266 for (l = (unsigned char *)name; *l != 0; l += len+1)
13e435eb 267 {
0fc2f313
SK
268 len = *l;
269 memmove(l, l+1, len);
270 l[len] = '.';
13e435eb 271 }
7f0485cf 272
0fc2f313 273 *(l-1) = 0;
13e435eb
GB
274}
275
5ada8885
SK
276/* Input in presentation format */
277static int count_labels(char *name)
278{
279 int i;
280
281 if (*name == 0)
282 return 0;
283
284 for (i = 0; *name; name++)
285 if (*name == '.')
286 i++;
287
288 return i+1;
289}
290
5f8e58f4
SK
291/* Implement RFC1982 wrapped compare for 32-bit numbers */
292static int serial_compare_32(unsigned long s1, unsigned long s2)
293{
294 if (s1 == s2)
295 return SERIAL_EQ;
0ca895f5 296
5f8e58f4
SK
297 if ((s1 < s2 && (s2 - s1) < (1UL<<31)) ||
298 (s1 > s2 && (s1 - s2) > (1UL<<31)))
299 return SERIAL_LT;
300 if ((s1 < s2 && (s2 - s1) > (1UL<<31)) ||
301 (s1 > s2 && (s1 - s2) < (1UL<<31)))
302 return SERIAL_GT;
303 return SERIAL_UNDEF;
304}
0852d76b 305
5f8e58f4
SK
306/* Check whether today/now is between date_start and date_end */
307static int check_date_range(unsigned long date_start, unsigned long date_end)
0852d76b 308{
5f8e58f4
SK
309 unsigned long curtime = time(0);
310
311 /* We must explicitly check against wanted values, because of SERIAL_UNDEF */
312 return serial_compare_32(curtime, date_start) == SERIAL_GT
313 && serial_compare_32(curtime, date_end) == SERIAL_LT;
314}
f119ed38 315
5f8e58f4
SK
316static u16 *get_desc(int type)
317{
318 /* List of RRtypes which include domains in the data.
319 0 -> domain
320 integer -> no of plain bytes
321 -1 -> end
322
323 zero is not a valid RRtype, so the final entry is returned for
324 anything which needs no mangling.
325 */
326
327 static u16 rr_desc[] =
328 {
329 T_NS, 0, -1,
330 T_MD, 0, -1,
331 T_MF, 0, -1,
332 T_CNAME, 0, -1,
333 T_SOA, 0, 0, -1,
334 T_MB, 0, -1,
335 T_MG, 0, -1,
336 T_MR, 0, -1,
337 T_PTR, 0, -1,
338 T_MINFO, 0, 0, -1,
339 T_MX, 2, 0, -1,
340 T_RP, 0, 0, -1,
341 T_AFSDB, 2, 0, -1,
342 T_RT, 2, 0, -1,
343 T_SIG, 18, 0, -1,
344 T_PX, 2, 0, 0, -1,
345 T_NXT, 0, -1,
346 T_KX, 2, 0, -1,
347 T_SRV, 6, 0, -1,
348 T_DNAME, 0, -1,
349 T_RRSIG, 18, 0, -1,
350 T_NSEC, 0, -1,
351 0, -1 /* wildcard/catchall */
352 };
353
354 u16 *p = rr_desc;
355
356 while (*p != type && *p != 0)
357 while (*p++ != (u16)-1);
f119ed38 358
5f8e58f4
SK
359 return p+1;
360}
0852d76b 361
5f8e58f4
SK
362/* Return bytes of canonicalised rdata, when the return value is zero, the remaining
363 data, pointed to by *p, should be used raw. */
364static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff,
365 unsigned char **p, u16 **desc)
366{
367 int d = **desc;
368
369 (*desc)++;
370
371 /* No more data needs mangling */
372 if (d == (u16)-1)
373 return 0;
374
375 if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
376 /* domain-name, canonicalise */
377 return to_wire(buff);
378 else
379 {
380 /* plain data preceding a domain-name, don't run off the end of the data */
381 if ((end - *p) < d)
382 d = end - *p;
383
384 if (d != 0)
385 {
386 memcpy(buff, *p, d);
387 *p += d;
388 }
389
390 return d;
391 }
0852d76b
GB
392}
393
5f8e58f4
SK
394/* Bubble sort the RRset into the canonical order.
395 Note that the byte-streams from two RRs may get unsynced: consider
396 RRs which have two domain-names at the start and then other data.
397 The domain-names may have different lengths in each RR, but sort equal
398
399 ------------
400 |abcde|fghi|
401 ------------
402 |abcd|efghi|
403 ------------
404
405 leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
406*/
407
408static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
409 unsigned char **rrset, char *buff1, char *buff2)
c3e0b9b6 410{
5f8e58f4 411 int swap, quit, i;
0fc2f313 412
5f8e58f4
SK
413 do
414 {
415 for (swap = 0, i = 0; i < rrsetidx-1; i++)
416 {
417 int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
418 u16 *dp1, *dp2;
419 unsigned char *end1, *end2;
420 unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
421 unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
422
423 p1 += 8; /* skip class, type, ttl */
424 GETSHORT(rdlen1, p1);
425 end1 = p1 + rdlen1;
426
427 p2 += 8; /* skip class, type, ttl */
428 GETSHORT(rdlen2, p2);
429 end2 = p2 + rdlen2;
430
431 dp1 = dp2 = rr_desc;
432
1486a9c7 433 for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
5f8e58f4 434 {
1486a9c7
SK
435 if (left1 != 0)
436 memmove(buff1, buff1 + len1 - left1, left1);
437
5f8e58f4
SK
438 if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
439 {
440 quit = 1;
441 len1 = end1 - p1;
442 memcpy(buff1 + left1, p1, len1);
443 }
444 len1 += left1;
445
1486a9c7
SK
446 if (left2 != 0)
447 memmove(buff2, buff2 + len2 - left2, left2);
448
5f8e58f4
SK
449 if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
450 {
451 quit = 1;
452 len2 = end2 - p2;
453 memcpy(buff2 + left2, p2, len2);
454 }
455 len2 += left2;
456
457 if (len1 > len2)
1486a9c7 458 left1 = len1 - len2, left2 = 0, len = len2;
5f8e58f4 459 else
1486a9c7 460 left2 = len2 - len1, left1 = 0, len = len1;
5f8e58f4
SK
461
462 rc = memcmp(buff1, buff2, len);
463
1486a9c7 464 if (rc == 1 || (rc == 0 && quit && len1 > len2))
5f8e58f4
SK
465 {
466 unsigned char *tmp = rrset[i+1];
467 rrset[i+1] = rrset[i];
468 rrset[i] = tmp;
469 swap = quit = 1;
470 }
471 }
472 }
473 } while (swap);
474}
c3e0b9b6 475
5f8e58f4
SK
476/* Validate a single RRset (class, type, name) in the supplied DNS reply
477 Return code:
478 STAT_SECURE if it validates.
479 STAT_INSECURE can't validate (no RRSIG, bad packet).
480 STAT_BOGUS signature is wrong.
481 STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
482
483 if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
484 otherwise find the key in the cache.
485*/
486static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class,
487 int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
488{
489 static unsigned char **rrset = NULL, **sigs = NULL;
490 static int rrset_sz = 0, sig_sz = 0;
0fc2f313 491
5f8e58f4 492 unsigned char *p;
5ada8885 493 int rrsetidx, sigidx, res, rdlen, j, name_labels;
5f8e58f4
SK
494 struct crec *crecp = NULL;
495 int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
496 u16 *rr_desc = get_desc(type);
c3e0b9b6 497
5f8e58f4
SK
498 if (!(p = skip_questions(header, plen)))
499 return STAT_INSECURE;
c3e0b9b6 500
5ada8885
SK
501 name_labels = count_labels(name); /* For 4035 5.3.2 check */
502
503 /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
5f8e58f4
SK
504 for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount);
505 j != 0; j--)
506 {
507 unsigned char *pstart, *pdata;
5ada8885 508 int stype, sclass;
c3e0b9b6 509
5f8e58f4
SK
510 pstart = p;
511
512 if (!(res = extract_name(header, plen, &p, name, 0, 10)))
513 return STAT_INSECURE; /* bad packet */
514
515 GETSHORT(stype, p);
516 GETSHORT(sclass, p);
5ada8885 517 p += 4; /* TTL */
5f8e58f4
SK
518
519 pdata = p;
c3e0b9b6 520
5f8e58f4
SK
521 GETSHORT(rdlen, p);
522
5f8e58f4
SK
523 if (res == 1 && sclass == class)
524 {
525 if (stype == type)
526 {
527 if (rrsetidx == rrset_sz)
528 {
529 unsigned char **new;
530
531 /* expand */
532 if (!(new = whine_malloc((rrset_sz + 5) * sizeof(unsigned char **))))
533 return STAT_INSECURE;
534
535 if (rrset)
536 {
537 memcpy(new, rrset, rrset_sz * sizeof(unsigned char **));
538 free(rrset);
539 }
540
541 rrset = new;
542 rrset_sz += 5;
543 }
544 rrset[rrsetidx++] = pstart;
545 }
546
547 if (stype == T_RRSIG)
548 {
5ada8885
SK
549 if (rdlen < 18)
550 return STAT_INSECURE; /* bad packet */
551
552 GETSHORT(type_covered, p);
553 algo = *p++;
554 labels = *p++;
555 p += 4; /* orig_ttl */
556 GETLONG(sig_expiration, p);
557 GETLONG(sig_inception, p);
558 p = pdata + 2; /* restore for ADD_RDLEN */
559
560 if (type_covered == type &&
561 check_date_range(sig_inception, sig_expiration) &&
86bec2d3 562 hash_find(algo_digest_name(algo)) &&
5ada8885
SK
563 labels <= name_labels)
564 {
565 if (sigidx == sig_sz)
566 {
567 unsigned char **new;
568
569 /* expand */
570 if (!(new = whine_malloc((sig_sz + 5) * sizeof(unsigned char **))))
571 return STAT_INSECURE;
572
573 if (sigs)
574 {
575 memcpy(new, sigs, sig_sz * sizeof(unsigned char **));
576 free(sigs);
577 }
578
579 sigs = new;
580 sig_sz += 5;
581 }
582
583 sigs[sigidx++] = pdata;
584 }
5f8e58f4
SK
585 }
586 }
587
588 if (!ADD_RDLEN(header, p, plen, rdlen))
589 return STAT_INSECURE;
590 }
c3e0b9b6 591
5f8e58f4
SK
592 /* RRset empty, no RRSIGs */
593 if (rrsetidx == 0 || sigidx == 0)
594 return STAT_INSECURE;
595
596 /* Sort RRset records into canonical order.
597 Note that at this point keyname and name buffs are
598 unused, and used as workspace by the sort. */
599 sort_rrset(header, plen, rr_desc, rrsetidx, rrset, name, keyname);
600
601 /* Now try all the sigs to try and find one which validates */
602 for (j = 0; j <sigidx; j++)
603 {
86bec2d3
SK
604 unsigned char *psav, *sig;
605 int i, wire_len, sig_len;
606 const struct nettle_hash *hash;
607 void *ctx;
608 unsigned char *digest;
5f8e58f4
SK
609 u32 nsigttl;
610
611 p = sigs[j];
5ada8885 612 GETSHORT(rdlen, p); /* rdlen >= 18 checked previously */
5f8e58f4
SK
613 psav = p;
614
5ada8885 615 p += 2; /* type_covered - already checked */
5f8e58f4
SK
616 algo = *p++;
617 labels = *p++;
618 GETLONG(orig_ttl, p);
5ada8885 619 p += 8; /* sig_expiration and sig_inception */
5f8e58f4
SK
620 GETSHORT(key_tag, p);
621
5f8e58f4
SK
622 if (!extract_name(header, plen, &p, keyname, 1, 0))
623 return STAT_INSECURE;
624
625 /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
626 if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
627 return STAT_NEED_KEY;
628
86bec2d3
SK
629 sig = p;
630 sig_len = rdlen - (p - psav);
631
632 if (!(hash = hash_find(algo_digest_name(algo))) ||
633 !hash_init(hash, &ctx, &digest))
634 continue;
5f8e58f4
SK
635
636 nsigttl = htonl(orig_ttl);
637
86bec2d3 638 hash->update(ctx, 18, psav);
5f8e58f4 639 wire_len = to_wire(keyname);
86bec2d3 640 hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
5f8e58f4
SK
641 from_wire(keyname);
642
5f8e58f4
SK
643 for (i = 0; i < rrsetidx; ++i)
644 {
645 int seg;
646 unsigned char *end, *cp;
5ada8885 647 char *name_start = name;
5f8e58f4
SK
648 u16 len, *dp;
649
650 p = rrset[i];
651 if (!extract_name(header, plen, &p, name, 1, 10))
652 return STAT_INSECURE;
5ada8885
SK
653
654 /* if more labels than in RRsig name, hash *.<no labels in rrsig labels field> 4035 5.3.2 */
655 if (labels < name_labels)
656 {
657 int k;
658 for (k = name_labels - labels; k != 0; k--)
659 while (*name_start != '.' && *name_start != 0)
660 name_start++;
661 name_start--;
662 *name_start = '*';
663 }
664
665 wire_len = to_wire(name_start);
86bec2d3
SK
666 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
667 hash->update(ctx, 4, p); /* class and type */
668 hash->update(ctx, 4, (unsigned char *)&nsigttl);
5f8e58f4
SK
669
670 p += 8; /* skip class, type, ttl */
671 GETSHORT(rdlen, p);
5ada8885
SK
672 if (!CHECK_LEN(header, p, plen, rdlen))
673 return STAT_INSECURE;
674
5f8e58f4
SK
675 end = p + rdlen;
676
677 /* canonicalise rdata and calculate length of same, use name buffer as workspace */
678 cp = p;
679 dp = rr_desc;
680 for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
681 len += end - cp;
682 len = htons(len);
86bec2d3 683 hash->update(ctx, 2, (unsigned char *)&len);
5f8e58f4
SK
684
685 /* Now canonicalise again and digest. */
686 cp = p;
687 dp = rr_desc;
688 while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
86bec2d3 689 hash->update(ctx, seg, (unsigned char *)name);
5f8e58f4 690 if (cp != end)
86bec2d3 691 hash->update(ctx, end - cp, cp);
5f8e58f4 692 }
86bec2d3
SK
693
694 hash->digest(ctx, hash->digest_size, digest);
695
5ada8885
SK
696 /* namebuff used for workspace above, restore to leave unchanged on exit */
697 p = (unsigned char*)(rrset[0]);
698 extract_name(header, plen, &p, name, 1, 0);
699
5f8e58f4
SK
700 if (key)
701 {
702 if (algo_in == algo && keytag_in == key_tag &&
86bec2d3 703 verify(key, keylen, sig, sig_len, digest, algo))
5f8e58f4
SK
704 return STAT_SECURE;
705 }
706 else
707 {
708 /* iterate through all possible keys 4035 5.3.1 */
709 for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
710 if (crecp->addr.key.algo == algo && crecp->addr.key.keytag == key_tag &&
86bec2d3 711 verify(crecp->addr.key.keydata, crecp->uid, sig, sig_len, digest, algo))
5f8e58f4
SK
712 return STAT_SECURE;
713 }
714 }
715
716 return STAT_BOGUS;
717}
718
0fc2f313 719/* The DNS packet is expected to contain the answer to a DNSKEY query.
5f8e58f4 720 Leave name of query in name.
c3e0b9b6
SK
721 Put all DNSKEYs in the answer which are valid into the cache.
722 return codes:
723 STAT_INSECURE bad packet, no DNSKEYs in reply.
724 STAT_SECURE At least one valid DNSKEY found and in cache.
0fc2f313
SK
725 STAT_BOGUS No DNSKEYs found, which can be validated with DS,
726 or self-sign for DNSKEY RRset is not valid.
727 STAT_NEED_DS DS records to validate a key not found, name in keyname
c3e0b9b6
SK
728*/
729int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
730{
0fc2f313 731 unsigned char *psave, *p = (unsigned char *)(header+1);
c3e0b9b6 732 struct crec *crecp, *recp1;
0fc2f313 733 int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag;
c3e0b9b6
SK
734 struct blockdata *key;
735
5f8e58f4
SK
736 if (ntohs(header->qdcount) != 1 ||
737 !extract_name(header, plen, &p, name, 1, 4))
738 {
739 strcpy(name, "<none>");
740 return STAT_INSECURE;
741 }
742
c3e0b9b6
SK
743 GETSHORT(qtype, p);
744 GETSHORT(qclass, p);
745
0fc2f313 746 if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0)
c3e0b9b6
SK
747 return STAT_INSECURE;
748
0fc2f313
SK
749 /* See if we have cached a DS record which validates this key */
750 if (!(crecp = cache_find_by_name(NULL, name, now, F_DS)))
751 {
752 strcpy(keyname, name);
753 return STAT_NEED_DS;
754 }
755
c3e0b9b6
SK
756 cache_start_insert();
757
0fc2f313
SK
758 /* NOTE, we need to find ONE DNSKEY which matches the DS */
759 for (valid = 0, j = ntohs(header->ancount); j != 0; j--)
c3e0b9b6
SK
760 {
761 /* Ensure we have type, class TTL and length */
0fc2f313 762 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
c3e0b9b6
SK
763 return STAT_INSECURE; /* bad packet */
764
765 GETSHORT(qtype, p);
766 GETSHORT(qclass, p);
767 GETLONG(ttl, p);
768 GETSHORT(rdlen, p);
769
0fc2f313 770 if (qclass != class || qtype != T_DNSKEY || rc == 2)
c3e0b9b6 771 {
0fc2f313
SK
772 if (ADD_RDLEN(header, p, plen, rdlen))
773 continue;
774
775 return STAT_INSECURE; /* bad packet */
c3e0b9b6
SK
776 }
777
0fc2f313
SK
778 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
779 return STAT_INSECURE; /* bad packet */
780
781 psave = p;
c3e0b9b6 782
c3e0b9b6 783 GETSHORT(flags, p);
0fc2f313
SK
784 if (*p++ != 3)
785 return STAT_INSECURE;
c3e0b9b6 786 algo = *p++;
0fc2f313 787 keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
c3e0b9b6 788
0fc2f313
SK
789 /* Put the key into the cache. Note that if the validation fails, we won't
790 call cache_end_insert() and this will never be committed. */
791 if ((key = blockdata_alloc((char*)p, rdlen - 4)) &&
792 (recp1 = cache_insert(name, NULL, now, ttl, F_FORWARD | F_DNSKEY)))
c3e0b9b6 793 {
0fc2f313
SK
794 recp1->uid = rdlen - 4;
795 recp1->addr.key.keydata = key;
796 recp1->addr.key.algo = algo;
797 recp1->addr.key.keytag = keytag;
c3e0b9b6
SK
798 }
799
0fc2f313
SK
800 p = psave;
801 if (!ADD_RDLEN(header, p, plen, rdlen))
802 return STAT_INSECURE; /* bad packet */
c3e0b9b6 803
0fc2f313
SK
804 /* Already determined that message is OK. Just loop stuffing cache */
805 if (valid || !key)
806 continue;
807
808 for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
86bec2d3
SK
809 {
810 void *ctx;
811 unsigned char *digest, *ds_digest;
812 const struct nettle_hash *hash;
813
814 if (recp1->addr.key.algo == algo &&
815 recp1->addr.key.keytag == keytag &&
816 (flags & 0x100) && /* zone key flag */
817 (hash = hash_find(ds_digest_name(recp1->addr.key.digest))) &&
818 hash_init(hash, &ctx, &digest))
0fc2f313 819
86bec2d3
SK
820 {
821 int wire_len = to_wire(name);
822
823 /* Note that digest may be different between DSs, so
824 we can't move this outside the loop. */
825 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
826 hash->update(ctx, (unsigned int)rdlen, psave);
827 hash->digest(ctx, hash->digest_size, digest);
828
829 from_wire(name);
830
831 if (recp1->uid == (int)hash->digest_size &&
832 (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->uid, NULL)) &&
833 memcmp (ds_digest, digest, recp1->uid) == 0 &&
834 validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag))
835 {
836 struct all_addr a;
837 valid = 1;
838 a.addr.keytag = keytag;
839 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
840 break;
841 }
842 }
843 }
c3e0b9b6 844 }
c3e0b9b6 845
0fc2f313
SK
846 if (valid)
847 {
848 /* commit cache insert. */
849 cache_end_insert();
850 return STAT_SECURE;
851 }
852
853 log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
854 return STAT_BOGUS;
c3e0b9b6 855}
0fc2f313 856
c3e0b9b6 857/* The DNS packet is expected to contain the answer to a DS query
0fc2f313 858 Leave name of DS query in name.
c3e0b9b6
SK
859 Put all DSs in the answer which are valid into the cache.
860 return codes:
0fc2f313 861 STAT_INSECURE bad packet, no DS in reply.
c3e0b9b6
SK
862 STAT_SECURE At least one valid DS found and in cache.
863 STAT_BOGUS At least one DS found, which fails validation.
864 STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
865*/
866
867int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
868{
0fc2f313
SK
869 unsigned char *psave, *p = (unsigned char *)(header+1);
870 struct crec *crecp;
c3e0b9b6
SK
871 int qtype, qclass, val, j, gotone;
872 struct blockdata *key;
873
5f8e58f4
SK
874 if (ntohs(header->qdcount) != 1 ||
875 !extract_name(header, plen, &p, name, 1, 4))
876 {
877 strcpy(name, "<none>");
878 return STAT_INSECURE;
879 }
880
c3e0b9b6
SK
881 GETSHORT(qtype, p);
882 GETSHORT(qclass, p);
883
0fc2f313 884 if (qtype != T_DS || qclass != class || ntohs(header->ancount) == 0)
c3e0b9b6 885 return STAT_INSECURE;
0fc2f313
SK
886
887 val = validate_rrset(now, header, plen, class, T_DS, name, keyname, NULL, 0, 0, 0);
888
889 if (val == STAT_BOGUS)
890 log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
c3e0b9b6
SK
891
892 /* failed to validate or missing key. */
893 if (val != STAT_SECURE)
894 return val;
895
896 cache_start_insert();
897
898 for (gotone = 0, j = ntohs(header->ancount); j != 0; j--)
899 {
0fc2f313 900 int ttl, rdlen, rc, algo, digest, keytag;
c3e0b9b6
SK
901
902 /* Ensure we have type, class TTL and length */
903 if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
904 return STAT_INSECURE; /* bad packet */
905
906 GETSHORT(qtype, p);
907 GETSHORT(qclass, p);
908 GETLONG(ttl, p);
909 GETSHORT(rdlen, p);
910
911 /* check type, class and name, skip if not in DS rrset */
0fc2f313 912 if (qclass == class && qtype == T_DS && rc == 1)
c3e0b9b6 913 {
0fc2f313
SK
914 if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
915 return STAT_INSECURE; /* bad packet */
916
917 psave = p;
918 GETSHORT(keytag, p);
919 algo = *p++;
920 digest = *p++;
c3e0b9b6
SK
921
922 /* We've proved that the DS is OK, store it in the cache */
0fc2f313
SK
923 if ((key = blockdata_alloc((char*)p, rdlen - 4)) &&
924 (crecp = cache_insert(name, NULL, now, ttl, F_FORWARD | F_DS)))
c3e0b9b6 925 {
0fc2f313
SK
926 struct all_addr a;
927 a.addr.keytag = keytag;
928 log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
929 crecp->addr.key.digest = digest;
c3e0b9b6
SK
930 crecp->addr.key.keydata = key;
931 crecp->addr.key.algo = algo;
0fc2f313 932 crecp->addr.key.keytag = keytag;
b6e9e7c3 933 crecp->uid = rdlen - 4;
c3e0b9b6 934 }
0fc2f313
SK
935 else
936 return STAT_INSECURE; /* cache problem */
937
938 p = psave;
c3e0b9b6 939 }
0fc2f313
SK
940
941 if (!ADD_RDLEN(header, p, plen, rdlen))
942 return STAT_INSECURE; /* bad packet */
943
c3e0b9b6
SK
944 }
945
946 cache_end_insert();
947
0fc2f313 948 return STAT_SECURE;
c3e0b9b6
SK
949}
950
0fc2f313
SK
951/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
952int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class)
adca3e9c 953{
0fc2f313
SK
954 unsigned char *ans_start, *p1, *p2;
955 int type1, class1, rdlen1, type2, class2, rdlen2;
956 int i, j, rc;
adca3e9c 957
0fc2f313
SK
958 if (!(ans_start = skip_questions(header, plen)))
959 return STAT_INSECURE;
960
961 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
adca3e9c 962 {
0fc2f313
SK
963 if (!extract_name(header, plen, &p1, name, 1, 10))
964 return STAT_INSECURE; /* bad packet */
965
966 GETSHORT(type1, p1);
967 GETSHORT(class1, p1);
968 p1 += 4; /* TTL */
969 GETSHORT(rdlen1, p1);
970
971 /* Don't try and validate RRSIGs! */
972 if (type1 != T_RRSIG)
973 {
974 /* Check if we've done this RRset already */
975 for (p2 = ans_start, j = 0; j < i; j++)
976 {
977 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
978 return STAT_INSECURE; /* bad packet */
979
980 GETSHORT(type2, p2);
981 GETSHORT(class2, p2);
982 p2 += 4; /* TTL */
983 GETSHORT(rdlen2, p2);
984
985 if (type2 == type1 && class2 == class1 && rc == 1)
986 break; /* Done it before: name, type, class all match. */
987
988 if (!ADD_RDLEN(header, p2, plen, rdlen2))
989 return STAT_INSECURE;
990 }
991
992 /* Not done, validate now */
993 if (j == i && (rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0)) != STAT_SECURE)
994 {
995 *class = class1; /* Class for DS or DNSKEY */
996 return rc;
997 }
998 }
adca3e9c 999
0fc2f313
SK
1000 if (!ADD_RDLEN(header, p1, plen, rdlen1))
1001 return STAT_INSECURE;
adca3e9c
GB
1002 }
1003
0fc2f313 1004 return STAT_SECURE;
e292e93d
GB
1005}
1006
c3e0b9b6 1007
3471f181 1008/* Compute keytag (checksum to quickly index a key). See RFC4034 */
0fc2f313 1009int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
3471f181 1010{
75ffc9bf
GB
1011 if (alg == 1)
1012 {
1013 /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
1014 See RFC4034, Appendix B.1 */
0fc2f313 1015 return key[keylen-4] * 256 + key[keylen-3];
75ffc9bf
GB
1016 }
1017 else
1018 {
1019 unsigned long ac;
1020 int i;
1021
0fc2f313
SK
1022 ac = ((htons(flags) >> 8) | ((htons(flags) << 8) & 0xff00)) + 0x300 + alg;
1023 for (i = 0; i < keylen; ++i)
1024 ac += (i & 1) ? key[i] : key[i] << 8;
1025 ac += (ac >> 16) & 0xffff;
1026 return ac & 0xffff;
0304d28f 1027 }
3471f181 1028}
e292e93d 1029
5f8e58f4
SK
1030size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
1031{
1032 unsigned char *p;
1033 char types[20];
1034
1035 querystr("dnssec", types, type);
1036
1037 if (addr->sa.sa_family == AF_INET)
1038 log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
1039#ifdef HAVE_IPV6
1040 else
1041 log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
1042#endif
1043
1044 header->qdcount = htons(1);
1045 header->ancount = htons(0);
1046 header->nscount = htons(0);
1047 header->arcount = htons(0);
e292e93d 1048
5f8e58f4
SK
1049 header->hb3 = HB3_RD;
1050 SET_OPCODE(header, QUERY);
1051 header->hb4 = HB4_CD;
1052
1053 /* ID filled in later */
1054
1055 p = (unsigned char *)(header+1);
1056
1057 p = do_rfc1035_name(p, name);
1058 *p++ = 0;
1059 PUTSHORT(type, p);
1060 PUTSHORT(class, p);
1061
1062 return add_do_bit(header, p - (unsigned char *)header, end);
1063}
1064
0fc2f313 1065#endif /* HAVE_DNSSEC */