xref: /freebsd/contrib/unbound/testcode/unitverify.c (revision b2efd602aea8b3cbc3fb215b9611946d04fceb10)
1 /*
2  * testcode/unitverify.c - unit test for signature verification routines.
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  * Calls verification unit tests. Exits with code 1 on a failure.
39  */
40 
41 #include "config.h"
42 #include "util/log.h"
43 #include "testcode/unitmain.h"
44 #include "validator/val_sigcrypt.h"
45 #include "validator/val_secalgo.h"
46 #include "validator/val_nsec.h"
47 #include "validator/val_nsec3.h"
48 #include "validator/validator.h"
49 #include "testcode/testpkts.h"
50 #include "util/data/msgreply.h"
51 #include "util/data/msgparse.h"
52 #include "util/data/dname.h"
53 #include "util/regional.h"
54 #include "util/alloc.h"
55 #include "util/rbtree.h"
56 #include "util/net_help.h"
57 #include "util/module.h"
58 #include "util/config_file.h"
59 #include "sldns/sbuffer.h"
60 #include "sldns/keyraw.h"
61 #include "sldns/str2wire.h"
62 #include "sldns/wire2str.h"
63 
64 #ifdef HAVE_SSL
65 #ifdef HAVE_OPENSSL_ERR_H
66 #include <openssl/err.h>
67 #endif
68 #endif
69 
70 /** verbose signature test */
71 static int vsig = 0;
72 
73 /** entry to packet buffer with wireformat */
74 static void
entry_to_buf(struct entry * e,sldns_buffer * pkt)75 entry_to_buf(struct entry* e, sldns_buffer* pkt)
76 {
77 	unit_assert(e->reply_list);
78 	if(e->reply_list->reply_from_hex) {
79 		sldns_buffer_copy(pkt, e->reply_list->reply_from_hex);
80 	} else {
81 		sldns_buffer_clear(pkt);
82 		sldns_buffer_write(pkt, e->reply_list->reply_pkt,
83 			e->reply_list->reply_len);
84 		sldns_buffer_flip(pkt);
85 	}
86 }
87 
88 /** entry to reply info conversion */
89 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)90 entry_to_repinfo(struct entry* e, struct alloc_cache* alloc,
91 	struct regional* region, sldns_buffer* pkt, struct query_info* qi,
92 	struct reply_info** rep)
93 {
94 	int ret;
95 	struct edns_data edns;
96 	entry_to_buf(e, pkt);
97 	/* lock alloc lock to please lock checking software.
98 	 * alloc_special_obtain assumes it is talking to a ub-alloc,
99 	 * and does not need to perform locking. Here the alloc is
100 	 * the only one, so we lock it here */
101 	lock_quick_lock(&alloc->lock);
102 	ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns);
103 	lock_quick_unlock(&alloc->lock);
104 	if(ret != 0) {
105 		char rcode[16];
106 		sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode));
107 		printf("parse code %d: %s\n", ret, rcode);
108 		unit_assert(ret != 0);
109 	}
110 }
111 
112 /** extract DNSKEY rrset from answer and convert it */
113 static struct ub_packed_rrset_key*
extract_keys(struct entry * e,struct alloc_cache * alloc,struct regional * region,sldns_buffer * pkt)114 extract_keys(struct entry* e, struct alloc_cache* alloc,
115 	struct regional* region, sldns_buffer* pkt)
116 {
117 	struct ub_packed_rrset_key* dnskey = NULL;
118 	struct query_info qinfo;
119 	struct reply_info* rep = NULL;
120 	size_t i;
121 
122 	entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
123 	for(i=0; i<rep->an_numrrsets; i++) {
124 		if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) {
125 			dnskey = rep->rrsets[i];
126 			rep->rrsets[i] = NULL;
127 			break;
128 		}
129 	}
130 	unit_assert(dnskey);
131 
132 	reply_info_parsedelete(rep, alloc);
133 	query_info_clear(&qinfo);
134 	return dnskey;
135 }
136 
137 /** return true if answer should be bogus */
138 static int
should_be_bogus(struct ub_packed_rrset_key * rrset,struct query_info * qinfo)139 should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo)
140 {
141 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
142 		entry.data;
143 	if(d->rrsig_count == 0)
144 		return 1;
145 	/* name 'bogus' as first label signals bogus */
146 	if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0)
147 		return 1;
148 	if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0)
149 		return 1;
150 	return 0;
151 }
152 
153 /** return number of rrs in an rrset */
154 static size_t
rrset_get_count(struct ub_packed_rrset_key * rrset)155 rrset_get_count(struct ub_packed_rrset_key* rrset)
156 {
157 	struct packed_rrset_data* d = (struct packed_rrset_data*)
158 	rrset->entry.data;
159 	if(!d) return 0;
160 	return d->count;
161 }
162 
163 /** setup sig alg list from dnskey */
164 static void
setup_sigalg(struct ub_packed_rrset_key * dnskey,uint8_t * sigalg)165 setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
166 {
167 	uint8_t a[ALGO_NEEDS_MAX];
168 	size_t i, n = 0;
169 	memset(a, 0, sizeof(a));
170 	for(i=0; i<rrset_get_count(dnskey); i++) {
171 		uint8_t algo = (uint8_t)dnskey_get_algo(dnskey, i);
172 		if(a[algo] == 0) {
173 			a[algo] = 1;
174 			sigalg[n++] = algo;
175 		}
176 	}
177 	sigalg[n] = 0;
178 }
179 
180 /** verify and test one rrset against the key rrset */
181 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)182 verifytest_rrset(struct module_env* env, struct val_env* ve,
183 	struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
184 	struct query_info* qinfo)
185 {
186 	enum sec_status sec;
187 	char reasonbuf[256];
188 	char* reason = NULL;
189 	uint8_t sigalg[ALGO_NEEDS_MAX+1];
190 	int verified = 0;
191 	if(vsig) {
192 		log_nametypeclass(VERB_QUERY, "verify of rrset",
193 			rrset->rk.dname, ntohs(rrset->rk.type),
194 			ntohs(rrset->rk.rrset_class));
195 	}
196 	setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
197 	/* ok to give null as qstate here, won't be used for answer section. */
198 	sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason,
199 		NULL, LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf,
200 		sizeof(reasonbuf));
201 	if(vsig) {
202 		printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
203 			reason?reason:"");
204 	}
205 	if(should_be_bogus(rrset, qinfo)) {
206 		unit_assert(sec == sec_status_bogus);
207 	} else {
208 		unit_assert(sec == sec_status_secure);
209 	}
210 }
211 
212 /** verify and test an entry - every rr in the message */
213 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)214 verifytest_entry(struct entry* e, struct alloc_cache* alloc,
215 	struct regional* region, sldns_buffer* pkt,
216 	struct ub_packed_rrset_key* dnskey, struct module_env* env,
217 	struct val_env* ve)
218 {
219 	struct query_info qinfo;
220 	struct reply_info* rep = NULL;
221 	size_t i;
222 
223 	regional_free_all(region);
224 	if(vsig) {
225 		char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
226 			e->reply_list->reply_len);
227 		printf("verifying pkt:\n%s\n", s?s:"outofmemory");
228 		free(s);
229 	}
230 	entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
231 
232 	for(i=0; i<rep->rrset_count; i++) {
233 		verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo);
234 	}
235 
236 	reply_info_parsedelete(rep, alloc);
237 	query_info_clear(&qinfo);
238 }
239 
240 /** find RRset in reply by type */
241 static struct ub_packed_rrset_key*
find_rrset_type(struct reply_info * rep,uint16_t type)242 find_rrset_type(struct reply_info* rep, uint16_t type)
243 {
244 	size_t i;
245 	for(i=0; i<rep->rrset_count; i++) {
246 		if(ntohs(rep->rrsets[i]->rk.type) == type)
247 			return rep->rrsets[i];
248 	}
249 	return NULL;
250 }
251 
252 /** DS sig test an entry - get DNSKEY and DS in entry and verify */
253 static void
dstest_entry(struct entry * e,struct alloc_cache * alloc,struct regional * region,sldns_buffer * pkt,struct module_env * env)254 dstest_entry(struct entry* e, struct alloc_cache* alloc,
255 	struct regional* region, sldns_buffer* pkt, struct module_env* env)
256 {
257 	struct query_info qinfo;
258 	struct reply_info* rep = NULL;
259 	struct ub_packed_rrset_key* ds, *dnskey;
260 	int ret;
261 
262 	regional_free_all(region);
263 	if(vsig) {
264 		char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
265 			e->reply_list->reply_len);
266 		printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory");
267 		free(s);
268 	}
269 	entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
270 	ds = find_rrset_type(rep, LDNS_RR_TYPE_DS);
271 	dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY);
272 	/* check test is OK */
273 	unit_assert(ds && dnskey);
274 
275 	ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0);
276 	if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) {
277 		if(vsig) {
278 			printf("result(yes)= %s\n", ret?"yes":"no");
279 		}
280 		unit_assert(ret);
281 	} else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) {
282 		if(vsig) {
283 			printf("result(no)= %s\n", ret?"yes":"no");
284 		}
285 		unit_assert(!ret);
286 		verbose(VERB_QUERY, "DS fail: OK; matched unit test");
287 	} else {
288 		fatal_exit("Bad qname in DS unit test, yes or no");
289 	}
290 
291 	reply_info_parsedelete(rep, alloc);
292 	query_info_clear(&qinfo);
293 }
294 
295 /** verify from a file */
296 static void
verifytest_file(const char * fname,const char * at_date)297 verifytest_file(const char* fname, const char* at_date)
298 {
299 	/*
300 	 * The file contains a list of ldns-testpkts entries.
301 	 * The first entry must be a query for DNSKEY.
302 	 * The answer rrset is the keyset that will be used for verification
303 	 */
304 	struct ub_packed_rrset_key* dnskey;
305 	struct regional* region = regional_create();
306 	struct alloc_cache alloc;
307 	sldns_buffer* buf = sldns_buffer_new(65535);
308 	struct entry* e;
309 	struct entry* list = read_datafile(fname, 1);
310 	struct module_env env;
311 	struct val_env ve;
312 	time_t now = time(NULL);
313 	unit_show_func("signature verify", fname);
314 
315 	if(!list)
316 		fatal_exit("could not read %s: %s", fname, strerror(errno));
317 	alloc_init(&alloc, NULL, 1);
318 	memset(&env, 0, sizeof(env));
319 	memset(&ve, 0, sizeof(ve));
320 	env.scratch = region;
321 	env.scratch_buffer = buf;
322 	env.now = &now;
323 	ve.date_override = cfg_convert_timeval(at_date);
324 	unit_assert(region && buf);
325 	dnskey = extract_keys(list, &alloc, region, buf);
326 	if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey",
327 			dnskey->rk.dname, ntohs(dnskey->rk.type),
328 			ntohs(dnskey->rk.rrset_class));
329 	/* ready to go! */
330 	for(e = list->next; e; e = e->next) {
331 		verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve);
332 	}
333 
334 	ub_packed_rrset_parsedelete(dnskey, &alloc);
335 	delete_entry(list);
336 	regional_destroy(region);
337 	alloc_clear(&alloc);
338 	sldns_buffer_free(buf);
339 }
340 
341 /** verify DS matches DNSKEY from a file */
342 static void
dstest_file(const char * fname)343 dstest_file(const char* fname)
344 {
345 	/*
346 	 * The file contains a list of ldns-testpkts entries.
347 	 * The first entry must be a query for DNSKEY.
348 	 * The answer rrset is the keyset that will be used for verification
349 	 */
350 	struct regional* region = regional_create();
351 	struct alloc_cache alloc;
352 	sldns_buffer* buf = sldns_buffer_new(65535);
353 	struct entry* e;
354 	struct entry* list = read_datafile(fname, 1);
355 	struct module_env env;
356 	unit_show_func("DS verify", fname);
357 
358 	if(!list)
359 		fatal_exit("could not read %s: %s", fname, strerror(errno));
360 	alloc_init(&alloc, NULL, 1);
361 	memset(&env, 0, sizeof(env));
362 	env.scratch = region;
363 	env.scratch_buffer = buf;
364 	unit_assert(region && buf);
365 
366 	/* ready to go! */
367 	for(e = list; e; e = e->next) {
368 		dstest_entry(e, &alloc, region, buf, &env);
369 	}
370 
371 	delete_entry(list);
372 	regional_destroy(region);
373 	alloc_clear(&alloc);
374 	sldns_buffer_free(buf);
375 }
376 
377 /** helper for unittest of NSEC routines */
378 static int
unitest_nsec_has_type_rdata(char * bitmap,size_t len,uint16_t type)379 unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type)
380 {
381 	return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type);
382 }
383 
384 /** Test NSEC type bitmap routine */
385 static void
nsectest(void)386 nsectest(void)
387 {
388 	/* bitmap starts at type bitmap rdata field */
389 	/* from rfc 4034 example */
390 	char* bitmap = "\000\006\100\001\000\000\000\003"
391 		"\004\033\000\000\000\000\000\000"
392 		"\000\000\000\000\000\000\000\000"
393 		"\000\000\000\000\000\000\000\000"
394 		"\000\000\000\000\040";
395 	size_t len = 37;
396 
397 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0));
398 	unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A));
399 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2));
400 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3));
401 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4));
402 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5));
403 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6));
404 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7));
405 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8));
406 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9));
407 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10));
408 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11));
409 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12));
410 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13));
411 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14));
412 	unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX));
413 	unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG));
414 	unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC));
415 	unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234));
416 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233));
417 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235));
418 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236));
419 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237));
420 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238));
421 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239));
422 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240));
423 	unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230));
424 }
425 
426 /** Test hash algo - NSEC3 hash it and compare result */
427 static void
nsec3_hash_test_entry(struct entry * e,rbtree_type * ct,struct alloc_cache * alloc,struct regional * region,sldns_buffer * buf)428 nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
429 	struct alloc_cache* alloc, struct regional* region,
430 	sldns_buffer* buf)
431 {
432 	struct query_info qinfo;
433 	struct reply_info* rep = NULL;
434 	struct ub_packed_rrset_key* answer, *nsec3, *nsec3_region;
435 	struct nsec3_cached_hash* hash = NULL;
436 	int ret;
437 	uint8_t* qname;
438 
439 	if(vsig) {
440 		char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
441 			e->reply_list->reply_len);
442 		printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory");
443 		free(s);
444 	}
445 	entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep);
446 	nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3);
447 	answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA);
448 	qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len);
449 	/* check test is OK */
450 	unit_assert(nsec3 && answer && qname);
451 
452 	/* Copy the nsec3 to the region, so it can stay referenced by the
453 	 * ct tree entry. The region is freed when the file is done. */
454 	nsec3_region = packed_rrset_copy_region(nsec3, region, 0);
455 
456 	ret = nsec3_hash_name(ct, region, buf, nsec3_region, 0, qname,
457 		qinfo.qname_len, &hash);
458 	if(ret < 1) {
459 		printf("Bad nsec3_hash_name retcode %d\n", ret);
460 		unit_assert(ret == 1 || ret == 2);
461 	}
462 	unit_assert(hash->dname && hash->hash && hash->hash_len &&
463 		hash->b32 && hash->b32_len);
464 	unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]);
465 	/* does not do lowercasing. */
466 	unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len)
467 		== 0);
468 
469 	reply_info_parsedelete(rep, alloc);
470 	query_info_clear(&qinfo);
471 }
472 
473 
474 /** Read file to test NSEC3 hash algo */
475 static void
nsec3_hash_test(const char * fname)476 nsec3_hash_test(const char* fname)
477 {
478 	/*
479 	 * The list contains a list of ldns-testpkts entries.
480 	 * Every entry is a test.
481 	 * 	The qname is hashed.
482 	 * 	The answer section AAAA RR name is the required result.
483 	 * 	The auth section NSEC3 is used to get hash parameters.
484 	 * The hash cache is maintained per file.
485 	 *
486 	 * The test does not perform canonicalization during the compare.
487 	 */
488 	rbtree_type ct;
489 	struct regional* region = regional_create();
490 	struct alloc_cache alloc;
491 	sldns_buffer* buf = sldns_buffer_new(65535);
492 	struct entry* e;
493 	struct entry* list = read_datafile(fname, 1);
494 	unit_show_func("NSEC3 hash", fname);
495 
496 	if(!list)
497 		fatal_exit("could not read %s: %s", fname, strerror(errno));
498 	rbtree_init(&ct, &nsec3_hash_cmp);
499 	alloc_init(&alloc, NULL, 1);
500 	unit_assert(region && buf);
501 
502 	/* ready to go! */
503 	for(e = list; e; e = e->next) {
504 		nsec3_hash_test_entry(e, &ct, &alloc, region, buf);
505 	}
506 
507 	delete_entry(list);
508 	regional_destroy(region);
509 	alloc_clear(&alloc);
510 	sldns_buffer_free(buf);
511 }
512 
513 #define xstr(s) str(s)
514 #define str(s) #s
515 
516 #define SRCDIRSTR xstr(SRCDIR)
517 
518 #if defined(HAVE_SSL) && defined(USE_SHA1)
519 /* Detect if openssl is configured to disable RSASHA1 signatures,
520  * with the rh-allow-sha1-signatures disabled. */
521 static int
rh_allow_sha1_signatures_disabled(void)522 rh_allow_sha1_signatures_disabled(void)
523 {
524 	EVP_MD_CTX* ctx;
525 	EVP_PKEY* evp_key;
526 	/* This key is rdata from nlnetlabs.nl DNSKEY from 20250424005001,
527 	 * with id=50602 (ksk), size=2048b.
528 	 * A 2048 bit key is taken to avoid key too small errors. */
529 	unsigned char key[] = {
530 		0x03, 0x01, 0x00, 0x01, 0xBC, 0x0B, 0xE8, 0xBB,
531 		0x97, 0x4C, 0xB5, 0xED, 0x6F, 0x6D, 0xC2, 0xB1,
532 		0x78, 0x69, 0x93, 0x1C, 0x72, 0x19, 0xB1, 0x05,
533 		0x51, 0x13, 0xA1, 0xFC, 0xBF, 0x01, 0x58, 0x0D,
534 		0x44, 0x10, 0x5F, 0x0B, 0x75, 0x0E, 0x11, 0x9A,
535 		0xC8, 0xF8, 0x0F, 0x90, 0xFC, 0xB8, 0x09, 0xD1,
536 		0x14, 0x39, 0x0D, 0x84, 0xCE, 0x97, 0x88, 0x82,
537 		0x3D, 0xC5, 0xCB, 0x1A, 0xBF, 0x00, 0x46, 0x37,
538 		0x01, 0xF1, 0xCD, 0x46, 0xA2, 0x8F, 0x83, 0x19,
539 		0x42, 0xED, 0x6F, 0xAF, 0x37, 0x1F, 0x18, 0x82,
540 		0x4B, 0x70, 0x2D, 0x50, 0xA5, 0xA6, 0x66, 0x48,
541 		0x7F, 0x56, 0xA8, 0x86, 0x05, 0x41, 0xC8, 0xBE,
542 		0x4F, 0x8B, 0x38, 0x51, 0xF0, 0xEB, 0xAD, 0x2F,
543 		0x7A, 0xC0, 0xEF, 0xC7, 0xD2, 0x72, 0x6F, 0x16,
544 		0x66, 0xAF, 0x59, 0x55, 0xFF, 0xEE, 0x9D, 0x50,
545 		0xE9, 0xDB, 0xF4, 0x02, 0xBC, 0x33, 0x5C, 0xC5,
546 		0xDA, 0x1C, 0x6A, 0xD1, 0x55, 0xD1, 0x20, 0x2B,
547 		0x63, 0x03, 0x4B, 0x77, 0x45, 0x46, 0x78, 0x31,
548 		0xE4, 0x90, 0xB9, 0x7F, 0x00, 0xFB, 0x62, 0x7C,
549 		0x07, 0xD3, 0xC1, 0x00, 0xA0, 0x54, 0x63, 0x74,
550 		0x0A, 0x17, 0x7B, 0xE7, 0xAD, 0x38, 0x07, 0x86,
551 		0x68, 0xE4, 0xFD, 0x20, 0x68, 0xD5, 0x33, 0x92,
552 		0xCA, 0x90, 0xDD, 0xA4, 0xE9, 0xF2, 0x11, 0xBD,
553 		0x9D, 0xA5, 0xF5, 0xEB, 0xB9, 0xFE, 0x8F, 0xA1,
554 		0xE4, 0xBF, 0xA4, 0xA4, 0x34, 0x5C, 0x6A, 0x95,
555 		0xB6, 0x42, 0x22, 0xF6, 0xD6, 0x10, 0x9C, 0x9B,
556 		0x0A, 0x56, 0xE7, 0x42, 0xE5, 0x7F, 0x1F, 0x4E,
557 		0xBE, 0x4F, 0x8C, 0xED, 0x30, 0x63, 0xA7, 0x88,
558 		0x93, 0xED, 0x37, 0x3C, 0x80, 0xBC, 0xD1, 0x66,
559 		0xBD, 0xB8, 0x2E, 0x65, 0xC4, 0xC8, 0x00, 0x5B,
560 		0xE7, 0x85, 0x96, 0xDD, 0xAA, 0x05, 0xE6, 0x4F,
561 		0x03, 0x64, 0xFA, 0x2D, 0xF6, 0x88, 0x14, 0x8F,
562 		0x15, 0x4D, 0xFD, 0xD3
563 	};
564 	size_t keylen = 260;
565 
566 #ifdef HAVE_EVP_MD_CTX_NEW
567 	ctx = EVP_MD_CTX_new();
568 #else
569 	ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
570 	if(ctx) EVP_MD_CTX_init(ctx);
571 #endif
572 	if(!ctx) return 0;
573 
574 	evp_key = sldns_key_rsa2pkey_raw(key, keylen);
575 	if(!evp_key) {
576 #ifdef HAVE_EVP_MD_CTX_NEW
577 		EVP_MD_CTX_destroy(ctx);
578 #else
579 		EVP_MD_CTX_cleanup(ctx);
580 		free(ctx);
581 #endif
582 		return 0;
583 	}
584 
585 #ifndef HAVE_EVP_DIGESTVERIFY
586 	(void)evp_key; /* not used */
587 	if(EVP_DigestInit(ctx, EVP_sha1()) == 0)
588 #else
589 	if(EVP_DigestVerifyInit(ctx, NULL, EVP_sha1(), NULL, evp_key) == 0)
590 #endif
591 	{
592 		unsigned long e = ERR_get_error();
593 #ifdef EVP_R_INVALID_DIGEST
594 		if (ERR_GET_LIB(e) == ERR_LIB_EVP &&
595 			ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST) {
596 			/* rh-allow-sha1-signatures makes use of sha1 invalid. */
597 			if(vsig)
598 				printf("Detected that rh-allow-sha1-signatures is off, and disables SHA1 signatures\n");
599 #ifdef HAVE_EVP_MD_CTX_NEW
600 			EVP_MD_CTX_destroy(ctx);
601 #else
602 			EVP_MD_CTX_cleanup(ctx);
603 			free(ctx);
604 #endif
605 			EVP_PKEY_free(evp_key);
606 			return 1;
607 		}
608 #endif /* EVP_R_INVALID_DIGEST */
609 		/* The signature verify failed for another reason. */
610 		log_crypto_err_code("EVP_DigestVerifyInit", e);
611 #ifdef HAVE_EVP_MD_CTX_NEW
612 		EVP_MD_CTX_destroy(ctx);
613 #else
614 		EVP_MD_CTX_cleanup(ctx);
615 		free(ctx);
616 #endif
617 		EVP_PKEY_free(evp_key);
618 		return 0;
619 	}
620 #ifdef HAVE_EVP_MD_CTX_NEW
621 	EVP_MD_CTX_destroy(ctx);
622 #else
623 	EVP_MD_CTX_cleanup(ctx);
624 	free(ctx);
625 #endif
626 	EVP_PKEY_free(evp_key);
627 	return 0;
628 }
629 #endif /* HAVE_SSL && USE_SHA1 */
630 
631 void
verify_test(void)632 verify_test(void)
633 {
634 	unit_show_feature("signature verify");
635 
636 #if defined(HAVE_SSL) && defined(USE_SHA1)
637 	if(rh_allow_sha1_signatures_disabled()) {
638 		/* Allow the use of SHA1 signatures for the test,
639 		 * in case that OpenSSL disallows use of RSASHA1
640 		 * with rh-allow-sha1-signatures disabled. */
641 #ifndef UB_ON_WINDOWS
642 		setenv("OPENSSL_ENABLE_SHA1_SIGNATURES", "1", 0);
643 #else
644 		_putenv("OPENSSL_ENABLE_SHA1_SIGNATURES=1");
645 #endif
646 	}
647 #endif
648 
649 #ifdef USE_SHA1
650 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004");
651 #endif
652 #if defined(USE_DSA) && defined(USE_SHA1)
653 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004");
654 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004");
655 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004");
656 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004");
657 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004");
658 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150");
659 #endif /* USE_DSA */
660 #ifdef USE_SHA1
661 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150");
662 #endif
663 #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
664 	verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256", "20070829144150");
665 #  ifdef USE_SHA1
666 	verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150");
667 #  endif
668 	verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000");
669 #endif
670 #if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
671 	verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150");
672 	verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000");
673 #endif
674 #ifdef USE_SHA1
675 	verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022");
676 	verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004");
677 #endif
678 #ifdef USE_GOST
679 	if(sldns_key_EVP_load_gost_id())
680 	  verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
681 	else printf("Warning: skipped GOST, openssl does not provide gost.\n");
682 #endif
683 #ifdef USE_ECDSA
684 	/* test for support in case we use libNSS and ECC is removed */
685 	if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
686 		verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439");
687 		verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439");
688 	}
689 	dstest_file(SRCDIRSTR "/testdata/test_ds.sha384");
690 #endif
691 #ifdef USE_ED25519
692 	if(dnskey_algo_id_is_supported(LDNS_ED25519)) {
693 		verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed25519", "20170530140439");
694 	}
695 #endif
696 #ifdef USE_ED448
697 	if(dnskey_algo_id_is_supported(LDNS_ED448)) {
698 		verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed448", "20180408143630");
699 	}
700 #endif
701 #ifdef USE_SHA1
702 	dstest_file(SRCDIRSTR "/testdata/test_ds.sha1");
703 #endif
704 	nsectest();
705 	nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1");
706 }
707