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