]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/unbound/validator/val_sigcrypt.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / unbound / validator / val_sigcrypt.c
1 /*
2  * validator/val_sigcrypt.c - validator signature crypto functions.
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 /**
37  * \file
38  *
39  * This file contains helper functions for the validator module.
40  * The functions help with signature verification and checking, the
41  * bridging between RR wireformat data and crypto calls.
42  */
43 #include "config.h"
44 #include "validator/val_sigcrypt.h"
45 #include "validator/val_secalgo.h"
46 #include "validator/validator.h"
47 #include "util/data/msgreply.h"
48 #include "util/data/msgparse.h"
49 #include "util/data/dname.h"
50 #include "util/rbtree.h"
51 #include "util/module.h"
52 #include "util/net_help.h"
53 #include "util/regional.h"
54 #include "ldns/keyraw.h"
55 #include "ldns/sbuffer.h"
56 #include "ldns/parseutil.h"
57 #include "ldns/wire2str.h"
58
59 #include <ctype.h>
60 #if !defined(HAVE_SSL) && !defined(HAVE_NSS)
61 #error "Need crypto library to do digital signature cryptography"
62 #endif
63
64 #ifdef HAVE_OPENSSL_ERR_H
65 #include <openssl/err.h>
66 #endif
67
68 #ifdef HAVE_OPENSSL_RAND_H
69 #include <openssl/rand.h>
70 #endif
71
72 #ifdef HAVE_OPENSSL_CONF_H
73 #include <openssl/conf.h>
74 #endif
75
76 #ifdef HAVE_OPENSSL_ENGINE_H
77 #include <openssl/engine.h>
78 #endif
79
80 /** return number of rrs in an rrset */
81 static size_t
82 rrset_get_count(struct ub_packed_rrset_key* rrset)
83 {
84         struct packed_rrset_data* d = (struct packed_rrset_data*)
85         rrset->entry.data;
86         if(!d) return 0;
87         return d->count;
88 }
89
90 /**
91  * Get RR signature count
92  */
93 static size_t
94 rrset_get_sigcount(struct ub_packed_rrset_key* k)
95 {
96         struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
97         return d->rrsig_count;
98 }
99
100 /**
101  * Get signature keytag value
102  * @param k: rrset (with signatures)
103  * @param sig_idx: signature index.
104  * @return keytag or 0 if malformed rrsig.
105  */
106 static uint16_t 
107 rrset_get_sig_keytag(struct ub_packed_rrset_key* k, size_t sig_idx)
108 {
109         uint16_t t;
110         struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
111         log_assert(sig_idx < d->rrsig_count);
112         if(d->rr_len[d->count + sig_idx] < 2+18)
113                 return 0;
114         memmove(&t, d->rr_data[d->count + sig_idx]+2+16, 2);
115         return ntohs(t);
116 }
117
118 /**
119  * Get signature signing algorithm value
120  * @param k: rrset (with signatures)
121  * @param sig_idx: signature index.
122  * @return algo or 0 if malformed rrsig.
123  */
124 static int 
125 rrset_get_sig_algo(struct ub_packed_rrset_key* k, size_t sig_idx)
126 {
127         struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
128         log_assert(sig_idx < d->rrsig_count);
129         if(d->rr_len[d->count + sig_idx] < 2+3)
130                 return 0;
131         return (int)d->rr_data[d->count + sig_idx][2+2];
132 }
133
134 /** get rdata pointer and size */
135 static void
136 rrset_get_rdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** rdata,
137         size_t* len)
138 {
139         struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
140         log_assert(d && idx < (d->count + d->rrsig_count));
141         *rdata = d->rr_data[idx];
142         *len = d->rr_len[idx];
143 }
144
145 uint16_t
146 dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx)
147 {
148         uint8_t* rdata;
149         size_t len;
150         uint16_t f;
151         rrset_get_rdata(k, idx, &rdata, &len);
152         if(len < 2+2)
153                 return 0;
154         memmove(&f, rdata+2, 2);
155         f = ntohs(f);
156         return f;
157 }
158
159 /**
160  * Get DNSKEY protocol value from rdata
161  * @param k: DNSKEY rrset.
162  * @param idx: which key.
163  * @return protocol octet value
164  */
165 static int
166 dnskey_get_protocol(struct ub_packed_rrset_key* k, size_t idx)
167 {
168         uint8_t* rdata;
169         size_t len;
170         rrset_get_rdata(k, idx, &rdata, &len);
171         if(len < 2+4)
172                 return 0;
173         return (int)rdata[2+2];
174 }
175
176 int
177 dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx)
178 {
179         uint8_t* rdata;
180         size_t len;
181         rrset_get_rdata(k, idx, &rdata, &len);
182         if(len < 2+4)
183                 return 0;
184         return (int)rdata[2+3];
185 }
186
187 /** get public key rdata field from a dnskey RR and do some checks */
188 static void
189 dnskey_get_pubkey(struct ub_packed_rrset_key* k, size_t idx,
190         unsigned char** pk, unsigned int* pklen)
191 {
192         uint8_t* rdata;
193         size_t len;
194         rrset_get_rdata(k, idx, &rdata, &len);
195         if(len < 2+5) {
196                 *pk = NULL;
197                 *pklen = 0;
198                 return;
199         }
200         *pk = (unsigned char*)rdata+2+4;
201         *pklen = (unsigned)len-2-4;
202 }
203
204 int
205 ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx)
206 {
207         uint8_t* rdata;
208         size_t len;
209         rrset_get_rdata(k, idx, &rdata, &len);
210         if(len < 2+3)
211                 return 0;
212         return (int)rdata[2+2];
213 }
214
215 int
216 ds_get_digest_algo(struct ub_packed_rrset_key* k, size_t idx)
217 {
218         uint8_t* rdata;
219         size_t len;
220         rrset_get_rdata(k, idx, &rdata, &len);
221         if(len < 2+4)
222                 return 0;
223         return (int)rdata[2+3];
224 }
225
226 uint16_t 
227 ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx)
228 {
229         uint16_t t;
230         uint8_t* rdata;
231         size_t len;
232         rrset_get_rdata(ds_rrset, ds_idx, &rdata, &len);
233         if(len < 2+2)
234                 return 0;
235         memmove(&t, rdata+2, 2);
236         return ntohs(t);
237 }
238
239 /**
240  * Return pointer to the digest in a DS RR.
241  * @param k: DS rrset.
242  * @param idx: which DS.
243  * @param digest: digest data is returned.
244  *      on error, this is NULL.
245  * @param len: length of digest is returned.
246  *      on error, the length is 0.
247  */
248 static void
249 ds_get_sigdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** digest,
250         size_t* len)
251 {
252         uint8_t* rdata;
253         size_t rdlen;
254         rrset_get_rdata(k, idx, &rdata, &rdlen);
255         if(rdlen < 2+5) {
256                 *digest = NULL;
257                 *len = 0;
258                 return;
259         }
260         *digest = rdata + 2 + 4;
261         *len = rdlen - 2 - 4;
262 }
263
264 /**
265  * Return size of DS digest according to its hash algorithm.
266  * @param k: DS rrset.
267  * @param idx: which DS.
268  * @return size in bytes of digest, or 0 if not supported. 
269  */
270 static size_t
271 ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx)
272 {
273         return ds_digest_size_supported(ds_get_digest_algo(k, idx));
274 }
275
276 /**
277  * Create a DS digest for a DNSKEY entry.
278  *
279  * @param env: module environment. Uses scratch space.
280  * @param dnskey_rrset: DNSKEY rrset.
281  * @param dnskey_idx: index of RR in rrset.
282  * @param ds_rrset: DS rrset
283  * @param ds_idx: index of RR in DS rrset.
284  * @param digest: digest is returned in here (must be correctly sized).
285  * @return false on error.
286  */
287 static int
288 ds_create_dnskey_digest(struct module_env* env, 
289         struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx,
290         struct ub_packed_rrset_key* ds_rrset, size_t ds_idx,
291         uint8_t* digest)
292 {
293         sldns_buffer* b = env->scratch_buffer;
294         uint8_t* dnskey_rdata;
295         size_t dnskey_len;
296         rrset_get_rdata(dnskey_rrset, dnskey_idx, &dnskey_rdata, &dnskey_len);
297
298         /* create digest source material in buffer 
299          * digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
300          *      DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. */
301         sldns_buffer_clear(b);
302         sldns_buffer_write(b, dnskey_rrset->rk.dname, 
303                 dnskey_rrset->rk.dname_len);
304         query_dname_tolower(sldns_buffer_begin(b));
305         sldns_buffer_write(b, dnskey_rdata+2, dnskey_len-2); /* skip rdatalen*/
306         sldns_buffer_flip(b);
307         
308         return secalgo_ds_digest(ds_get_digest_algo(ds_rrset, ds_idx),
309                 (unsigned char*)sldns_buffer_begin(b), sldns_buffer_limit(b),
310                 (unsigned char*)digest);
311 }
312
313 int ds_digest_match_dnskey(struct module_env* env,
314         struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx,
315         struct ub_packed_rrset_key* ds_rrset, size_t ds_idx)
316 {
317         uint8_t* ds;    /* DS digest */
318         size_t dslen;
319         uint8_t* digest; /* generated digest */
320         size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx);
321         
322         if(digestlen == 0) {
323                 verbose(VERB_QUERY, "DS fail: not supported, or DS RR "
324                         "format error");
325                 return 0; /* not supported, or DS RR format error */
326         }
327         /* check digest length in DS with length from hash function */
328         ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen);
329         if(!ds || dslen != digestlen) {
330                 verbose(VERB_QUERY, "DS fail: DS RR algo and digest do not "
331                         "match each other");
332                 return 0; /* DS algorithm and digest do not match */
333         }
334
335         digest = regional_alloc(env->scratch, digestlen);
336         if(!digest) {
337                 verbose(VERB_QUERY, "DS fail: out of memory");
338                 return 0; /* mem error */
339         }
340         if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset, 
341                 ds_idx, digest)) {
342                 verbose(VERB_QUERY, "DS fail: could not calc key digest");
343                 return 0; /* digest algo failed */
344         }
345         if(memcmp(digest, ds, dslen) != 0) {
346                 verbose(VERB_QUERY, "DS fail: digest is different");
347                 return 0; /* digest different */
348         }
349         return 1;
350 }
351
352 int 
353 ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 
354         size_t ds_idx)
355 {
356         return (ds_digest_size_algo(ds_rrset, ds_idx) != 0);
357 }
358
359 int 
360 ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 
361         size_t ds_idx)
362 {
363         return dnskey_algo_id_is_supported(ds_get_key_algo(ds_rrset, ds_idx));
364 }
365
366 uint16_t 
367 dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx)
368 {
369         uint8_t* data;
370         size_t len;
371         rrset_get_rdata(dnskey_rrset, dnskey_idx, &data, &len);
372         /* do not pass rdatalen to ldns */
373         return sldns_calc_keytag_raw(data+2, len-2);
374 }
375
376 int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset,
377         size_t dnskey_idx)
378 {
379         return dnskey_algo_id_is_supported(dnskey_get_algo(dnskey_rrset, 
380                 dnskey_idx));
381 }
382
383 void algo_needs_init_dnskey_add(struct algo_needs* n,
384         struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
385 {
386         uint8_t algo;
387         size_t i, total = n->num;
388         size_t num = rrset_get_count(dnskey);
389
390         for(i=0; i<num; i++) {
391                 algo = (uint8_t)dnskey_get_algo(dnskey, i);
392                 if(!dnskey_algo_id_is_supported((int)algo))
393                         continue;
394                 if(n->needs[algo] == 0) {
395                         n->needs[algo] = 1;
396                         sigalg[total] = algo;
397                         total++;
398                 }
399         }
400         sigalg[total] = 0;
401         n->num = total;
402 }
403
404 void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg)
405 {
406         uint8_t algo;
407         size_t total = 0;
408
409         memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
410         while( (algo=*sigalg++) != 0) {
411                 log_assert(dnskey_algo_id_is_supported((int)algo));
412                 log_assert(n->needs[algo] == 0);
413                 n->needs[algo] = 1;
414                 total++;
415         }
416         n->num = total;
417 }
418
419 void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
420         int fav_ds_algo, uint8_t* sigalg)
421 {
422         uint8_t algo;
423         size_t i, total = 0;
424         size_t num = rrset_get_count(ds);
425
426         memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
427         for(i=0; i<num; i++) {
428                 if(ds_get_digest_algo(ds, i) != fav_ds_algo)
429                         continue;
430                 algo = (uint8_t)ds_get_key_algo(ds, i);
431                 if(!dnskey_algo_id_is_supported((int)algo))
432                         continue;
433                 log_assert(algo != 0); /* we do not support 0 and is EOS */
434                 if(n->needs[algo] == 0) {
435                         n->needs[algo] = 1;
436                         sigalg[total] = algo;           
437                         total++;
438                 }
439         }
440         sigalg[total] = 0;
441         n->num = total;
442 }
443
444 int algo_needs_set_secure(struct algo_needs* n, uint8_t algo)
445 {
446         if(n->needs[algo]) {
447                 n->needs[algo] = 0;
448                 n->num --;
449                 if(n->num == 0) /* done! */
450                         return 1;
451         }
452         return 0;
453 }
454
455 void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo)
456 {
457         if(n->needs[algo]) n->needs[algo] = 2; /* need it, but bogus */
458 }
459
460 size_t algo_needs_num_missing(struct algo_needs* n)
461 {
462         return n->num;
463 }
464
465 int algo_needs_missing(struct algo_needs* n)
466 {
467         int i;
468         /* first check if a needed algo was bogus - report that */
469         for(i=0; i<ALGO_NEEDS_MAX; i++)
470                 if(n->needs[i] == 2)
471                         return 0;
472         /* now check which algo is missing */
473         for(i=0; i<ALGO_NEEDS_MAX; i++)
474                 if(n->needs[i] == 1)
475                         return i;
476         return 0;
477 }
478
479 enum sec_status 
480 dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
481         struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
482         uint8_t* sigalg, char** reason)
483 {
484         enum sec_status sec;
485         size_t i, num;
486         rbtree_t* sortree = NULL;
487         /* make sure that for all DNSKEY algorithms there are valid sigs */
488         struct algo_needs needs;
489         int alg;
490
491         num = rrset_get_sigcount(rrset);
492         if(num == 0) {
493                 verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
494                         "signatures");
495                 *reason = "no signatures";
496                 return sec_status_bogus;
497         }
498
499         if(sigalg) {
500                 algo_needs_init_list(&needs, sigalg);
501                 if(algo_needs_num_missing(&needs) == 0) {
502                         verbose(VERB_QUERY, "zone has no known algorithms");
503                         *reason = "zone has no known algorithms";
504                         return sec_status_insecure;
505                 }
506         }
507         for(i=0; i<num; i++) {
508                 sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset, 
509                         dnskey, i, &sortree, reason);
510                 /* see which algorithm has been fixed up */
511                 if(sec == sec_status_secure) {
512                         if(!sigalg)
513                                 return sec; /* done! */
514                         else if(algo_needs_set_secure(&needs,
515                                 (uint8_t)rrset_get_sig_algo(rrset, i)))
516                                 return sec; /* done! */
517                 } else if(sigalg && sec == sec_status_bogus) {
518                         algo_needs_set_bogus(&needs,
519                                 (uint8_t)rrset_get_sig_algo(rrset, i));
520                 }
521         }
522         if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
523                 verbose(VERB_ALGO, "rrset failed to verify: "
524                         "no valid signatures for %d algorithms",
525                         (int)algo_needs_num_missing(&needs));
526                 algo_needs_reason(env, alg, reason, "no signatures");
527         } else {
528                 verbose(VERB_ALGO, "rrset failed to verify: "
529                         "no valid signatures");
530         }
531         return sec_status_bogus;
532 }
533
534 void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s)
535 {
536         char buf[256];
537         sldns_lookup_table *t = sldns_lookup_by_id(sldns_algorithms, alg);
538         if(t&&t->name)
539                 snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name);
540         else    snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s,
541                         (unsigned)alg);
542         *reason = regional_strdup(env->scratch, buf);
543         if(!*reason)
544                 *reason = s;
545 }
546
547 enum sec_status 
548 dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
549         struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
550         size_t dnskey_idx, char** reason)
551 {
552         enum sec_status sec;
553         size_t i, num, numchecked = 0;
554         rbtree_t* sortree = NULL;
555         int buf_canon = 0;
556         uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx);
557         int algo = dnskey_get_algo(dnskey, dnskey_idx);
558
559         num = rrset_get_sigcount(rrset);
560         if(num == 0) {
561                 verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
562                         "signatures");
563                 *reason = "no signatures";
564                 return sec_status_bogus;
565         }
566         for(i=0; i<num; i++) {
567                 /* see if sig matches keytag and algo */
568                 if(algo != rrset_get_sig_algo(rrset, i) ||
569                         tag != rrset_get_sig_keytag(rrset, i))
570                         continue;
571                 buf_canon = 0;
572                 sec = dnskey_verify_rrset_sig(env->scratch, 
573                         env->scratch_buffer, ve, *env->now, rrset, 
574                         dnskey, dnskey_idx, i, &sortree, &buf_canon, reason);
575                 if(sec == sec_status_secure)
576                         return sec;
577                 numchecked ++;
578         }
579         verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
580         if(!numchecked) *reason = "signature missing";
581         return sec_status_bogus;
582 }
583
584 enum sec_status 
585 dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, 
586         time_t now, struct ub_packed_rrset_key* rrset, 
587         struct ub_packed_rrset_key* dnskey, size_t sig_idx, 
588         struct rbtree_t** sortree, char** reason)
589 {
590         /* find matching keys and check them */
591         enum sec_status sec = sec_status_bogus;
592         uint16_t tag = rrset_get_sig_keytag(rrset, sig_idx);
593         int algo = rrset_get_sig_algo(rrset, sig_idx);
594         size_t i, num = rrset_get_count(dnskey);
595         size_t numchecked = 0;
596         int buf_canon = 0;
597         verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo);
598         if(!dnskey_algo_id_is_supported(algo)) {
599                 verbose(VERB_QUERY, "verify sig: unknown algorithm");
600                 return sec_status_insecure;
601         }
602         
603         for(i=0; i<num; i++) {
604                 /* see if key matches keytag and algo */
605                 if(algo != dnskey_get_algo(dnskey, i) ||
606                         tag != dnskey_calc_keytag(dnskey, i))
607                         continue;
608                 numchecked ++;
609
610                 /* see if key verifies */
611                 sec = dnskey_verify_rrset_sig(env->scratch, 
612                         env->scratch_buffer, ve, now, rrset, dnskey, i, 
613                         sig_idx, sortree, &buf_canon, reason);
614                 if(sec == sec_status_secure)
615                         return sec;
616         }
617         if(numchecked == 0) {
618                 *reason = "signatures from unknown keys";
619                 verbose(VERB_QUERY, "verify: could not find appropriate key");
620                 return sec_status_bogus;
621         }
622         return sec_status_bogus;
623 }
624
625 /**
626  * RR entries in a canonical sorted tree of RRs
627  */
628 struct canon_rr {
629         /** rbtree node, key is this structure */
630         rbnode_t node;
631         /** rrset the RR is in */
632         struct ub_packed_rrset_key* rrset;
633         /** which RR in the rrset */
634         size_t rr_idx;
635 };
636
637 /**
638  * Compare two RR for canonical order, in a field-style sweep.
639  * @param d: rrset data
640  * @param desc: ldns wireformat descriptor.
641  * @param i: first RR to compare
642  * @param j: first RR to compare
643  * @return comparison code.
644  */
645 static int
646 canonical_compare_byfield(struct packed_rrset_data* d, 
647         const sldns_rr_descriptor* desc, size_t i, size_t j)
648 {
649         /* sweep across rdata, keep track of some state:
650          *      which rr field, and bytes left in field.
651          *      current position in rdata, length left.
652          *      are we in a dname, length left in a label.
653          */
654         int wfi = -1;   /* current wireformat rdata field (rdf) */
655         int wfj = -1;
656         uint8_t* di = d->rr_data[i]+2; /* ptr to current rdata byte */
657         uint8_t* dj = d->rr_data[j]+2;
658         size_t ilen = d->rr_len[i]-2; /* length left in rdata */
659         size_t jlen = d->rr_len[j]-2;
660         int dname_i = 0;  /* true if these bytes are part of a name */
661         int dname_j = 0;
662         size_t lablen_i = 0; /* 0 for label length byte,for first byte of rdf*/
663         size_t lablen_j = 0; /* otherwise remaining length of rdf or label */
664         int dname_num_i = (int)desc->_dname_count; /* decreased at root label */
665         int dname_num_j = (int)desc->_dname_count;
666
667         /* loop while there are rdata bytes available for both rrs,
668          * and still some lowercasing needs to be done; either the dnames
669          * have not been reached yet, or they are currently being processed */
670         while(ilen > 0 && jlen > 0 && (dname_num_i > 0 || dname_num_j > 0)) {
671                 /* compare these two bytes */
672                 /* lowercase if in a dname and not a label length byte */
673                 if( ((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di)
674                  != ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj)
675                  ) {
676                   if(((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di)
677                   < ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj))
678                         return -1;
679                     return 1;
680                 }
681                 ilen--;
682                 jlen--;
683                 /* bytes are equal */
684
685                 /* advance field i */
686                 /* lablen 0 means that this byte is the first byte of the
687                  * next rdata field; inspect this rdata field and setup
688                  * to process the rest of this rdata field.
689                  * The reason to first read the byte, then setup the rdf,
690                  * is that we are then sure the byte is available and short
691                  * rdata is handled gracefully (even if it is a formerr). */
692                 if(lablen_i == 0) { 
693                         if(dname_i) {
694                                 /* scan this dname label */
695                                 /* capture length to lowercase */
696                                 lablen_i = (size_t)*di;
697                                 if(lablen_i == 0) {
698                                         /* end root label */
699                                         dname_i = 0;
700                                         dname_num_i--;
701                                         /* if dname num is 0, then the
702                                          * remainder is binary only */
703                                         if(dname_num_i == 0)
704                                                 lablen_i = ilen;
705                                 }
706                         } else {
707                                 /* scan this rdata field */
708                                 wfi++;
709                                 if(desc->_wireformat[wfi] 
710                                         == LDNS_RDF_TYPE_DNAME) {
711                                         dname_i = 1; 
712                                         lablen_i = (size_t)*di;
713                                         if(lablen_i == 0) {
714                                                 dname_i = 0;
715                                                 dname_num_i--;
716                                                 if(dname_num_i == 0)
717                                                         lablen_i = ilen;
718                                         }
719                                 } else if(desc->_wireformat[wfi] 
720                                         == LDNS_RDF_TYPE_STR)
721                                         lablen_i = (size_t)*di;
722                                 else    lablen_i = get_rdf_size(
723                                         desc->_wireformat[wfi]) - 1;
724                         }
725                 } else  lablen_i--;
726
727                 /* advance field j; same as for i */
728                 if(lablen_j == 0) { 
729                         if(dname_j) {
730                                 lablen_j = (size_t)*dj;
731                                 if(lablen_j == 0) {
732                                         dname_j = 0;
733                                         dname_num_j--;
734                                         if(dname_num_j == 0)
735                                                 lablen_j = jlen;
736                                 }
737                         } else {
738                                 wfj++;
739                                 if(desc->_wireformat[wfj] 
740                                         == LDNS_RDF_TYPE_DNAME) {
741                                         dname_j = 1; 
742                                         lablen_j = (size_t)*dj;
743                                         if(lablen_j == 0) {
744                                                 dname_j = 0;
745                                                 dname_num_j--;
746                                                 if(dname_num_j == 0)
747                                                         lablen_j = jlen;
748                                         }
749                                 } else if(desc->_wireformat[wfj] 
750                                         == LDNS_RDF_TYPE_STR)
751                                         lablen_j = (size_t)*dj;
752                                 else    lablen_j = get_rdf_size(
753                                         desc->_wireformat[wfj]) - 1;
754                         }
755                 } else  lablen_j--;
756                 di++;
757                 dj++;
758         }
759         /* end of the loop; because we advanced byte by byte; now we have
760          * that the rdata has ended, or that there is a binary remainder */
761         /* shortest first */
762         if(ilen == 0 && jlen == 0)
763                 return 0;
764         if(ilen == 0)
765                 return -1;
766         if(jlen == 0)
767                 return 1;
768         /* binary remainder, capture comparison in wfi variable */
769         if((wfi = memcmp(di, dj, (ilen<jlen)?ilen:jlen)) != 0)
770                 return wfi;
771         if(ilen < jlen)
772                 return -1;
773         if(jlen < ilen)
774                 return 1;
775         return 0;
776 }
777
778 /**
779  * Compare two RRs in the same RRset and determine their relative
780  * canonical order.
781  * @param rrset: the rrset in which to perform compares.
782  * @param i: first RR to compare
783  * @param j: first RR to compare
784  * @return 0 if RR i== RR j, -1 if <, +1 if >.
785  */
786 static int
787 canonical_compare(struct ub_packed_rrset_key* rrset, size_t i, size_t j)
788 {
789         struct packed_rrset_data* d = (struct packed_rrset_data*)
790                 rrset->entry.data;
791         const sldns_rr_descriptor* desc;
792         uint16_t type = ntohs(rrset->rk.type);
793         size_t minlen;
794         int c;
795
796         if(i==j)
797                 return 0;
798         /* in case rdata-len is to be compared for canonical order
799         c = memcmp(d->rr_data[i], d->rr_data[j], 2);
800         if(c != 0)
801                 return c; */
802
803         switch(type) {
804                 /* These RR types have only a name as RDATA. 
805                  * This name has to be canonicalized.*/
806                 case LDNS_RR_TYPE_NS:
807                 case LDNS_RR_TYPE_MD:
808                 case LDNS_RR_TYPE_MF:
809                 case LDNS_RR_TYPE_CNAME:
810                 case LDNS_RR_TYPE_MB:
811                 case LDNS_RR_TYPE_MG:
812                 case LDNS_RR_TYPE_MR:
813                 case LDNS_RR_TYPE_PTR:
814                 case LDNS_RR_TYPE_DNAME:
815                         /* the wireread function has already checked these
816                          * dname's for correctness, and this double checks */
817                         if(!dname_valid(d->rr_data[i]+2, d->rr_len[i]-2) ||
818                                 !dname_valid(d->rr_data[j]+2, d->rr_len[j]-2))
819                                 return 0;
820                         return query_dname_compare(d->rr_data[i]+2,
821                                 d->rr_data[j]+2);
822
823                 /* These RR types have STR and fixed size rdata fields
824                  * before one or more name fields that need canonicalizing,
825                  * and after that a byte-for byte remainder can be compared.
826                  */
827                 /* type starts with the name; remainder is binary compared */
828                 case LDNS_RR_TYPE_NXT: 
829                 /* use rdata field formats */
830                 case LDNS_RR_TYPE_MINFO:
831                 case LDNS_RR_TYPE_RP:
832                 case LDNS_RR_TYPE_SOA:
833                 case LDNS_RR_TYPE_RT:
834                 case LDNS_RR_TYPE_AFSDB:
835                 case LDNS_RR_TYPE_KX:
836                 case LDNS_RR_TYPE_MX:
837                 case LDNS_RR_TYPE_SIG:
838                 /* RRSIG signer name has to be downcased */
839                 case LDNS_RR_TYPE_RRSIG:
840                 case LDNS_RR_TYPE_PX:
841                 case LDNS_RR_TYPE_NAPTR:
842                 case LDNS_RR_TYPE_SRV:
843                         desc = sldns_rr_descript(type);
844                         log_assert(desc);
845                         /* this holds for the types that need canonicalizing */
846                         log_assert(desc->_minimum == desc->_maximum);
847                         return canonical_compare_byfield(d, desc, i, j);
848
849                 case LDNS_RR_TYPE_HINFO: /* no longer downcased */
850                 case LDNS_RR_TYPE_NSEC: 
851         default:
852                 /* For unknown RR types, or types not listed above,
853                  * no canonicalization is needed, do binary compare */
854                 /* byte for byte compare, equal means shortest first*/
855                 minlen = d->rr_len[i]-2;
856                 if(minlen > d->rr_len[j]-2)
857                         minlen = d->rr_len[j]-2;
858                 c = memcmp(d->rr_data[i]+2, d->rr_data[j]+2, minlen);
859                 if(c!=0)
860                         return c;
861                 /* rdata equal, shortest is first */
862                 if(d->rr_len[i] < d->rr_len[j])
863                         return -1;
864                 if(d->rr_len[i] > d->rr_len[j])
865                         return 1;
866                 /* rdata equal, length equal */
867                 break;
868         }
869         return 0;
870 }
871
872 int
873 canonical_tree_compare(const void* k1, const void* k2)
874 {
875         struct canon_rr* r1 = (struct canon_rr*)k1;
876         struct canon_rr* r2 = (struct canon_rr*)k2;
877         log_assert(r1->rrset == r2->rrset);
878         return canonical_compare(r1->rrset, r1->rr_idx, r2->rr_idx);
879 }
880
881 /**
882  * Sort RRs for rrset in canonical order.
883  * Does not actually canonicalize the RR rdatas.
884  * Does not touch rrsigs.
885  * @param rrset: to sort.
886  * @param d: rrset data.
887  * @param sortree: tree to sort into.
888  * @param rrs: rr storage.
889  */
890 static void
891 canonical_sort(struct ub_packed_rrset_key* rrset, struct packed_rrset_data* d,
892         rbtree_t* sortree, struct canon_rr* rrs)
893 {
894         size_t i;
895         /* insert into rbtree to sort and detect duplicates */
896         for(i=0; i<d->count; i++) {
897                 rrs[i].node.key = &rrs[i];
898                 rrs[i].rrset = rrset;
899                 rrs[i].rr_idx = i;
900                 if(!rbtree_insert(sortree, &rrs[i].node)) {
901                         /* this was a duplicate */
902                 }
903         }
904 }
905
906 /**
907  * Inser canonical owner name into buffer.
908  * @param buf: buffer to insert into at current position.
909  * @param k: rrset with its owner name.
910  * @param sig: signature with signer name and label count.
911  *      must be length checked, at least 18 bytes long.
912  * @param can_owner: position in buffer returned for future use.
913  * @param can_owner_len: length of canonical owner name.
914  */
915 static void
916 insert_can_owner(sldns_buffer* buf, struct ub_packed_rrset_key* k,
917         uint8_t* sig, uint8_t** can_owner, size_t* can_owner_len)
918 {
919         int rrsig_labels = (int)sig[3];
920         int fqdn_labels = dname_signame_label_count(k->rk.dname);
921         *can_owner = sldns_buffer_current(buf);
922         if(rrsig_labels == fqdn_labels) {
923                 /* no change */
924                 sldns_buffer_write(buf, k->rk.dname, k->rk.dname_len);
925                 query_dname_tolower(*can_owner);
926                 *can_owner_len = k->rk.dname_len;
927                 return;
928         }
929         log_assert(rrsig_labels < fqdn_labels);
930         /* *. | fqdn(rightmost rrsig_labels) */
931         if(rrsig_labels < fqdn_labels) {
932                 int i;
933                 uint8_t* nm = k->rk.dname;
934                 size_t len = k->rk.dname_len;
935                 /* so skip fqdn_labels-rrsig_labels */
936                 for(i=0; i<fqdn_labels-rrsig_labels; i++) {
937                         dname_remove_label(&nm, &len);  
938                 }
939                 *can_owner_len = len+2;
940                 sldns_buffer_write(buf, (uint8_t*)"\001*", 2);
941                 sldns_buffer_write(buf, nm, len);
942                 query_dname_tolower(*can_owner);
943         }
944 }
945
946 /**
947  * Canonicalize Rdata in buffer.
948  * @param buf: buffer at position just after the rdata.
949  * @param rrset: rrset with type.
950  * @param len: length of the rdata (including rdatalen uint16).
951  */
952 static void
953 canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
954         size_t len)
955 {
956         uint8_t* datstart = sldns_buffer_current(buf)-len+2;
957         switch(ntohs(rrset->rk.type)) {
958                 case LDNS_RR_TYPE_NXT: 
959                 case LDNS_RR_TYPE_NS:
960                 case LDNS_RR_TYPE_MD:
961                 case LDNS_RR_TYPE_MF:
962                 case LDNS_RR_TYPE_CNAME:
963                 case LDNS_RR_TYPE_MB:
964                 case LDNS_RR_TYPE_MG:
965                 case LDNS_RR_TYPE_MR:
966                 case LDNS_RR_TYPE_PTR:
967                 case LDNS_RR_TYPE_DNAME:
968                         /* type only has a single argument, the name */
969                         query_dname_tolower(datstart);
970                         return;
971                 case LDNS_RR_TYPE_MINFO:
972                 case LDNS_RR_TYPE_RP:
973                 case LDNS_RR_TYPE_SOA:
974                         /* two names after another */
975                         query_dname_tolower(datstart);
976                         query_dname_tolower(datstart + 
977                                 dname_valid(datstart, len-2));
978                         return;
979                 case LDNS_RR_TYPE_RT:
980                 case LDNS_RR_TYPE_AFSDB:
981                 case LDNS_RR_TYPE_KX:
982                 case LDNS_RR_TYPE_MX:
983                         /* skip fixed part */
984                         if(len < 2+2+1) /* rdlen, skiplen, 1byteroot */
985                                 return;
986                         datstart += 2;
987                         query_dname_tolower(datstart);
988                         return;
989                 case LDNS_RR_TYPE_SIG:
990                 /* downcase the RRSIG, compat with BIND (kept it from SIG) */
991                 case LDNS_RR_TYPE_RRSIG:
992                         /* skip fixed part */
993                         if(len < 2+18+1)
994                                 return;
995                         datstart += 18;
996                         query_dname_tolower(datstart);
997                         return;
998                 case LDNS_RR_TYPE_PX:
999                         /* skip, then two names after another */
1000                         if(len < 2+2+1) 
1001                                 return;
1002                         datstart += 2;
1003                         query_dname_tolower(datstart);
1004                         query_dname_tolower(datstart + 
1005                                 dname_valid(datstart, len-2-2));
1006                         return;
1007                 case LDNS_RR_TYPE_NAPTR:
1008                         if(len < 2+4)
1009                                 return;
1010                         len -= 2+4;
1011                         datstart += 4;
1012                         if(len < (size_t)datstart[0]+1) /* skip text field */
1013                                 return;
1014                         len -= (size_t)datstart[0]+1;
1015                         datstart += (size_t)datstart[0]+1;
1016                         if(len < (size_t)datstart[0]+1) /* skip text field */
1017                                 return;
1018                         len -= (size_t)datstart[0]+1;
1019                         datstart += (size_t)datstart[0]+1;
1020                         if(len < (size_t)datstart[0]+1) /* skip text field */
1021                                 return;
1022                         len -= (size_t)datstart[0]+1;
1023                         datstart += (size_t)datstart[0]+1;
1024                         if(len < 1)     /* check name is at least 1 byte*/
1025                                 return;
1026                         query_dname_tolower(datstart);
1027                         return;
1028                 case LDNS_RR_TYPE_SRV:
1029                         /* skip fixed part */
1030                         if(len < 2+6+1)
1031                                 return;
1032                         datstart += 6;
1033                         query_dname_tolower(datstart);
1034                         return;
1035
1036                 /* do not canonicalize NSEC rdata name, compat with 
1037                  * from bind 9.4 signer, where it does not do so */
1038                 case LDNS_RR_TYPE_NSEC: /* type starts with the name */
1039                 case LDNS_RR_TYPE_HINFO: /* not downcased */
1040                 /* A6 not supported */
1041                 default:        
1042                         /* nothing to do for unknown types */
1043                         return;
1044         }
1045 }
1046
1047 int rrset_canonical_equal(struct regional* region,
1048         struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2)
1049 {
1050         struct rbtree_t sortree1, sortree2;
1051         struct canon_rr *rrs1, *rrs2, *p1, *p2;
1052         struct packed_rrset_data* d1=(struct packed_rrset_data*)k1->entry.data;
1053         struct packed_rrset_data* d2=(struct packed_rrset_data*)k2->entry.data;
1054         struct ub_packed_rrset_key fk;
1055         struct packed_rrset_data fd;
1056         size_t flen[2];
1057         uint8_t* fdata[2];
1058
1059         /* basic compare */
1060         if(k1->rk.dname_len != k2->rk.dname_len ||
1061                 k1->rk.flags != k2->rk.flags ||
1062                 k1->rk.type != k2->rk.type ||
1063                 k1->rk.rrset_class != k2->rk.rrset_class ||
1064                 query_dname_compare(k1->rk.dname, k2->rk.dname) != 0)
1065                 return 0;
1066         if(d1->ttl != d2->ttl ||
1067                 d1->count != d2->count ||
1068                 d1->rrsig_count != d2->rrsig_count ||
1069                 d1->trust != d2->trust ||
1070                 d1->security != d2->security)
1071                 return 0;
1072
1073         /* init */
1074         memset(&fk, 0, sizeof(fk));
1075         memset(&fd, 0, sizeof(fd));
1076         fk.entry.data = &fd;
1077         fd.count = 2;
1078         fd.rr_len = flen;
1079         fd.rr_data = fdata;
1080         rbtree_init(&sortree1, &canonical_tree_compare);
1081         rbtree_init(&sortree2, &canonical_tree_compare);
1082         rrs1 = regional_alloc(region, sizeof(struct canon_rr)*d1->count);
1083         rrs2 = regional_alloc(region, sizeof(struct canon_rr)*d2->count);
1084         if(!rrs1 || !rrs2) return 1; /* alloc failure */
1085
1086         /* sort */
1087         canonical_sort(k1, d1, &sortree1, rrs1);
1088         canonical_sort(k2, d2, &sortree2, rrs2);
1089
1090         /* compare canonical-sorted RRs for canonical-equality */
1091         if(sortree1.count != sortree2.count)
1092                 return 0;
1093         p1 = (struct canon_rr*)rbtree_first(&sortree1);
1094         p2 = (struct canon_rr*)rbtree_first(&sortree2);
1095         while(p1 != (struct canon_rr*)RBTREE_NULL &&
1096                 p2 != (struct canon_rr*)RBTREE_NULL) {
1097                 flen[0] = d1->rr_len[p1->rr_idx];
1098                 flen[1] = d2->rr_len[p2->rr_idx];
1099                 fdata[0] = d1->rr_data[p1->rr_idx];
1100                 fdata[1] = d2->rr_data[p2->rr_idx];
1101
1102                 if(canonical_compare(&fk, 0, 1) != 0)
1103                         return 0;
1104                 p1 = (struct canon_rr*)rbtree_next(&p1->node);
1105                 p2 = (struct canon_rr*)rbtree_next(&p2->node);
1106         }
1107         return 1;
1108 }
1109
1110 /**
1111  * Create canonical form of rrset in the scratch buffer.
1112  * @param region: temporary region.
1113  * @param buf: the buffer to use.
1114  * @param k: the rrset to insert.
1115  * @param sig: RRSIG rdata to include.
1116  * @param siglen: RRSIG rdata len excluding signature field, but inclusive
1117  *      signer name length.
1118  * @param sortree: if NULL is passed a new sorted rrset tree is built.
1119  *      Otherwise it is reused.
1120  * @return false on alloc error.
1121  */
1122 static int
1123 rrset_canonical(struct regional* region, sldns_buffer* buf, 
1124         struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen,
1125         struct rbtree_t** sortree)
1126 {
1127         struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
1128         uint8_t* can_owner = NULL;
1129         size_t can_owner_len = 0;
1130         struct canon_rr* walk;
1131         struct canon_rr* rrs;
1132
1133         if(!*sortree) {
1134                 *sortree = (struct rbtree_t*)regional_alloc(region, 
1135                         sizeof(rbtree_t));
1136                 if(!*sortree)
1137                         return 0;
1138                 rrs = regional_alloc(region, sizeof(struct canon_rr)*d->count);
1139                 if(!rrs) {
1140                         *sortree = NULL;
1141                         return 0;
1142                 }
1143                 rbtree_init(*sortree, &canonical_tree_compare);
1144                 canonical_sort(k, d, *sortree, rrs);
1145         }
1146
1147         sldns_buffer_clear(buf);
1148         sldns_buffer_write(buf, sig, siglen);
1149         /* canonicalize signer name */
1150         query_dname_tolower(sldns_buffer_begin(buf)+18); 
1151         RBTREE_FOR(walk, struct canon_rr*, (*sortree)) {
1152                 /* see if there is enough space left in the buffer */
1153                 if(sldns_buffer_remaining(buf) < can_owner_len + 2 + 2 + 4
1154                         + d->rr_len[walk->rr_idx]) {
1155                         log_err("verify: failed to canonicalize, "
1156                                 "rrset too big");
1157                         return 0;
1158                 }
1159                 /* determine canonical owner name */
1160                 if(can_owner)
1161                         sldns_buffer_write(buf, can_owner, can_owner_len);
1162                 else    insert_can_owner(buf, k, sig, &can_owner, 
1163                                 &can_owner_len);
1164                 sldns_buffer_write(buf, &k->rk.type, 2);
1165                 sldns_buffer_write(buf, &k->rk.rrset_class, 2);
1166                 sldns_buffer_write(buf, sig+4, 4);
1167                 sldns_buffer_write(buf, d->rr_data[walk->rr_idx], 
1168                         d->rr_len[walk->rr_idx]);
1169                 canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]);
1170         }
1171         sldns_buffer_flip(buf);
1172         return 1;
1173 }
1174
1175 /** pretty print rrsig error with dates */
1176 static void
1177 sigdate_error(const char* str, int32_t expi, int32_t incep, int32_t now)
1178 {
1179         struct tm tm;
1180         char expi_buf[16];
1181         char incep_buf[16];
1182         char now_buf[16];
1183         time_t te, ti, tn;
1184
1185         if(verbosity < VERB_QUERY)
1186                 return;
1187         te = (time_t)expi;
1188         ti = (time_t)incep;
1189         tn = (time_t)now;
1190         memset(&tm, 0, sizeof(tm));
1191         if(gmtime_r(&te, &tm) && strftime(expi_buf, 15, "%Y%m%d%H%M%S", &tm)
1192          &&gmtime_r(&ti, &tm) && strftime(incep_buf, 15, "%Y%m%d%H%M%S", &tm)
1193          &&gmtime_r(&tn, &tm) && strftime(now_buf, 15, "%Y%m%d%H%M%S", &tm)) {
1194                 log_info("%s expi=%s incep=%s now=%s", str, expi_buf, 
1195                         incep_buf, now_buf);
1196         } else
1197                 log_info("%s expi=%u incep=%u now=%u", str, (unsigned)expi, 
1198                         (unsigned)incep, (unsigned)now);
1199 }
1200
1201 /** check rrsig dates */
1202 static int
1203 check_dates(struct val_env* ve, uint32_t unow,
1204         uint8_t* expi_p, uint8_t* incep_p, char** reason)
1205 {
1206         /* read out the dates */
1207         int32_t expi, incep, now;
1208         memmove(&expi, expi_p, sizeof(expi));
1209         memmove(&incep, incep_p, sizeof(incep));
1210         expi = ntohl(expi);
1211         incep = ntohl(incep);
1212
1213         /* get current date */
1214         if(ve->date_override) {
1215                 if(ve->date_override == -1) {
1216                         verbose(VERB_ALGO, "date override: ignore date"); 
1217                         return 1;
1218                 }
1219                 now = ve->date_override;
1220                 verbose(VERB_ALGO, "date override option %d", (int)now); 
1221         } else  now = (int32_t)unow;
1222
1223         /* check them */
1224         if(incep - expi > 0) {
1225                 sigdate_error("verify: inception after expiration, "
1226                         "signature bad", expi, incep, now);
1227                 *reason = "signature inception after expiration";
1228                 return 0;
1229         }
1230         if(incep - now > 0) {
1231                 /* within skew ? (calc here to avoid calculation normally) */
1232                 int32_t skew = (expi-incep)/10;
1233                 if(skew < ve->skew_min) skew = ve->skew_min;
1234                 if(skew > ve->skew_max) skew = ve->skew_max;
1235                 if(incep - now > skew) {
1236                         sigdate_error("verify: signature bad, current time is"
1237                                 " before inception date", expi, incep, now);
1238                         *reason = "signature before inception date";
1239                         return 0;
1240                 }
1241                 sigdate_error("verify warning suspicious signature inception "
1242                         " or bad local clock", expi, incep, now);
1243         }
1244         if(now - expi > 0) {
1245                 int32_t skew = (expi-incep)/10;
1246                 if(skew < ve->skew_min) skew = ve->skew_min;
1247                 if(skew > ve->skew_max) skew = ve->skew_max;
1248                 if(now - expi > skew) {
1249                         sigdate_error("verify: signature expired", expi, 
1250                                 incep, now);
1251                         *reason = "signature expired";
1252                         return 0;
1253                 }
1254                 sigdate_error("verify warning suspicious signature expiration "
1255                         " or bad local clock", expi, incep, now);
1256         }
1257         return 1;
1258 }
1259
1260 /** adjust rrset TTL for verified rrset, compare to original TTL and expi */
1261 static void
1262 adjust_ttl(struct val_env* ve, uint32_t unow, 
1263         struct ub_packed_rrset_key* rrset, uint8_t* orig_p, 
1264         uint8_t* expi_p, uint8_t* incep_p)
1265 {
1266         struct packed_rrset_data* d = 
1267                 (struct packed_rrset_data*)rrset->entry.data;
1268         /* read out the dates */
1269         int32_t origttl, expittl, expi, incep, now;
1270         memmove(&origttl, orig_p, sizeof(origttl));
1271         memmove(&expi, expi_p, sizeof(expi));
1272         memmove(&incep, incep_p, sizeof(incep));
1273         expi = ntohl(expi);
1274         incep = ntohl(incep);
1275         origttl = ntohl(origttl);
1276
1277         /* get current date */
1278         if(ve->date_override) {
1279                 now = ve->date_override;
1280         } else  now = (int32_t)unow;
1281         expittl = expi - now;
1282
1283         /* so now:
1284          * d->ttl: rrset ttl read from message or cache. May be reduced
1285          * origttl: original TTL from signature, authoritative TTL max.
1286          * expittl: TTL until the signature expires.
1287          *
1288          * Use the smallest of these.
1289          */
1290         if(d->ttl > (time_t)origttl) {
1291                 verbose(VERB_QUERY, "rrset TTL larger than original TTL,"
1292                         " adjusting TTL downwards");
1293                 d->ttl = origttl;
1294         }
1295         if(expittl > 0 && d->ttl > (time_t)expittl) {
1296                 verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl,"
1297                         " adjusting TTL downwards");
1298                 d->ttl = expittl;
1299         }
1300 }
1301
1302 enum sec_status 
1303 dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf, 
1304         struct val_env* ve, time_t now,
1305         struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
1306         size_t dnskey_idx, size_t sig_idx,
1307         struct rbtree_t** sortree, int* buf_canon, char** reason)
1308 {
1309         enum sec_status sec;
1310         uint8_t* sig;           /* RRSIG rdata */
1311         size_t siglen;
1312         size_t rrnum = rrset_get_count(rrset);
1313         uint8_t* signer;        /* rrsig signer name */
1314         size_t signer_len;
1315         unsigned char* sigblock; /* signature rdata field */
1316         unsigned int sigblock_len;
1317         uint16_t ktag;          /* DNSKEY key tag */
1318         unsigned char* key;     /* public key rdata field */
1319         unsigned int keylen;
1320         rrset_get_rdata(rrset, rrnum + sig_idx, &sig, &siglen);
1321         /* min length of rdatalen, fixed rrsig, root signer, 1 byte sig */
1322         if(siglen < 2+20) {
1323                 verbose(VERB_QUERY, "verify: signature too short");
1324                 *reason = "signature too short";
1325                 return sec_status_bogus;
1326         }
1327
1328         if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
1329                 verbose(VERB_QUERY, "verify: dnskey without ZSK flag");
1330                 *reason = "dnskey without ZSK flag";
1331                 return sec_status_bogus; 
1332         }
1333
1334         if(dnskey_get_protocol(dnskey, dnskey_idx) != LDNS_DNSSEC_KEYPROTO) { 
1335                 /* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */
1336                 verbose(VERB_QUERY, "verify: dnskey has wrong key protocol");
1337                 *reason = "dnskey has wrong protocolnumber";
1338                 return sec_status_bogus;
1339         }
1340
1341         /* verify as many fields in rrsig as possible */
1342         signer = sig+2+18;
1343         signer_len = dname_valid(signer, siglen-2-18);
1344         if(!signer_len) {
1345                 verbose(VERB_QUERY, "verify: malformed signer name");
1346                 *reason = "signer name malformed";
1347                 return sec_status_bogus; /* signer name invalid */
1348         }
1349         if(!dname_subdomain_c(rrset->rk.dname, signer)) {
1350                 verbose(VERB_QUERY, "verify: signer name is off-tree");
1351                 *reason = "signer name off-tree";
1352                 return sec_status_bogus; /* signer name offtree */
1353         }
1354         sigblock = (unsigned char*)signer+signer_len;
1355         if(siglen < 2+18+signer_len+1) {
1356                 verbose(VERB_QUERY, "verify: too short, no signature data");
1357                 *reason = "signature too short, no signature data";
1358                 return sec_status_bogus; /* sig rdf is < 1 byte */
1359         }
1360         sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len);
1361
1362         /* verify key dname == sig signer name */
1363         if(query_dname_compare(signer, dnskey->rk.dname) != 0) {
1364                 verbose(VERB_QUERY, "verify: wrong key for rrsig");
1365                 log_nametypeclass(VERB_QUERY, "RRSIG signername is", 
1366                         signer, 0, 0);
1367                 log_nametypeclass(VERB_QUERY, "the key name is", 
1368                         dnskey->rk.dname, 0, 0);
1369                 *reason = "signer name mismatches key name";
1370                 return sec_status_bogus;
1371         }
1372
1373         /* verify covered type */
1374         /* memcmp works because type is in network format for rrset */
1375         if(memcmp(sig+2, &rrset->rk.type, 2) != 0) {
1376                 verbose(VERB_QUERY, "verify: wrong type covered");
1377                 *reason = "signature covers wrong type";
1378                 return sec_status_bogus;
1379         }
1380         /* verify keytag and sig algo (possibly again) */
1381         if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) {
1382                 verbose(VERB_QUERY, "verify: wrong algorithm");
1383                 *reason = "signature has wrong algorithm";
1384                 return sec_status_bogus;
1385         }
1386         ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx));
1387         if(memcmp(sig+2+16, &ktag, 2) != 0) {
1388                 verbose(VERB_QUERY, "verify: wrong keytag");
1389                 *reason = "signature has wrong keytag";
1390                 return sec_status_bogus;
1391         }
1392
1393         /* verify labels is in a valid range */
1394         if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) {
1395                 verbose(VERB_QUERY, "verify: labelcount out of range");
1396                 *reason = "signature labelcount out of range";
1397                 return sec_status_bogus;
1398         }
1399
1400         /* original ttl, always ok */
1401
1402         if(!*buf_canon) {
1403                 /* create rrset canonical format in buffer, ready for 
1404                  * signature */
1405                 if(!rrset_canonical(region, buf, rrset, sig+2, 
1406                         18 + signer_len, sortree)) {
1407                         log_err("verify: failed due to alloc error");
1408                         return sec_status_unchecked;
1409                 }
1410                 *buf_canon = 1;
1411         }
1412
1413         /* check that dnskey is available */
1414         dnskey_get_pubkey(dnskey, dnskey_idx, &key, &keylen);
1415         if(!key) {
1416                 verbose(VERB_QUERY, "verify: short DNSKEY RR");
1417                 return sec_status_unchecked;
1418         }
1419
1420         /* verify */
1421         sec = verify_canonrrset(buf, (int)sig[2+2],
1422                 sigblock, sigblock_len, key, keylen, reason);
1423         
1424         if(sec == sec_status_secure) {
1425                 /* check if TTL is too high - reduce if so */
1426                 adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12);
1427
1428                 /* verify inception, expiration dates 
1429                  * Do this last so that if you ignore expired-sigs the
1430                  * rest is sure to be OK. */
1431                 if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) {
1432                         return sec_status_bogus;
1433                 }
1434         }
1435
1436         return sec;
1437 }