13b6c3722Schristos /*
23b6c3722Schristos * testcode/unitverify.c - unit test for signature verification routines.
33b6c3722Schristos *
43b6c3722Schristos * Copyright (c) 2007, NLnet Labs. All rights reserved.
53b6c3722Schristos *
63b6c3722Schristos * This software is open source.
73b6c3722Schristos *
83b6c3722Schristos * Redistribution and use in source and binary forms, with or without
93b6c3722Schristos * modification, are permitted provided that the following conditions
103b6c3722Schristos * are met:
113b6c3722Schristos *
123b6c3722Schristos * Redistributions of source code must retain the above copyright notice,
133b6c3722Schristos * this list of conditions and the following disclaimer.
143b6c3722Schristos *
153b6c3722Schristos * Redistributions in binary form must reproduce the above copyright notice,
163b6c3722Schristos * this list of conditions and the following disclaimer in the documentation
173b6c3722Schristos * and/or other materials provided with the distribution.
183b6c3722Schristos *
193b6c3722Schristos * Neither the name of the NLNET LABS nor the names of its contributors may
203b6c3722Schristos * be used to endorse or promote products derived from this software without
213b6c3722Schristos * specific prior written permission.
223b6c3722Schristos *
233b6c3722Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
243b6c3722Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
253b6c3722Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
263b6c3722Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
273b6c3722Schristos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
283b6c3722Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
293b6c3722Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
303b6c3722Schristos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
313b6c3722Schristos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
323b6c3722Schristos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
333b6c3722Schristos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343b6c3722Schristos *
353b6c3722Schristos */
363b6c3722Schristos /**
373b6c3722Schristos * \file
383b6c3722Schristos * Calls verification unit tests. Exits with code 1 on a failure.
393b6c3722Schristos */
403b6c3722Schristos
413b6c3722Schristos #include "config.h"
423b6c3722Schristos #include "util/log.h"
433b6c3722Schristos #include "testcode/unitmain.h"
443b6c3722Schristos #include "validator/val_sigcrypt.h"
453b6c3722Schristos #include "validator/val_secalgo.h"
463b6c3722Schristos #include "validator/val_nsec.h"
473b6c3722Schristos #include "validator/val_nsec3.h"
483b6c3722Schristos #include "validator/validator.h"
493b6c3722Schristos #include "testcode/testpkts.h"
503b6c3722Schristos #include "util/data/msgreply.h"
513b6c3722Schristos #include "util/data/msgparse.h"
523b6c3722Schristos #include "util/data/dname.h"
533b6c3722Schristos #include "util/regional.h"
543b6c3722Schristos #include "util/alloc.h"
553b6c3722Schristos #include "util/rbtree.h"
563b6c3722Schristos #include "util/net_help.h"
573b6c3722Schristos #include "util/module.h"
583b6c3722Schristos #include "util/config_file.h"
593b6c3722Schristos #include "sldns/sbuffer.h"
603b6c3722Schristos #include "sldns/keyraw.h"
613b6c3722Schristos #include "sldns/str2wire.h"
623b6c3722Schristos #include "sldns/wire2str.h"
633b6c3722Schristos
643b6c3722Schristos /** verbose signature test */
653b6c3722Schristos static int vsig = 0;
663b6c3722Schristos
673b6c3722Schristos /** entry to packet buffer with wireformat */
683b6c3722Schristos static void
entry_to_buf(struct entry * e,sldns_buffer * pkt)693b6c3722Schristos entry_to_buf(struct entry* e, sldns_buffer* pkt)
703b6c3722Schristos {
713b6c3722Schristos unit_assert(e->reply_list);
723b6c3722Schristos if(e->reply_list->reply_from_hex) {
733b6c3722Schristos sldns_buffer_copy(pkt, e->reply_list->reply_from_hex);
743b6c3722Schristos } else {
753b6c3722Schristos sldns_buffer_clear(pkt);
763b6c3722Schristos sldns_buffer_write(pkt, e->reply_list->reply_pkt,
773b6c3722Schristos e->reply_list->reply_len);
783b6c3722Schristos sldns_buffer_flip(pkt);
793b6c3722Schristos }
803b6c3722Schristos }
813b6c3722Schristos
823b6c3722Schristos /** entry to reply info conversion */
833b6c3722Schristos static void
entry_to_repinfo(struct entry * e,struct alloc_cache * alloc,struct regional * region,sldns_buffer * pkt,struct query_info * qi,struct reply_info ** rep)843b6c3722Schristos entry_to_repinfo(struct entry* e, struct alloc_cache* alloc,
853b6c3722Schristos struct regional* region, sldns_buffer* pkt, struct query_info* qi,
863b6c3722Schristos struct reply_info** rep)
873b6c3722Schristos {
883b6c3722Schristos int ret;
893b6c3722Schristos struct edns_data edns;
903b6c3722Schristos entry_to_buf(e, pkt);
913b6c3722Schristos /* lock alloc lock to please lock checking software.
923b6c3722Schristos * alloc_special_obtain assumes it is talking to a ub-alloc,
933b6c3722Schristos * and does not need to perform locking. Here the alloc is
943b6c3722Schristos * the only one, so we lock it here */
953b6c3722Schristos lock_quick_lock(&alloc->lock);
963b6c3722Schristos ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns);
973b6c3722Schristos lock_quick_unlock(&alloc->lock);
983b6c3722Schristos if(ret != 0) {
993b6c3722Schristos char rcode[16];
1003b6c3722Schristos sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode));
1013b6c3722Schristos printf("parse code %d: %s\n", ret, rcode);
1023b6c3722Schristos unit_assert(ret != 0);
1033b6c3722Schristos }
1043b6c3722Schristos }
1053b6c3722Schristos
1063b6c3722Schristos /** extract DNSKEY rrset from answer and convert it */
1073b6c3722Schristos static struct ub_packed_rrset_key*
extract_keys(struct entry * e,struct alloc_cache * alloc,struct regional * region,sldns_buffer * pkt)1083b6c3722Schristos extract_keys(struct entry* e, struct alloc_cache* alloc,
1093b6c3722Schristos struct regional* region, sldns_buffer* pkt)
1103b6c3722Schristos {
1113b6c3722Schristos struct ub_packed_rrset_key* dnskey = NULL;
1123b6c3722Schristos struct query_info qinfo;
1133b6c3722Schristos struct reply_info* rep = NULL;
1143b6c3722Schristos size_t i;
1153b6c3722Schristos
1163b6c3722Schristos entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
1173b6c3722Schristos for(i=0; i<rep->an_numrrsets; i++) {
1183b6c3722Schristos if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) {
1193b6c3722Schristos dnskey = rep->rrsets[i];
1203b6c3722Schristos rep->rrsets[i] = NULL;
1213b6c3722Schristos break;
1223b6c3722Schristos }
1233b6c3722Schristos }
1243b6c3722Schristos unit_assert(dnskey);
1253b6c3722Schristos
1263b6c3722Schristos reply_info_parsedelete(rep, alloc);
1273b6c3722Schristos query_info_clear(&qinfo);
1283b6c3722Schristos return dnskey;
1293b6c3722Schristos }
1303b6c3722Schristos
1313b6c3722Schristos /** return true if answer should be bogus */
1323b6c3722Schristos static int
should_be_bogus(struct ub_packed_rrset_key * rrset,struct query_info * qinfo)1333b6c3722Schristos should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo)
1343b6c3722Schristos {
1353b6c3722Schristos struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
1363b6c3722Schristos entry.data;
1373b6c3722Schristos if(d->rrsig_count == 0)
1383b6c3722Schristos return 1;
1393b6c3722Schristos /* name 'bogus' as first label signals bogus */
1403b6c3722Schristos if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0)
1413b6c3722Schristos return 1;
1423b6c3722Schristos if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0)
1433b6c3722Schristos return 1;
1443b6c3722Schristos return 0;
1453b6c3722Schristos }
1463b6c3722Schristos
1473b6c3722Schristos /** return number of rrs in an rrset */
1483b6c3722Schristos static size_t
rrset_get_count(struct ub_packed_rrset_key * rrset)1493b6c3722Schristos rrset_get_count(struct ub_packed_rrset_key* rrset)
1503b6c3722Schristos {
1513b6c3722Schristos struct packed_rrset_data* d = (struct packed_rrset_data*)
1523b6c3722Schristos rrset->entry.data;
1533b6c3722Schristos if(!d) return 0;
1543b6c3722Schristos return d->count;
1553b6c3722Schristos }
1563b6c3722Schristos
1573b6c3722Schristos /** setup sig alg list from dnskey */
1583b6c3722Schristos static void
setup_sigalg(struct ub_packed_rrset_key * dnskey,uint8_t * sigalg)1593b6c3722Schristos setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
1603b6c3722Schristos {
1613b6c3722Schristos uint8_t a[ALGO_NEEDS_MAX];
1623b6c3722Schristos size_t i, n = 0;
1633b6c3722Schristos memset(a, 0, sizeof(a));
1643b6c3722Schristos for(i=0; i<rrset_get_count(dnskey); i++) {
1653b6c3722Schristos uint8_t algo = (uint8_t)dnskey_get_algo(dnskey, i);
1663b6c3722Schristos if(a[algo] == 0) {
1673b6c3722Schristos a[algo] = 1;
1683b6c3722Schristos sigalg[n++] = algo;
1693b6c3722Schristos }
1703b6c3722Schristos }
1713b6c3722Schristos sigalg[n] = 0;
1723b6c3722Schristos }
1733b6c3722Schristos
1743b6c3722Schristos /** verify and test one rrset against the key rrset */
1753b6c3722Schristos static void
verifytest_rrset(struct module_env * env,struct val_env * ve,struct ub_packed_rrset_key * rrset,struct ub_packed_rrset_key * dnskey,struct query_info * qinfo)1763b6c3722Schristos verifytest_rrset(struct module_env* env, struct val_env* ve,
1773b6c3722Schristos struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
1783b6c3722Schristos struct query_info* qinfo)
1793b6c3722Schristos {
1803b6c3722Schristos enum sec_status sec;
1813b6c3722Schristos char* reason = NULL;
1823b6c3722Schristos uint8_t sigalg[ALGO_NEEDS_MAX+1];
183*91f7d55fSchristos int verified = 0;
1843b6c3722Schristos if(vsig) {
1853b6c3722Schristos log_nametypeclass(VERB_QUERY, "verify of rrset",
1863b6c3722Schristos rrset->rk.dname, ntohs(rrset->rk.type),
1873b6c3722Schristos ntohs(rrset->rk.rrset_class));
1883b6c3722Schristos }
1893b6c3722Schristos setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
1900cd9f4ecSchristos /* ok to give null as qstate here, won't be used for answer section. */
1917a540f2bSchristos sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, NULL,
192*91f7d55fSchristos LDNS_SECTION_ANSWER, NULL, &verified);
1933b6c3722Schristos if(vsig) {
1943b6c3722Schristos printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
1953b6c3722Schristos reason?reason:"");
1963b6c3722Schristos }
1973b6c3722Schristos if(should_be_bogus(rrset, qinfo)) {
1983b6c3722Schristos unit_assert(sec == sec_status_bogus);
1993b6c3722Schristos } else {
2003b6c3722Schristos unit_assert(sec == sec_status_secure);
2013b6c3722Schristos }
2023b6c3722Schristos }
2033b6c3722Schristos
2043b6c3722Schristos /** verify and test an entry - every rr in the message */
2053b6c3722Schristos static void
verifytest_entry(struct entry * e,struct alloc_cache * alloc,struct regional * region,sldns_buffer * pkt,struct ub_packed_rrset_key * dnskey,struct module_env * env,struct val_env * ve)2063b6c3722Schristos verifytest_entry(struct entry* e, struct alloc_cache* alloc,
2073b6c3722Schristos struct regional* region, sldns_buffer* pkt,
2083b6c3722Schristos struct ub_packed_rrset_key* dnskey, struct module_env* env,
2093b6c3722Schristos struct val_env* ve)
2103b6c3722Schristos {
2113b6c3722Schristos struct query_info qinfo;
2123b6c3722Schristos struct reply_info* rep = NULL;
2133b6c3722Schristos size_t i;
2143b6c3722Schristos
2153b6c3722Schristos regional_free_all(region);
2163b6c3722Schristos if(vsig) {
2173b6c3722Schristos char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
2183b6c3722Schristos e->reply_list->reply_len);
2193b6c3722Schristos printf("verifying pkt:\n%s\n", s?s:"outofmemory");
2203b6c3722Schristos free(s);
2213b6c3722Schristos }
2223b6c3722Schristos entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
2233b6c3722Schristos
2243b6c3722Schristos for(i=0; i<rep->rrset_count; i++) {
2253b6c3722Schristos verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo);
2263b6c3722Schristos }
2273b6c3722Schristos
2283b6c3722Schristos reply_info_parsedelete(rep, alloc);
2293b6c3722Schristos query_info_clear(&qinfo);
2303b6c3722Schristos }
2313b6c3722Schristos
2323b6c3722Schristos /** find RRset in reply by type */
2333b6c3722Schristos static struct ub_packed_rrset_key*
find_rrset_type(struct reply_info * rep,uint16_t type)2343b6c3722Schristos find_rrset_type(struct reply_info* rep, uint16_t type)
2353b6c3722Schristos {
2363b6c3722Schristos size_t i;
2373b6c3722Schristos for(i=0; i<rep->rrset_count; i++) {
2383b6c3722Schristos if(ntohs(rep->rrsets[i]->rk.type) == type)
2393b6c3722Schristos return rep->rrsets[i];
2403b6c3722Schristos }
2413b6c3722Schristos return NULL;
2423b6c3722Schristos }
2433b6c3722Schristos
2443b6c3722Schristos /** DS sig test an entry - get DNSKEY and DS in entry and verify */
2453b6c3722Schristos static void
dstest_entry(struct entry * e,struct alloc_cache * alloc,struct regional * region,sldns_buffer * pkt,struct module_env * env)2463b6c3722Schristos dstest_entry(struct entry* e, struct alloc_cache* alloc,
2473b6c3722Schristos struct regional* region, sldns_buffer* pkt, struct module_env* env)
2483b6c3722Schristos {
2493b6c3722Schristos struct query_info qinfo;
2503b6c3722Schristos struct reply_info* rep = NULL;
2513b6c3722Schristos struct ub_packed_rrset_key* ds, *dnskey;
2523b6c3722Schristos int ret;
2533b6c3722Schristos
2543b6c3722Schristos regional_free_all(region);
2553b6c3722Schristos if(vsig) {
2563b6c3722Schristos char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
2573b6c3722Schristos e->reply_list->reply_len);
2583b6c3722Schristos printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory");
2593b6c3722Schristos free(s);
2603b6c3722Schristos }
2613b6c3722Schristos entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
2623b6c3722Schristos ds = find_rrset_type(rep, LDNS_RR_TYPE_DS);
2633b6c3722Schristos dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY);
2643b6c3722Schristos /* check test is OK */
2653b6c3722Schristos unit_assert(ds && dnskey);
2663b6c3722Schristos
2673b6c3722Schristos ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0);
2683b6c3722Schristos if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) {
2693b6c3722Schristos if(vsig) {
2703b6c3722Schristos printf("result(yes)= %s\n", ret?"yes":"no");
2713b6c3722Schristos }
2723b6c3722Schristos unit_assert(ret);
2733b6c3722Schristos } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) {
2743b6c3722Schristos if(vsig) {
2753b6c3722Schristos printf("result(no)= %s\n", ret?"yes":"no");
2763b6c3722Schristos }
2773b6c3722Schristos unit_assert(!ret);
2783b6c3722Schristos verbose(VERB_QUERY, "DS fail: OK; matched unit test");
2793b6c3722Schristos } else {
2803b6c3722Schristos fatal_exit("Bad qname in DS unit test, yes or no");
2813b6c3722Schristos }
2823b6c3722Schristos
2833b6c3722Schristos reply_info_parsedelete(rep, alloc);
2843b6c3722Schristos query_info_clear(&qinfo);
2853b6c3722Schristos }
2863b6c3722Schristos
2873b6c3722Schristos /** verify from a file */
2883b6c3722Schristos static void
verifytest_file(const char * fname,const char * at_date)2893b6c3722Schristos verifytest_file(const char* fname, const char* at_date)
2903b6c3722Schristos {
2913b6c3722Schristos /*
2923b6c3722Schristos * The file contains a list of ldns-testpkts entries.
2933b6c3722Schristos * The first entry must be a query for DNSKEY.
2943b6c3722Schristos * The answer rrset is the keyset that will be used for verification
2953b6c3722Schristos */
2963b6c3722Schristos struct ub_packed_rrset_key* dnskey;
2973b6c3722Schristos struct regional* region = regional_create();
2983b6c3722Schristos struct alloc_cache alloc;
2993b6c3722Schristos sldns_buffer* buf = sldns_buffer_new(65535);
3003b6c3722Schristos struct entry* e;
3013b6c3722Schristos struct entry* list = read_datafile(fname, 1);
3023b6c3722Schristos struct module_env env;
3033b6c3722Schristos struct val_env ve;
3043b6c3722Schristos time_t now = time(NULL);
3050cd9f4ecSchristos unit_show_func("signature verify", fname);
3063b6c3722Schristos
3073b6c3722Schristos if(!list)
3083b6c3722Schristos fatal_exit("could not read %s: %s", fname, strerror(errno));
3093b6c3722Schristos alloc_init(&alloc, NULL, 1);
3103b6c3722Schristos memset(&env, 0, sizeof(env));
3113b6c3722Schristos memset(&ve, 0, sizeof(ve));
3123b6c3722Schristos env.scratch = region;
3133b6c3722Schristos env.scratch_buffer = buf;
3143b6c3722Schristos env.now = &now;
3153b6c3722Schristos ve.date_override = cfg_convert_timeval(at_date);
3163b6c3722Schristos unit_assert(region && buf);
3173b6c3722Schristos dnskey = extract_keys(list, &alloc, region, buf);
3183b6c3722Schristos if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey",
3193b6c3722Schristos dnskey->rk.dname, ntohs(dnskey->rk.type),
3203b6c3722Schristos ntohs(dnskey->rk.rrset_class));
3213b6c3722Schristos /* ready to go! */
3223b6c3722Schristos for(e = list->next; e; e = e->next) {
3233b6c3722Schristos verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve);
3243b6c3722Schristos }
3253b6c3722Schristos
3263b6c3722Schristos ub_packed_rrset_parsedelete(dnskey, &alloc);
3273b6c3722Schristos delete_entry(list);
3283b6c3722Schristos regional_destroy(region);
3293b6c3722Schristos alloc_clear(&alloc);
3303b6c3722Schristos sldns_buffer_free(buf);
3313b6c3722Schristos }
3323b6c3722Schristos
3333b6c3722Schristos /** verify DS matches DNSKEY from a file */
3343b6c3722Schristos static void
dstest_file(const char * fname)3353b6c3722Schristos dstest_file(const char* fname)
3363b6c3722Schristos {
3373b6c3722Schristos /*
3383b6c3722Schristos * The file contains a list of ldns-testpkts entries.
3393b6c3722Schristos * The first entry must be a query for DNSKEY.
3403b6c3722Schristos * The answer rrset is the keyset that will be used for verification
3413b6c3722Schristos */
3423b6c3722Schristos struct regional* region = regional_create();
3433b6c3722Schristos struct alloc_cache alloc;
3443b6c3722Schristos sldns_buffer* buf = sldns_buffer_new(65535);
3453b6c3722Schristos struct entry* e;
3463b6c3722Schristos struct entry* list = read_datafile(fname, 1);
3473b6c3722Schristos struct module_env env;
3480cd9f4ecSchristos unit_show_func("DS verify", fname);
3493b6c3722Schristos
3503b6c3722Schristos if(!list)
3513b6c3722Schristos fatal_exit("could not read %s: %s", fname, strerror(errno));
3523b6c3722Schristos alloc_init(&alloc, NULL, 1);
3533b6c3722Schristos memset(&env, 0, sizeof(env));
3543b6c3722Schristos env.scratch = region;
3553b6c3722Schristos env.scratch_buffer = buf;
3563b6c3722Schristos unit_assert(region && buf);
3573b6c3722Schristos
3583b6c3722Schristos /* ready to go! */
3593b6c3722Schristos for(e = list; e; e = e->next) {
3603b6c3722Schristos dstest_entry(e, &alloc, region, buf, &env);
3613b6c3722Schristos }
3623b6c3722Schristos
3633b6c3722Schristos delete_entry(list);
3643b6c3722Schristos regional_destroy(region);
3653b6c3722Schristos alloc_clear(&alloc);
3663b6c3722Schristos sldns_buffer_free(buf);
3673b6c3722Schristos }
3683b6c3722Schristos
3693b6c3722Schristos /** helper for unittest of NSEC routines */
3703b6c3722Schristos static int
unitest_nsec_has_type_rdata(char * bitmap,size_t len,uint16_t type)3713b6c3722Schristos unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type)
3723b6c3722Schristos {
3733b6c3722Schristos return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type);
3743b6c3722Schristos }
3753b6c3722Schristos
3763b6c3722Schristos /** Test NSEC type bitmap routine */
3773b6c3722Schristos static void
nsectest(void)3783b6c3722Schristos nsectest(void)
3793b6c3722Schristos {
3803b6c3722Schristos /* bitmap starts at type bitmap rdata field */
3813b6c3722Schristos /* from rfc 4034 example */
3823b6c3722Schristos char* bitmap = "\000\006\100\001\000\000\000\003"
3833b6c3722Schristos "\004\033\000\000\000\000\000\000"
3843b6c3722Schristos "\000\000\000\000\000\000\000\000"
3853b6c3722Schristos "\000\000\000\000\000\000\000\000"
3863b6c3722Schristos "\000\000\000\000\040";
3873b6c3722Schristos size_t len = 37;
3883b6c3722Schristos
3893b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0));
3903b6c3722Schristos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A));
3913b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2));
3923b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3));
3933b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4));
3943b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5));
3953b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6));
3963b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7));
3973b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8));
3983b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9));
3993b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10));
4003b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11));
4013b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12));
4023b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13));
4033b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14));
4043b6c3722Schristos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX));
4053b6c3722Schristos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG));
4063b6c3722Schristos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC));
4073b6c3722Schristos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234));
4083b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233));
4093b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235));
4103b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236));
4113b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237));
4123b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238));
4133b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239));
4143b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240));
4153b6c3722Schristos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230));
4163b6c3722Schristos }
4173b6c3722Schristos
4183b6c3722Schristos /** Test hash algo - NSEC3 hash it and compare result */
4193b6c3722Schristos static void
nsec3_hash_test_entry(struct entry * e,rbtree_type * ct,struct alloc_cache * alloc,struct regional * region,sldns_buffer * buf)4200cd9f4ecSchristos nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
4213b6c3722Schristos struct alloc_cache* alloc, struct regional* region,
4223b6c3722Schristos sldns_buffer* buf)
4233b6c3722Schristos {
4243b6c3722Schristos struct query_info qinfo;
4253b6c3722Schristos struct reply_info* rep = NULL;
4263b6c3722Schristos struct ub_packed_rrset_key* answer, *nsec3;
4273b6c3722Schristos struct nsec3_cached_hash* hash = NULL;
4283b6c3722Schristos int ret;
4293b6c3722Schristos uint8_t* qname;
4303b6c3722Schristos
4313b6c3722Schristos if(vsig) {
4323b6c3722Schristos char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
4333b6c3722Schristos e->reply_list->reply_len);
4343b6c3722Schristos printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory");
4353b6c3722Schristos free(s);
4363b6c3722Schristos }
4373b6c3722Schristos entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep);
4383b6c3722Schristos nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3);
4393b6c3722Schristos answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA);
4403b6c3722Schristos qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len);
4413b6c3722Schristos /* check test is OK */
4423b6c3722Schristos unit_assert(nsec3 && answer && qname);
4433b6c3722Schristos
4443b6c3722Schristos ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
4453b6c3722Schristos qinfo.qname_len, &hash);
446*91f7d55fSchristos if(ret < 1) {
4473b6c3722Schristos printf("Bad nsec3_hash_name retcode %d\n", ret);
448*91f7d55fSchristos unit_assert(ret == 1 || ret == 2);
4493b6c3722Schristos }
4503b6c3722Schristos unit_assert(hash->dname && hash->hash && hash->hash_len &&
4513b6c3722Schristos hash->b32 && hash->b32_len);
4523b6c3722Schristos unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]);
4533b6c3722Schristos /* does not do lowercasing. */
4543b6c3722Schristos unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len)
4553b6c3722Schristos == 0);
4563b6c3722Schristos
4573b6c3722Schristos reply_info_parsedelete(rep, alloc);
4583b6c3722Schristos query_info_clear(&qinfo);
4593b6c3722Schristos }
4603b6c3722Schristos
4613b6c3722Schristos
4623b6c3722Schristos /** Read file to test NSEC3 hash algo */
4633b6c3722Schristos static void
nsec3_hash_test(const char * fname)4643b6c3722Schristos nsec3_hash_test(const char* fname)
4653b6c3722Schristos {
4663b6c3722Schristos /*
4673b6c3722Schristos * The list contains a list of ldns-testpkts entries.
4683b6c3722Schristos * Every entry is a test.
4693b6c3722Schristos * The qname is hashed.
4703b6c3722Schristos * The answer section AAAA RR name is the required result.
4713b6c3722Schristos * The auth section NSEC3 is used to get hash parameters.
4723b6c3722Schristos * The hash cache is maintained per file.
4733b6c3722Schristos *
4743b6c3722Schristos * The test does not perform canonicalization during the compare.
4753b6c3722Schristos */
4760cd9f4ecSchristos rbtree_type ct;
4773b6c3722Schristos struct regional* region = regional_create();
4783b6c3722Schristos struct alloc_cache alloc;
4793b6c3722Schristos sldns_buffer* buf = sldns_buffer_new(65535);
4803b6c3722Schristos struct entry* e;
4813b6c3722Schristos struct entry* list = read_datafile(fname, 1);
4820cd9f4ecSchristos unit_show_func("NSEC3 hash", fname);
4833b6c3722Schristos
4843b6c3722Schristos if(!list)
4853b6c3722Schristos fatal_exit("could not read %s: %s", fname, strerror(errno));
4863b6c3722Schristos rbtree_init(&ct, &nsec3_hash_cmp);
4873b6c3722Schristos alloc_init(&alloc, NULL, 1);
4883b6c3722Schristos unit_assert(region && buf);
4893b6c3722Schristos
4903b6c3722Schristos /* ready to go! */
4913b6c3722Schristos for(e = list; e; e = e->next) {
4923b6c3722Schristos nsec3_hash_test_entry(e, &ct, &alloc, region, buf);
4933b6c3722Schristos }
4943b6c3722Schristos
4953b6c3722Schristos delete_entry(list);
4963b6c3722Schristos regional_destroy(region);
4973b6c3722Schristos alloc_clear(&alloc);
4983b6c3722Schristos sldns_buffer_free(buf);
4993b6c3722Schristos }
5003b6c3722Schristos
501f42d8de7Schristos #define xstr(s) str(s)
502f42d8de7Schristos #define str(s) #s
503f42d8de7Schristos
504f42d8de7Schristos #define SRCDIRSTR xstr(SRCDIR)
505f42d8de7Schristos
5063b6c3722Schristos void
verify_test(void)5073b6c3722Schristos verify_test(void)
5083b6c3722Schristos {
5093b6c3722Schristos unit_show_feature("signature verify");
5100cd9f4ecSchristos #ifdef USE_SHA1
511f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004");
5120cd9f4ecSchristos #endif
5130cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
514f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004");
515f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004");
516f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004");
517f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004");
518f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004");
519f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150");
5203b6c3722Schristos #endif /* USE_DSA */
5210cd9f4ecSchristos #ifdef USE_SHA1
522f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150");
5230cd9f4ecSchristos #endif
5243b6c3722Schristos #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
525f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256", "20070829144150");
5260cd9f4ecSchristos # ifdef USE_SHA1
527f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150");
5280cd9f4ecSchristos # endif
529f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000");
5303b6c3722Schristos #endif
5313b6c3722Schristos #if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
532f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150");
533f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000");
5343b6c3722Schristos #endif
5350cd9f4ecSchristos #ifdef USE_SHA1
536f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022");
537f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004");
5380cd9f4ecSchristos #endif
5393b6c3722Schristos #ifdef USE_GOST
5403b6c3722Schristos if(sldns_key_EVP_load_gost_id())
541f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
5423b6c3722Schristos else printf("Warning: skipped GOST, openssl does not provide gost.\n");
5433b6c3722Schristos #endif
5443b6c3722Schristos #ifdef USE_ECDSA
5453b6c3722Schristos /* test for support in case we use libNSS and ECC is removed */
5463b6c3722Schristos if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
547f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439");
548f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439");
5493b6c3722Schristos }
550f42d8de7Schristos dstest_file(SRCDIRSTR "/testdata/test_ds.sha384");
5513b6c3722Schristos #endif
5520cd9f4ecSchristos #ifdef USE_ED25519
5530cd9f4ecSchristos if(dnskey_algo_id_is_supported(LDNS_ED25519)) {
554f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed25519", "20170530140439");
5550cd9f4ecSchristos }
5560cd9f4ecSchristos #endif
5577cd94d69Schristos #ifdef USE_ED448
5587cd94d69Schristos if(dnskey_algo_id_is_supported(LDNS_ED448)) {
559f42d8de7Schristos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed448", "20180408143630");
5607cd94d69Schristos }
5617cd94d69Schristos #endif
5620cd9f4ecSchristos #ifdef USE_SHA1
563f42d8de7Schristos dstest_file(SRCDIRSTR "/testdata/test_ds.sha1");
5640cd9f4ecSchristos #endif
5653b6c3722Schristos nsectest();
566f42d8de7Schristos nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1");
5673b6c3722Schristos }
568