1238104Sdes#include <ldns/config.h> 2238104Sdes 3238104Sdes#include <ldns/ldns.h> 4238104Sdes 5238104Sdes#include <strings.h> 6238104Sdes#include <time.h> 7238104Sdes 8238104Sdes#ifdef HAVE_SSL 9238104Sdes/* this entire file is rather useless when you don't have 10238104Sdes * crypto... 11238104Sdes */ 12238104Sdes#include <openssl/ssl.h> 13238104Sdes#include <openssl/evp.h> 14238104Sdes#include <openssl/rand.h> 15238104Sdes#include <openssl/err.h> 16238104Sdes#include <openssl/md5.h> 17238104Sdes 18238104Sdesldns_dnssec_data_chain * 19246827Sdesldns_dnssec_data_chain_new(void) 20238104Sdes{ 21238104Sdes ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); 22238104Sdes if(!nc) return NULL; 23238104Sdes /* 24238104Sdes * not needed anymore because CALLOC initalizes everything to zero. 25238104Sdes 26238104Sdes nc->rrset = NULL; 27238104Sdes nc->parent_type = 0; 28238104Sdes nc->parent = NULL; 29238104Sdes nc->signatures = NULL; 30238104Sdes nc->packet_rcode = 0; 31238104Sdes nc->packet_qtype = 0; 32238104Sdes nc->packet_nodata = false; 33238104Sdes 34238104Sdes */ 35238104Sdes return nc; 36238104Sdes} 37238104Sdes 38238104Sdesvoid 39238104Sdesldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain) 40238104Sdes{ 41238104Sdes LDNS_FREE(chain); 42238104Sdes} 43238104Sdes 44238104Sdesvoid 45238104Sdesldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain) 46238104Sdes{ 47238104Sdes ldns_rr_list_deep_free(chain->rrset); 48238104Sdes ldns_rr_list_deep_free(chain->signatures); 49238104Sdes if (chain->parent) { 50238104Sdes ldns_dnssec_data_chain_deep_free(chain->parent); 51238104Sdes } 52238104Sdes LDNS_FREE(chain); 53238104Sdes} 54238104Sdes 55238104Sdesvoid 56238104Sdesldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt, 57238104Sdes const ldns_dnssec_data_chain *chain) 58238104Sdes{ 59238104Sdes ldns_lookup_table *rcode; 60238104Sdes const ldns_rr_descriptor *rr_descriptor; 61238104Sdes if (chain) { 62238104Sdes ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent); 63238104Sdes if (ldns_rr_list_rr_count(chain->rrset) > 0) { 64238104Sdes rcode = ldns_lookup_by_id(ldns_rcodes, 65238104Sdes (int) chain->packet_rcode); 66238104Sdes if (rcode) { 67238104Sdes fprintf(out, ";; rcode: %s\n", rcode->name); 68238104Sdes } 69238104Sdes 70238104Sdes rr_descriptor = ldns_rr_descript(chain->packet_qtype); 71238104Sdes if (rr_descriptor && rr_descriptor->_name) { 72238104Sdes fprintf(out, ";; qtype: %s\n", rr_descriptor->_name); 73238104Sdes } else if (chain->packet_qtype != 0) { 74238104Sdes fprintf(out, "TYPE%u", 75238104Sdes chain->packet_qtype); 76238104Sdes } 77238104Sdes if (chain->packet_nodata) { 78238104Sdes fprintf(out, ";; NODATA response\n"); 79238104Sdes } 80238104Sdes fprintf(out, "rrset:\n"); 81238104Sdes ldns_rr_list_print_fmt(out, fmt, chain->rrset); 82238104Sdes fprintf(out, "sigs:\n"); 83238104Sdes ldns_rr_list_print_fmt(out, fmt, chain->signatures); 84238104Sdes fprintf(out, "---\n"); 85238104Sdes } else { 86238104Sdes fprintf(out, "<no data>\n"); 87238104Sdes } 88238104Sdes } 89238104Sdes} 90238104Sdesvoid 91238104Sdesldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain) 92238104Sdes{ 93238104Sdes ldns_dnssec_data_chain_print_fmt( 94238104Sdes out, ldns_output_format_default, chain); 95238104Sdes} 96238104Sdes 97238104Sdes 98238104Sdesstatic void 99238104Sdesldns_dnssec_build_data_chain_dnskey(ldns_resolver *res, 100238104Sdes uint16_t qflags, 101238104Sdes const ldns_pkt *pkt, 102238104Sdes ldns_rr_list *signatures, 103238104Sdes ldns_dnssec_data_chain *new_chain, 104238104Sdes ldns_rdf *key_name, 105238104Sdes ldns_rr_class c) { 106238104Sdes ldns_rr_list *keys; 107238104Sdes ldns_pkt *my_pkt; 108238104Sdes if (signatures && ldns_rr_list_rr_count(signatures) > 0) { 109238104Sdes new_chain->signatures = ldns_rr_list_clone(signatures); 110238104Sdes new_chain->parent_type = 0; 111238104Sdes 112238104Sdes keys = ldns_pkt_rr_list_by_name_and_type( 113238104Sdes pkt, 114238104Sdes key_name, 115238104Sdes LDNS_RR_TYPE_DNSKEY, 116238104Sdes LDNS_SECTION_ANY_NOQUESTION 117238104Sdes ); 118238104Sdes if (!keys) { 119238104Sdes my_pkt = ldns_resolver_query(res, 120238104Sdes key_name, 121238104Sdes LDNS_RR_TYPE_DNSKEY, 122238104Sdes c, 123238104Sdes qflags); 124238104Sdes if (my_pkt) { 125238104Sdes keys = ldns_pkt_rr_list_by_name_and_type( 126238104Sdes my_pkt, 127238104Sdes key_name, 128238104Sdes LDNS_RR_TYPE_DNSKEY, 129238104Sdes LDNS_SECTION_ANY_NOQUESTION 130238104Sdes ); 131238104Sdes new_chain->parent = ldns_dnssec_build_data_chain(res, 132238104Sdes qflags, 133238104Sdes keys, 134238104Sdes my_pkt, 135238104Sdes NULL); 136238104Sdes new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; 137238104Sdes ldns_pkt_free(my_pkt); 138238104Sdes } 139238104Sdes } else { 140238104Sdes new_chain->parent = ldns_dnssec_build_data_chain(res, 141238104Sdes qflags, 142238104Sdes keys, 143238104Sdes pkt, 144238104Sdes NULL); 145238104Sdes new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; 146238104Sdes } 147238104Sdes ldns_rr_list_deep_free(keys); 148238104Sdes } 149238104Sdes} 150238104Sdes 151238104Sdesstatic void 152238104Sdesldns_dnssec_build_data_chain_other(ldns_resolver *res, 153238104Sdes uint16_t qflags, 154238104Sdes ldns_dnssec_data_chain *new_chain, 155238104Sdes ldns_rdf *key_name, 156238104Sdes ldns_rr_class c, 157238104Sdes ldns_rr_list *dss) 158238104Sdes{ 159238104Sdes /* 'self-signed', parent is a DS */ 160238104Sdes 161238104Sdes /* okay, either we have other keys signing the current one, 162238104Sdes * or the current 163238104Sdes * one should have a DS record in the parent zone. 164238104Sdes * How do we find this out? Try both? 165238104Sdes * 166238104Sdes * request DNSKEYS for current zone, 167238104Sdes * add all signatures to current level 168238104Sdes */ 169238104Sdes ldns_pkt *my_pkt; 170238104Sdes ldns_rr_list *signatures2; 171238104Sdes 172238104Sdes new_chain->parent_type = 1; 173238104Sdes 174238104Sdes my_pkt = ldns_resolver_query(res, 175238104Sdes key_name, 176238104Sdes LDNS_RR_TYPE_DS, 177238104Sdes c, 178238104Sdes qflags); 179238104Sdes if (my_pkt) { 180238104Sdes dss = ldns_pkt_rr_list_by_name_and_type(my_pkt, 181238104Sdes key_name, 182238104Sdes LDNS_RR_TYPE_DS, 183238104Sdes LDNS_SECTION_ANY_NOQUESTION 184238104Sdes ); 185238104Sdes if (dss) { 186238104Sdes new_chain->parent = ldns_dnssec_build_data_chain(res, 187238104Sdes qflags, 188238104Sdes dss, 189238104Sdes my_pkt, 190238104Sdes NULL); 191238104Sdes new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; 192238104Sdes ldns_rr_list_deep_free(dss); 193238104Sdes } 194238104Sdes ldns_pkt_free(my_pkt); 195238104Sdes } 196238104Sdes 197238104Sdes my_pkt = ldns_resolver_query(res, 198238104Sdes key_name, 199238104Sdes LDNS_RR_TYPE_DNSKEY, 200238104Sdes c, 201238104Sdes qflags); 202238104Sdes if (my_pkt) { 203238104Sdes signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt, 204238104Sdes key_name, 205238104Sdes LDNS_RR_TYPE_RRSIG, 206238104Sdes LDNS_SECTION_ANSWER); 207238104Sdes if (signatures2) { 208238104Sdes if (new_chain->signatures) { 209238104Sdes printf("There were already sigs!\n"); 210238104Sdes ldns_rr_list_deep_free(new_chain->signatures); 211238104Sdes printf("replacing the old sigs\n"); 212238104Sdes } 213238104Sdes new_chain->signatures = signatures2; 214238104Sdes } 215238104Sdes ldns_pkt_free(my_pkt); 216238104Sdes } 217238104Sdes} 218238104Sdes 219246827Sdesstatic ldns_dnssec_data_chain * 220238104Sdesldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res, 221238104Sdes uint16_t qflags, 222238104Sdes ldns_rr *orig_rr, 223238104Sdes const ldns_rr_list *rrset, 224238104Sdes ldns_dnssec_data_chain *new_chain) 225238104Sdes{ 226238104Sdes ldns_rdf *possible_parent_name; 227238104Sdes ldns_pkt *my_pkt; 228238104Sdes /* apparently we were not able to find a signing key, so 229238104Sdes we assume the chain ends here 230238104Sdes */ 231238104Sdes /* try parents for auth denial of DS */ 232238104Sdes if (orig_rr) { 233238104Sdes possible_parent_name = ldns_rr_owner(orig_rr); 234238104Sdes } else if (rrset && ldns_rr_list_rr_count(rrset) > 0) { 235238104Sdes possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0)); 236238104Sdes } else { 237238104Sdes /* no information to go on, give up */ 238238104Sdes return new_chain; 239238104Sdes } 240238104Sdes 241238104Sdes my_pkt = ldns_resolver_query(res, 242238104Sdes possible_parent_name, 243238104Sdes LDNS_RR_TYPE_DS, 244238104Sdes LDNS_RR_CLASS_IN, 245238104Sdes qflags); 246238104Sdes if (!my_pkt) { 247238104Sdes return new_chain; 248238104Sdes } 249238104Sdes 250238104Sdes if (ldns_pkt_ancount(my_pkt) > 0) { 251238104Sdes /* add error, no sigs but DS in parent */ 252238104Sdes /*ldns_pkt_print(stdout, my_pkt);*/ 253238104Sdes ldns_pkt_free(my_pkt); 254238104Sdes } else { 255238104Sdes /* are there signatures? */ 256238104Sdes new_chain->parent = ldns_dnssec_build_data_chain(res, 257238104Sdes qflags, 258238104Sdes NULL, 259238104Sdes my_pkt, 260238104Sdes NULL); 261238104Sdes 262238104Sdes new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; 263238104Sdes 264238104Sdes } 265238104Sdes return new_chain; 266238104Sdes} 267238104Sdes 268238104Sdes 269238104Sdesldns_dnssec_data_chain * 270238104Sdesldns_dnssec_build_data_chain(ldns_resolver *res, 271238104Sdes uint16_t qflags, 272238104Sdes const ldns_rr_list *rrset, 273238104Sdes const ldns_pkt *pkt, 274238104Sdes ldns_rr *orig_rr) 275238104Sdes{ 276238104Sdes ldns_rr_list *signatures = NULL; 277238104Sdes ldns_rr_list *dss = NULL; 278238104Sdes 279238104Sdes ldns_rr_list *my_rrset; 280238104Sdes 281238104Sdes ldns_pkt *my_pkt; 282238104Sdes 283238104Sdes ldns_rdf *name = NULL, *key_name = NULL; 284238104Sdes ldns_rr_type type = 0; 285238104Sdes ldns_rr_class c = 0; 286238104Sdes 287238104Sdes bool other_rrset = false; 288246854Sdes 289238104Sdes ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new(); 290238104Sdes 291246854Sdes assert(pkt != NULL); 292246854Sdes 293238104Sdes if (!ldns_dnssec_pkt_has_rrsigs(pkt)) { 294238104Sdes /* hmm. no dnssec data in the packet. go up to try and deny 295238104Sdes * DS? */ 296238104Sdes return new_chain; 297238104Sdes } 298238104Sdes 299238104Sdes if (orig_rr) { 300238104Sdes new_chain->rrset = ldns_rr_list_new(); 301238104Sdes ldns_rr_list_push_rr(new_chain->rrset, orig_rr); 302238104Sdes new_chain->parent = ldns_dnssec_build_data_chain(res, 303238104Sdes qflags, 304238104Sdes rrset, 305238104Sdes pkt, 306238104Sdes NULL); 307238104Sdes new_chain->packet_rcode = ldns_pkt_get_rcode(pkt); 308238104Sdes new_chain->packet_qtype = ldns_rr_get_type(orig_rr); 309238104Sdes if (ldns_pkt_ancount(pkt) == 0) { 310238104Sdes new_chain->packet_nodata = true; 311238104Sdes } 312238104Sdes return new_chain; 313238104Sdes } 314238104Sdes 315238104Sdes if (!rrset || ldns_rr_list_rr_count(rrset) < 1) { 316238104Sdes /* hmm, no data, do we have denial? only works if pkt was given, 317238104Sdes otherwise caller has to do the check himself */ 318238104Sdes new_chain->packet_nodata = true; 319238104Sdes if (pkt) { 320238104Sdes my_rrset = ldns_pkt_rr_list_by_type(pkt, 321238104Sdes LDNS_RR_TYPE_NSEC, 322238104Sdes LDNS_SECTION_ANY_NOQUESTION 323238104Sdes ); 324238104Sdes if (my_rrset) { 325238104Sdes if (ldns_rr_list_rr_count(my_rrset) > 0) { 326238104Sdes type = LDNS_RR_TYPE_NSEC; 327238104Sdes other_rrset = true; 328238104Sdes } else { 329238104Sdes ldns_rr_list_deep_free(my_rrset); 330238104Sdes my_rrset = NULL; 331238104Sdes } 332238104Sdes } else { 333238104Sdes /* nothing, try nsec3 */ 334238104Sdes my_rrset = ldns_pkt_rr_list_by_type(pkt, 335238104Sdes LDNS_RR_TYPE_NSEC3, 336238104Sdes LDNS_SECTION_ANY_NOQUESTION); 337238104Sdes if (my_rrset) { 338238104Sdes if (ldns_rr_list_rr_count(my_rrset) > 0) { 339238104Sdes type = LDNS_RR_TYPE_NSEC3; 340238104Sdes other_rrset = true; 341238104Sdes } else { 342238104Sdes ldns_rr_list_deep_free(my_rrset); 343238104Sdes my_rrset = NULL; 344238104Sdes } 345238104Sdes } else { 346238104Sdes /* nothing, stop */ 347238104Sdes /* try parent zone? for denied insecure? */ 348238104Sdes return new_chain; 349238104Sdes } 350238104Sdes } 351238104Sdes } else { 352238104Sdes return new_chain; 353238104Sdes } 354238104Sdes } else { 355238104Sdes my_rrset = (ldns_rr_list *) rrset; 356238104Sdes } 357238104Sdes 358238104Sdes if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) { 359238104Sdes new_chain->rrset = ldns_rr_list_clone(my_rrset); 360238104Sdes name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0)); 361238104Sdes type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0)); 362238104Sdes c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0)); 363238104Sdes } 364238104Sdes 365238104Sdes if (other_rrset) { 366238104Sdes ldns_rr_list_deep_free(my_rrset); 367238104Sdes } 368238104Sdes 369238104Sdes /* normally there will only be 1 signature 'set' 370238104Sdes but there can be more than 1 denial (wildcards) 371238104Sdes so check for NSEC 372238104Sdes */ 373238104Sdes if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) { 374238104Sdes /* just throw in all signatures, the tree builder must sort 375238104Sdes this out */ 376238104Sdes if (pkt) { 377238104Sdes signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); 378238104Sdes } else { 379238104Sdes my_pkt = ldns_resolver_query(res, name, type, c, qflags); 380238104Sdes if (my_pkt) { 381238104Sdes signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); 382238104Sdes ldns_pkt_free(my_pkt); 383238104Sdes } 384238104Sdes } 385238104Sdes } else { 386238104Sdes if (pkt) { 387238104Sdes signatures = 388238104Sdes ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, 389238104Sdes name, 390238104Sdes type); 391238104Sdes } 392238104Sdes if (!signatures) { 393238104Sdes my_pkt = ldns_resolver_query(res, name, type, c, qflags); 394238104Sdes if (my_pkt) { 395238104Sdes signatures = 396238104Sdes ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt, 397238104Sdes name, 398238104Sdes type); 399238104Sdes ldns_pkt_free(my_pkt); 400238104Sdes } 401238104Sdes } 402238104Sdes } 403238104Sdes 404238104Sdes if (signatures && ldns_rr_list_rr_count(signatures) > 0) { 405238104Sdes key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7); 406238104Sdes } 407238104Sdes if (!key_name) { 408246854Sdes if (signatures) { 409246854Sdes ldns_rr_list_deep_free(signatures); 410246854Sdes } 411238104Sdes return ldns_dnssec_build_data_chain_nokeyname(res, 412238104Sdes qflags, 413238104Sdes orig_rr, 414238104Sdes rrset, 415238104Sdes new_chain); 416238104Sdes } 417238104Sdes if (type != LDNS_RR_TYPE_DNSKEY) { 418238104Sdes ldns_dnssec_build_data_chain_dnskey(res, 419238104Sdes qflags, 420238104Sdes pkt, 421238104Sdes signatures, 422238104Sdes new_chain, 423238104Sdes key_name, 424238104Sdes c 425246854Sdes ); 426238104Sdes } else { 427238104Sdes ldns_dnssec_build_data_chain_other(res, 428238104Sdes qflags, 429238104Sdes new_chain, 430238104Sdes key_name, 431238104Sdes c, 432238104Sdes dss 433246854Sdes ); 434238104Sdes } 435238104Sdes if (signatures) { 436238104Sdes ldns_rr_list_deep_free(signatures); 437238104Sdes } 438238104Sdes return new_chain; 439238104Sdes} 440238104Sdes 441238104Sdesldns_dnssec_trust_tree * 442246827Sdesldns_dnssec_trust_tree_new(void) 443238104Sdes{ 444238104Sdes ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, 445238104Sdes 1); 446238104Sdes if(!new_tree) return NULL; 447238104Sdes new_tree->rr = NULL; 448238104Sdes new_tree->rrset = NULL; 449238104Sdes new_tree->parent_count = 0; 450238104Sdes 451238104Sdes return new_tree; 452238104Sdes} 453238104Sdes 454238104Sdesvoid 455238104Sdesldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree) 456238104Sdes{ 457238104Sdes size_t i; 458238104Sdes if (tree) { 459238104Sdes for (i = 0; i < tree->parent_count; i++) { 460238104Sdes ldns_dnssec_trust_tree_free(tree->parents[i]); 461238104Sdes } 462238104Sdes } 463238104Sdes LDNS_FREE(tree); 464238104Sdes} 465238104Sdes 466238104Sdessize_t 467238104Sdesldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree) 468238104Sdes{ 469238104Sdes size_t result = 0; 470238104Sdes size_t parent = 0; 471238104Sdes size_t i; 472238104Sdes 473238104Sdes for (i = 0; i < tree->parent_count; i++) { 474238104Sdes parent = ldns_dnssec_trust_tree_depth(tree->parents[i]); 475238104Sdes if (parent > result) { 476238104Sdes result = parent; 477238104Sdes } 478238104Sdes } 479238104Sdes return 1 + result; 480238104Sdes} 481238104Sdes 482238104Sdes/* TODO ldns_ */ 483238104Sdesstatic void 484238104Sdesprint_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth) 485238104Sdes{ 486238104Sdes size_t i; 487238104Sdes for (i = 0; i < nr; i++) { 488238104Sdes if (i == nr - 1) { 489238104Sdes fprintf(out, "|---"); 490238104Sdes } else if (map && i < treedepth && map[i] == 1) { 491238104Sdes fprintf(out, "| "); 492238104Sdes } else { 493238104Sdes fprintf(out, " "); 494238104Sdes } 495238104Sdes } 496238104Sdes} 497238104Sdes 498246827Sdesstatic void 499238104Sdesldns_dnssec_trust_tree_print_sm_fmt(FILE *out, 500238104Sdes const ldns_output_format *fmt, 501238104Sdes ldns_dnssec_trust_tree *tree, 502238104Sdes size_t tabs, 503238104Sdes bool extended, 504238104Sdes uint8_t *sibmap, 505238104Sdes size_t treedepth) 506238104Sdes{ 507238104Sdes size_t i; 508238104Sdes const ldns_rr_descriptor *descriptor; 509238104Sdes bool mapset = false; 510238104Sdes 511238104Sdes if (!sibmap) { 512238104Sdes treedepth = ldns_dnssec_trust_tree_depth(tree); 513238104Sdes sibmap = LDNS_XMALLOC(uint8_t, treedepth); 514238104Sdes if(!sibmap) 515238104Sdes return; /* mem err */ 516238104Sdes memset(sibmap, 0, treedepth); 517238104Sdes mapset = true; 518238104Sdes } 519238104Sdes 520238104Sdes if (tree) { 521238104Sdes if (tree->rr) { 522238104Sdes print_tabs(out, tabs, sibmap, treedepth); 523238104Sdes ldns_rdf_print(out, ldns_rr_owner(tree->rr)); 524238104Sdes descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr)); 525238104Sdes 526238104Sdes if (descriptor->_name) { 527238104Sdes fprintf(out, " (%s", descriptor->_name); 528238104Sdes } else { 529238104Sdes fprintf(out, " (TYPE%d", 530238104Sdes ldns_rr_get_type(tree->rr)); 531238104Sdes } 532238104Sdes if (tabs > 0) { 533238104Sdes if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) { 534238104Sdes fprintf(out, " keytag: %u", 535238104Sdes (unsigned int) ldns_calc_keytag(tree->rr)); 536238104Sdes fprintf(out, " alg: "); 537238104Sdes ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); 538238104Sdes fprintf(out, " flags: "); 539238104Sdes ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 540238104Sdes } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) { 541238104Sdes fprintf(out, " keytag: "); 542238104Sdes ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 543238104Sdes fprintf(out, " digest type: "); 544238104Sdes ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); 545238104Sdes } 546238104Sdes if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) { 547238104Sdes fprintf(out, " "); 548238104Sdes ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 549238104Sdes fprintf(out, " "); 550238104Sdes ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1)); 551238104Sdes } 552238104Sdes } 553238104Sdes 554238104Sdes fprintf(out, ")\n"); 555238104Sdes for (i = 0; i < tree->parent_count; i++) { 556238104Sdes if (tree->parent_count > 1 && i < tree->parent_count - 1) { 557238104Sdes sibmap[tabs] = 1; 558238104Sdes } else { 559238104Sdes sibmap[tabs] = 0; 560238104Sdes } 561238104Sdes /* only print errors */ 562238104Sdes if (ldns_rr_get_type(tree->parents[i]->rr) == 563238104Sdes LDNS_RR_TYPE_NSEC || 564238104Sdes ldns_rr_get_type(tree->parents[i]->rr) == 565238104Sdes LDNS_RR_TYPE_NSEC3) { 566238104Sdes if (tree->parent_status[i] == LDNS_STATUS_OK) { 567238104Sdes print_tabs(out, tabs + 1, sibmap, treedepth); 568238104Sdes if (tabs == 0 && 569238104Sdes ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS && 570238104Sdes ldns_rr_rd_count(tree->rr) > 0) { 571238104Sdes fprintf(out, "Existence of DS is denied by:\n"); 572238104Sdes } else { 573238104Sdes fprintf(out, "Existence is denied by:\n"); 574238104Sdes } 575238104Sdes } else { 576238104Sdes /* NS records aren't signed */ 577238104Sdes if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) { 578238104Sdes fprintf(out, "Existence of DS is denied by:\n"); 579238104Sdes } else { 580238104Sdes print_tabs(out, tabs + 1, sibmap, treedepth); 581238104Sdes fprintf(out, 582238104Sdes "Error in denial of existence: %s\n", 583238104Sdes ldns_get_errorstr_by_id( 584238104Sdes tree->parent_status[i])); 585238104Sdes } 586238104Sdes } 587238104Sdes } else 588238104Sdes if (tree->parent_status[i] != LDNS_STATUS_OK) { 589238104Sdes print_tabs(out, tabs + 1, sibmap, treedepth); 590238104Sdes fprintf(out, 591238104Sdes "%s:\n", 592238104Sdes ldns_get_errorstr_by_id( 593238104Sdes tree->parent_status[i])); 594238104Sdes if (tree->parent_status[i] 595238104Sdes == LDNS_STATUS_SSL_ERR) { 596238104Sdes printf("; SSL Error: "); 597238104Sdes ERR_load_crypto_strings(); 598238104Sdes ERR_print_errors_fp(stdout); 599238104Sdes printf("\n"); 600238104Sdes } 601238104Sdes ldns_rr_print_fmt(out, fmt, 602238104Sdes tree-> 603238104Sdes parent_signature[i]); 604238104Sdes printf("For RRset:\n"); 605238104Sdes ldns_rr_list_print_fmt(out, fmt, 606238104Sdes tree->rrset); 607238104Sdes printf("With key:\n"); 608238104Sdes ldns_rr_print_fmt(out, fmt, 609238104Sdes tree->parents[i]->rr); 610238104Sdes } 611238104Sdes ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 612238104Sdes tree->parents[i], 613238104Sdes tabs+1, 614238104Sdes extended, 615238104Sdes sibmap, 616238104Sdes treedepth); 617238104Sdes } 618238104Sdes } else { 619238104Sdes print_tabs(out, tabs, sibmap, treedepth); 620238104Sdes fprintf(out, "<no data>\n"); 621238104Sdes } 622238104Sdes } else { 623238104Sdes fprintf(out, "<null pointer>\n"); 624238104Sdes } 625238104Sdes 626238104Sdes if (mapset) { 627238104Sdes LDNS_FREE(sibmap); 628238104Sdes } 629238104Sdes} 630238104Sdes 631238104Sdesvoid 632238104Sdesldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt, 633238104Sdes ldns_dnssec_trust_tree *tree, 634238104Sdes size_t tabs, 635238104Sdes bool extended) 636238104Sdes{ 637238104Sdes ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 638238104Sdes tree, tabs, extended, NULL, 0); 639238104Sdes} 640238104Sdes 641238104Sdesvoid 642238104Sdesldns_dnssec_trust_tree_print(FILE *out, 643238104Sdes ldns_dnssec_trust_tree *tree, 644238104Sdes size_t tabs, 645238104Sdes bool extended) 646238104Sdes{ 647238104Sdes ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, 648238104Sdes tree, tabs, extended); 649238104Sdes} 650238104Sdes 651238104Sdes 652238104Sdesldns_status 653238104Sdesldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, 654238104Sdes const ldns_dnssec_trust_tree *parent, 655238104Sdes const ldns_rr *signature, 656238104Sdes const ldns_status parent_status) 657238104Sdes{ 658238104Sdes if (tree 659238104Sdes && parent 660238104Sdes && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) { 661238104Sdes /* 662238104Sdes printf("Add parent for: "); 663238104Sdes ldns_rr_print(stdout, tree->rr); 664238104Sdes printf("parent: "); 665238104Sdes ldns_rr_print(stdout, parent->rr); 666238104Sdes */ 667238104Sdes tree->parents[tree->parent_count] = 668238104Sdes (ldns_dnssec_trust_tree *) parent; 669238104Sdes tree->parent_status[tree->parent_count] = parent_status; 670238104Sdes tree->parent_signature[tree->parent_count] = (ldns_rr *) signature; 671238104Sdes tree->parent_count++; 672238104Sdes return LDNS_STATUS_OK; 673238104Sdes } else { 674238104Sdes return LDNS_STATUS_ERR; 675238104Sdes } 676238104Sdes} 677238104Sdes 678238104Sdes/* if rr is null, take the first from the rrset */ 679238104Sdesldns_dnssec_trust_tree * 680238104Sdesldns_dnssec_derive_trust_tree_time( 681238104Sdes ldns_dnssec_data_chain *data_chain, 682238104Sdes ldns_rr *rr, 683238104Sdes time_t check_time 684238104Sdes ) 685238104Sdes{ 686238104Sdes ldns_rr_list *cur_rrset; 687238104Sdes ldns_rr_list *cur_sigs; 688238104Sdes ldns_rr *cur_rr = NULL; 689238104Sdes ldns_rr *cur_sig_rr; 690238104Sdes size_t i, j; 691238104Sdes 692238104Sdes ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); 693238104Sdes if(!new_tree) 694238104Sdes return NULL; 695238104Sdes 696238104Sdes if (data_chain && data_chain->rrset) { 697238104Sdes cur_rrset = data_chain->rrset; 698238104Sdes 699238104Sdes cur_sigs = data_chain->signatures; 700238104Sdes 701238104Sdes if (rr) { 702238104Sdes cur_rr = rr; 703238104Sdes } 704238104Sdes 705238104Sdes if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) { 706238104Sdes cur_rr = ldns_rr_list_rr(cur_rrset, 0); 707238104Sdes } 708238104Sdes 709238104Sdes if (cur_rr) { 710238104Sdes new_tree->rr = cur_rr; 711238104Sdes new_tree->rrset = cur_rrset; 712238104Sdes /* there are three possibilities: 713238104Sdes 1 - 'normal' rrset, signed by a key 714238104Sdes 2 - dnskey signed by other dnskey 715238104Sdes 3 - dnskey proven by higher level DS 716238104Sdes (data denied by nsec is a special case that can 717238104Sdes occur in multiple places) 718238104Sdes 719238104Sdes */ 720238104Sdes if (cur_sigs) { 721238104Sdes for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { 722238104Sdes /* find the appropriate key in the parent list */ 723238104Sdes cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); 724238104Sdes 725238104Sdes if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { 726238104Sdes if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 727238104Sdes ldns_rr_owner(cur_rr))) 728238104Sdes { 729238104Sdes /* find first that does match */ 730238104Sdes 731238104Sdes for (j = 0; 732238104Sdes j < ldns_rr_list_rr_count(cur_rrset) && 733238104Sdes ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0; 734238104Sdes j++) { 735238104Sdes cur_rr = ldns_rr_list_rr(cur_rrset, j); 736238104Sdes 737238104Sdes } 738238104Sdes if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 739238104Sdes ldns_rr_owner(cur_rr))) 740238104Sdes { 741238104Sdes break; 742238104Sdes } 743238104Sdes } 744238104Sdes 745238104Sdes } 746238104Sdes /* option 1 */ 747238104Sdes if (data_chain->parent) { 748238104Sdes ldns_dnssec_derive_trust_tree_normal_rrset_time( 749238104Sdes new_tree, 750238104Sdes data_chain, 751238104Sdes cur_sig_rr, 752238104Sdes check_time); 753238104Sdes } 754238104Sdes 755238104Sdes /* option 2 */ 756238104Sdes ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 757238104Sdes new_tree, 758238104Sdes data_chain, 759238104Sdes cur_rr, 760238104Sdes cur_sig_rr, 761238104Sdes check_time); 762238104Sdes } 763238104Sdes 764238104Sdes ldns_dnssec_derive_trust_tree_ds_rrset_time( 765238104Sdes new_tree, data_chain, 766238104Sdes cur_rr, check_time); 767238104Sdes } else { 768238104Sdes /* no signatures? maybe it's nsec data */ 769238104Sdes 770238104Sdes /* just add every rr from parent as new parent */ 771238104Sdes ldns_dnssec_derive_trust_tree_no_sig_time( 772238104Sdes new_tree, data_chain, check_time); 773238104Sdes } 774238104Sdes } 775238104Sdes } 776238104Sdes 777238104Sdes return new_tree; 778238104Sdes} 779238104Sdes 780238104Sdesldns_dnssec_trust_tree * 781238104Sdesldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) 782238104Sdes{ 783238104Sdes return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL)); 784238104Sdes} 785238104Sdes 786238104Sdesvoid 787238104Sdesldns_dnssec_derive_trust_tree_normal_rrset_time( 788238104Sdes ldns_dnssec_trust_tree *new_tree, 789238104Sdes ldns_dnssec_data_chain *data_chain, 790238104Sdes ldns_rr *cur_sig_rr, 791238104Sdes time_t check_time) 792238104Sdes{ 793238104Sdes size_t i, j; 794238104Sdes ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 795238104Sdes ldns_dnssec_trust_tree *cur_parent_tree; 796238104Sdes ldns_rr *cur_parent_rr; 797238104Sdes uint16_t cur_keytag; 798238104Sdes ldns_rr_list *tmp_rrset = NULL; 799238104Sdes ldns_status cur_status; 800238104Sdes 801238104Sdes cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); 802238104Sdes 803238104Sdes for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) { 804238104Sdes cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); 805238104Sdes if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { 806238104Sdes if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) { 807238104Sdes 808238104Sdes /* TODO: check wildcard nsec too */ 809238104Sdes if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { 810238104Sdes tmp_rrset = cur_rrset; 811238104Sdes if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) 812238104Sdes == LDNS_RR_TYPE_NSEC || 813238104Sdes ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) 814238104Sdes == LDNS_RR_TYPE_NSEC3) { 815238104Sdes /* might contain different names! 816238104Sdes sort and split */ 817238104Sdes ldns_rr_list_sort(cur_rrset); 818246854Sdes assert(tmp_rrset == cur_rrset); 819238104Sdes tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset); 820238104Sdes 821238104Sdes /* with nsecs, this might be the wrong one */ 822238104Sdes while (tmp_rrset && 823238104Sdes ldns_rr_list_rr_count(cur_rrset) > 0 && 824238104Sdes ldns_dname_compare( 825238104Sdes ldns_rr_owner(ldns_rr_list_rr( 826238104Sdes tmp_rrset, 0)), 827238104Sdes ldns_rr_owner(cur_sig_rr)) != 0) { 828238104Sdes ldns_rr_list_deep_free(tmp_rrset); 829238104Sdes tmp_rrset = 830238104Sdes ldns_rr_list_pop_rrset(cur_rrset); 831238104Sdes } 832238104Sdes } 833238104Sdes cur_status = ldns_verify_rrsig_time( 834238104Sdes tmp_rrset, 835238104Sdes cur_sig_rr, 836238104Sdes cur_parent_rr, 837238104Sdes check_time); 838246854Sdes if (tmp_rrset && tmp_rrset != cur_rrset 839246854Sdes ) { 840246854Sdes ldns_rr_list_deep_free( 841246854Sdes tmp_rrset); 842246854Sdes tmp_rrset = NULL; 843246854Sdes } 844238104Sdes /* avoid dupes */ 845238104Sdes for (i = 0; i < new_tree->parent_count; i++) { 846238104Sdes if (cur_parent_rr == new_tree->parents[i]->rr) { 847238104Sdes goto done; 848238104Sdes } 849238104Sdes } 850238104Sdes 851238104Sdes cur_parent_tree = 852238104Sdes ldns_dnssec_derive_trust_tree_time( 853238104Sdes data_chain->parent, 854238104Sdes cur_parent_rr, 855238104Sdes check_time); 856238104Sdes (void)ldns_dnssec_trust_tree_add_parent(new_tree, 857238104Sdes cur_parent_tree, 858238104Sdes cur_sig_rr, 859238104Sdes cur_status); 860238104Sdes } 861238104Sdes } 862238104Sdes } 863238104Sdes } 864238104Sdes done: 865238104Sdes ldns_rr_list_deep_free(cur_rrset); 866238104Sdes} 867238104Sdes 868238104Sdesvoid 869238104Sdesldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, 870238104Sdes ldns_dnssec_data_chain *data_chain, 871238104Sdes ldns_rr *cur_sig_rr) 872238104Sdes{ 873238104Sdes ldns_dnssec_derive_trust_tree_normal_rrset_time( 874238104Sdes new_tree, data_chain, cur_sig_rr, ldns_time(NULL)); 875238104Sdes} 876238104Sdes 877238104Sdesvoid 878238104Sdesldns_dnssec_derive_trust_tree_dnskey_rrset_time( 879238104Sdes ldns_dnssec_trust_tree *new_tree, 880238104Sdes ldns_dnssec_data_chain *data_chain, 881238104Sdes ldns_rr *cur_rr, 882238104Sdes ldns_rr *cur_sig_rr, 883238104Sdes time_t check_time) 884238104Sdes{ 885238104Sdes size_t j; 886238104Sdes ldns_rr_list *cur_rrset = data_chain->rrset; 887238104Sdes ldns_dnssec_trust_tree *cur_parent_tree; 888238104Sdes ldns_rr *cur_parent_rr; 889238104Sdes uint16_t cur_keytag; 890238104Sdes ldns_status cur_status; 891238104Sdes 892238104Sdes cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); 893238104Sdes 894238104Sdes for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) { 895238104Sdes cur_parent_rr = ldns_rr_list_rr(cur_rrset, j); 896238104Sdes if (cur_parent_rr != cur_rr && 897238104Sdes ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { 898238104Sdes if (ldns_calc_keytag(cur_parent_rr) == cur_keytag 899238104Sdes ) { 900238104Sdes cur_parent_tree = ldns_dnssec_trust_tree_new(); 901238104Sdes cur_parent_tree->rr = cur_parent_rr; 902238104Sdes cur_parent_tree->rrset = cur_rrset; 903238104Sdes cur_status = ldns_verify_rrsig_time( 904238104Sdes cur_rrset, cur_sig_rr, 905238104Sdes cur_parent_rr, check_time); 906238104Sdes (void) ldns_dnssec_trust_tree_add_parent(new_tree, 907238104Sdes cur_parent_tree, cur_sig_rr, cur_status); 908238104Sdes } 909238104Sdes } 910238104Sdes } 911238104Sdes} 912238104Sdes 913238104Sdesvoid 914238104Sdesldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, 915238104Sdes ldns_dnssec_data_chain *data_chain, 916238104Sdes ldns_rr *cur_rr, 917238104Sdes ldns_rr *cur_sig_rr) 918238104Sdes{ 919238104Sdes ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 920238104Sdes new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL)); 921238104Sdes} 922238104Sdes 923238104Sdesvoid 924238104Sdesldns_dnssec_derive_trust_tree_ds_rrset_time( 925238104Sdes ldns_dnssec_trust_tree *new_tree, 926238104Sdes ldns_dnssec_data_chain *data_chain, 927238104Sdes ldns_rr *cur_rr, 928238104Sdes time_t check_time) 929238104Sdes{ 930238104Sdes size_t j, h; 931238104Sdes ldns_rr_list *cur_rrset = data_chain->rrset; 932238104Sdes ldns_dnssec_trust_tree *cur_parent_tree; 933238104Sdes ldns_rr *cur_parent_rr; 934238104Sdes 935238104Sdes /* try the parent to see whether there are DSs there */ 936238104Sdes if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY && 937238104Sdes data_chain->parent && 938238104Sdes data_chain->parent->rrset 939238104Sdes ) { 940238104Sdes for (j = 0; 941238104Sdes j < ldns_rr_list_rr_count(data_chain->parent->rrset); 942238104Sdes j++) { 943238104Sdes cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); 944238104Sdes if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) { 945238104Sdes for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) { 946238104Sdes cur_rr = ldns_rr_list_rr(cur_rrset, h); 947238104Sdes if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) { 948238104Sdes cur_parent_tree = 949238104Sdes ldns_dnssec_derive_trust_tree_time( 950238104Sdes data_chain->parent, 951238104Sdes cur_parent_rr, 952238104Sdes check_time); 953238104Sdes (void) ldns_dnssec_trust_tree_add_parent( 954238104Sdes new_tree, 955238104Sdes cur_parent_tree, 956238104Sdes NULL, 957238104Sdes LDNS_STATUS_OK); 958238104Sdes } else { 959238104Sdes /*ldns_rr_print(stdout, cur_parent_rr);*/ 960238104Sdes } 961238104Sdes } 962238104Sdes } 963238104Sdes } 964238104Sdes } 965238104Sdes} 966238104Sdes 967238104Sdesvoid 968238104Sdesldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, 969238104Sdes ldns_dnssec_data_chain *data_chain, 970238104Sdes ldns_rr *cur_rr) 971238104Sdes{ 972238104Sdes ldns_dnssec_derive_trust_tree_ds_rrset_time( 973238104Sdes new_tree, data_chain, cur_rr, ldns_time(NULL)); 974238104Sdes} 975238104Sdes 976238104Sdesvoid 977238104Sdesldns_dnssec_derive_trust_tree_no_sig_time( 978238104Sdes ldns_dnssec_trust_tree *new_tree, 979238104Sdes ldns_dnssec_data_chain *data_chain, 980238104Sdes time_t check_time) 981238104Sdes{ 982238104Sdes size_t i; 983238104Sdes ldns_rr_list *cur_rrset; 984238104Sdes ldns_rr *cur_parent_rr; 985238104Sdes ldns_dnssec_trust_tree *cur_parent_tree; 986238104Sdes ldns_status result; 987238104Sdes 988238104Sdes if (data_chain->parent && data_chain->parent->rrset) { 989238104Sdes cur_rrset = data_chain->parent->rrset; 990238104Sdes /* nsec? */ 991238104Sdes if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { 992238104Sdes if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == 993238104Sdes LDNS_RR_TYPE_NSEC3) { 994238104Sdes result = ldns_dnssec_verify_denial_nsec3( 995238104Sdes new_tree->rr, 996238104Sdes cur_rrset, 997238104Sdes data_chain->parent->signatures, 998238104Sdes data_chain->packet_rcode, 999238104Sdes data_chain->packet_qtype, 1000238104Sdes data_chain->packet_nodata); 1001238104Sdes } else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == 1002238104Sdes LDNS_RR_TYPE_NSEC) { 1003238104Sdes result = ldns_dnssec_verify_denial( 1004238104Sdes new_tree->rr, 1005238104Sdes cur_rrset, 1006238104Sdes data_chain->parent->signatures); 1007238104Sdes } else { 1008238104Sdes /* unsigned zone, unsigned parent */ 1009238104Sdes result = LDNS_STATUS_OK; 1010238104Sdes } 1011238104Sdes } else { 1012238104Sdes result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1013238104Sdes } 1014238104Sdes for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) { 1015238104Sdes cur_parent_rr = ldns_rr_list_rr(cur_rrset, i); 1016238104Sdes cur_parent_tree = 1017238104Sdes ldns_dnssec_derive_trust_tree_time( 1018238104Sdes data_chain->parent, 1019238104Sdes cur_parent_rr, 1020238104Sdes check_time); 1021238104Sdes (void) ldns_dnssec_trust_tree_add_parent(new_tree, 1022238104Sdes cur_parent_tree, NULL, result); 1023238104Sdes } 1024238104Sdes } 1025238104Sdes} 1026238104Sdes 1027238104Sdesvoid 1028238104Sdesldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, 1029238104Sdes ldns_dnssec_data_chain *data_chain) 1030238104Sdes{ 1031238104Sdes ldns_dnssec_derive_trust_tree_no_sig_time( 1032238104Sdes new_tree, data_chain, ldns_time(NULL)); 1033238104Sdes} 1034238104Sdes 1035238104Sdes/* 1036238104Sdes * returns OK if there is a path from tree to key with only OK 1037238104Sdes * the (first) error in between otherwise 1038238104Sdes * or NOT_FOUND if the key wasn't present at all 1039238104Sdes */ 1040238104Sdesldns_status 1041238104Sdesldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, 1042238104Sdes ldns_rr_list *trusted_keys) 1043238104Sdes{ 1044238104Sdes size_t i; 1045238104Sdes ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY; 1046238104Sdes bool equal; 1047238104Sdes ldns_status parent_result; 1048238104Sdes 1049238104Sdes if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0) 1050238104Sdes { if (tree->rr) { 1051238104Sdes for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { 1052238104Sdes equal = ldns_rr_compare_ds( 1053238104Sdes tree->rr, 1054238104Sdes ldns_rr_list_rr(trusted_keys, i)); 1055238104Sdes if (equal) { 1056238104Sdes result = LDNS_STATUS_OK; 1057238104Sdes return result; 1058238104Sdes } 1059238104Sdes } 1060238104Sdes } 1061238104Sdes for (i = 0; i < tree->parent_count; i++) { 1062238104Sdes parent_result = 1063238104Sdes ldns_dnssec_trust_tree_contains_keys(tree->parents[i], 1064238104Sdes trusted_keys); 1065238104Sdes if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) { 1066238104Sdes if (tree->parent_status[i] != LDNS_STATUS_OK) { 1067238104Sdes result = tree->parent_status[i]; 1068238104Sdes } else { 1069246854Sdes if (tree->rr && 1070246854Sdes ldns_rr_get_type(tree->rr) 1071238104Sdes == LDNS_RR_TYPE_NSEC && 1072238104Sdes parent_result == LDNS_STATUS_OK 1073238104Sdes ) { 1074238104Sdes result = 1075238104Sdes LDNS_STATUS_DNSSEC_EXISTENCE_DENIED; 1076238104Sdes } else { 1077238104Sdes result = parent_result; 1078238104Sdes } 1079238104Sdes } 1080238104Sdes } 1081238104Sdes } 1082238104Sdes } else { 1083238104Sdes result = LDNS_STATUS_ERR; 1084238104Sdes } 1085238104Sdes 1086238104Sdes return result; 1087238104Sdes} 1088238104Sdes 1089238104Sdesldns_status 1090238104Sdesldns_verify_time( 1091238104Sdes ldns_rr_list *rrset, 1092238104Sdes ldns_rr_list *rrsig, 1093238104Sdes const ldns_rr_list *keys, 1094238104Sdes time_t check_time, 1095238104Sdes ldns_rr_list *good_keys 1096238104Sdes ) 1097238104Sdes{ 1098238104Sdes uint16_t i; 1099238104Sdes ldns_status verify_result = LDNS_STATUS_ERR; 1100238104Sdes 1101238104Sdes if (!rrset || !rrsig || !keys) { 1102238104Sdes return LDNS_STATUS_ERR; 1103238104Sdes } 1104238104Sdes 1105238104Sdes if (ldns_rr_list_rr_count(rrset) < 1) { 1106238104Sdes return LDNS_STATUS_ERR; 1107238104Sdes } 1108238104Sdes 1109238104Sdes if (ldns_rr_list_rr_count(rrsig) < 1) { 1110238104Sdes return LDNS_STATUS_CRYPTO_NO_RRSIG; 1111238104Sdes } 1112238104Sdes 1113238104Sdes if (ldns_rr_list_rr_count(keys) < 1) { 1114238104Sdes verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 1115238104Sdes } else { 1116238104Sdes for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { 1117238104Sdes ldns_status s = ldns_verify_rrsig_keylist_time( 1118238104Sdes rrset, ldns_rr_list_rr(rrsig, i), 1119238104Sdes keys, check_time, good_keys); 1120238104Sdes /* try a little to get more descriptive error */ 1121238104Sdes if(s == LDNS_STATUS_OK) { 1122238104Sdes verify_result = LDNS_STATUS_OK; 1123238104Sdes } else if(verify_result == LDNS_STATUS_ERR) 1124238104Sdes verify_result = s; 1125238104Sdes else if(s != LDNS_STATUS_ERR && verify_result == 1126238104Sdes LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) 1127238104Sdes verify_result = s; 1128238104Sdes } 1129238104Sdes } 1130238104Sdes return verify_result; 1131238104Sdes} 1132238104Sdes 1133238104Sdesldns_status 1134238104Sdesldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 1135238104Sdes ldns_rr_list *good_keys) 1136238104Sdes{ 1137238104Sdes return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys); 1138238104Sdes} 1139238104Sdes 1140238104Sdesldns_status 1141238104Sdesldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig, 1142238104Sdes const ldns_rr_list *keys, ldns_rr_list *good_keys) 1143238104Sdes{ 1144238104Sdes uint16_t i; 1145238104Sdes ldns_status verify_result = LDNS_STATUS_ERR; 1146238104Sdes 1147238104Sdes if (!rrset || !rrsig || !keys) { 1148238104Sdes return LDNS_STATUS_ERR; 1149238104Sdes } 1150238104Sdes 1151238104Sdes if (ldns_rr_list_rr_count(rrset) < 1) { 1152238104Sdes return LDNS_STATUS_ERR; 1153238104Sdes } 1154238104Sdes 1155238104Sdes if (ldns_rr_list_rr_count(rrsig) < 1) { 1156238104Sdes return LDNS_STATUS_CRYPTO_NO_RRSIG; 1157238104Sdes } 1158238104Sdes 1159238104Sdes if (ldns_rr_list_rr_count(keys) < 1) { 1160238104Sdes verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 1161238104Sdes } else { 1162238104Sdes for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { 1163238104Sdes ldns_status s = ldns_verify_rrsig_keylist_notime(rrset, 1164238104Sdes ldns_rr_list_rr(rrsig, i), keys, good_keys); 1165238104Sdes 1166238104Sdes /* try a little to get more descriptive error */ 1167238104Sdes if (s == LDNS_STATUS_OK) { 1168238104Sdes verify_result = LDNS_STATUS_OK; 1169238104Sdes } else if (verify_result == LDNS_STATUS_ERR) { 1170238104Sdes verify_result = s; 1171238104Sdes } else if (s != LDNS_STATUS_ERR && verify_result == 1172238104Sdes LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { 1173238104Sdes verify_result = s; 1174238104Sdes } 1175238104Sdes } 1176238104Sdes } 1177238104Sdes return verify_result; 1178238104Sdes} 1179238104Sdes 1180238104Sdesldns_rr_list * 1181238104Sdesldns_fetch_valid_domain_keys_time(const ldns_resolver *res, 1182238104Sdes const ldns_rdf *domain, 1183238104Sdes const ldns_rr_list *keys, 1184238104Sdes time_t check_time, 1185238104Sdes ldns_status *status) 1186238104Sdes{ 1187238104Sdes ldns_rr_list * trusted_keys = NULL; 1188238104Sdes ldns_rr_list * ds_keys = NULL; 1189238104Sdes ldns_rdf * prev_parent_domain; 1190238104Sdes ldns_rdf * parent_domain; 1191238104Sdes ldns_rr_list * parent_keys = NULL; 1192238104Sdes 1193238104Sdes if (res && domain && keys) { 1194238104Sdes 1195238104Sdes if ((trusted_keys = ldns_validate_domain_dnskey_time(res, 1196238104Sdes domain, keys, check_time))) { 1197238104Sdes *status = LDNS_STATUS_OK; 1198238104Sdes } else { 1199238104Sdes /* No trusted keys in this domain, we'll have to find some in the parent domain */ 1200238104Sdes *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 1201238104Sdes 1202238104Sdes parent_domain = ldns_dname_left_chop(domain); 1203246854Sdes while (parent_domain && /* Fail if we are at the root*/ 1204246854Sdes ldns_rdf_size(parent_domain) > 0) { 1205238104Sdes 1206238104Sdes if ((parent_keys = 1207238104Sdes ldns_fetch_valid_domain_keys_time(res, 1208238104Sdes parent_domain, 1209238104Sdes keys, 1210238104Sdes check_time, 1211238104Sdes status))) { 1212238104Sdes /* Check DS records */ 1213238104Sdes if ((ds_keys = 1214238104Sdes ldns_validate_domain_ds_time(res, 1215238104Sdes domain, 1216238104Sdes parent_keys, 1217238104Sdes check_time))) { 1218238104Sdes trusted_keys = 1219238104Sdes ldns_fetch_valid_domain_keys_time( 1220238104Sdes res, 1221238104Sdes domain, 1222238104Sdes ds_keys, 1223238104Sdes check_time, 1224238104Sdes status); 1225238104Sdes ldns_rr_list_deep_free(ds_keys); 1226238104Sdes } else { 1227238104Sdes /* No valid DS at the parent -- fail */ 1228238104Sdes *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ; 1229238104Sdes } 1230238104Sdes ldns_rr_list_deep_free(parent_keys); 1231238104Sdes break; 1232238104Sdes } else { 1233238104Sdes parent_domain = ldns_dname_left_chop(( 1234238104Sdes prev_parent_domain 1235238104Sdes = parent_domain 1236238104Sdes )); 1237238104Sdes ldns_rdf_deep_free(prev_parent_domain); 1238238104Sdes } 1239238104Sdes } 1240246854Sdes if (parent_domain) { 1241246854Sdes ldns_rdf_deep_free(parent_domain); 1242246854Sdes } 1243238104Sdes } 1244238104Sdes } 1245238104Sdes return trusted_keys; 1246238104Sdes} 1247238104Sdes 1248238104Sdesldns_rr_list * 1249238104Sdesldns_fetch_valid_domain_keys(const ldns_resolver *res, 1250238104Sdes const ldns_rdf *domain, 1251238104Sdes const ldns_rr_list *keys, 1252238104Sdes ldns_status *status) 1253238104Sdes{ 1254238104Sdes return ldns_fetch_valid_domain_keys_time( 1255238104Sdes res, domain, keys, ldns_time(NULL), status); 1256238104Sdes} 1257238104Sdes 1258238104Sdesldns_rr_list * 1259238104Sdesldns_validate_domain_dnskey_time( 1260238104Sdes const ldns_resolver * res, 1261238104Sdes const ldns_rdf * domain, 1262238104Sdes const ldns_rr_list * keys, 1263238104Sdes time_t check_time 1264238104Sdes ) 1265238104Sdes{ 1266238104Sdes ldns_pkt * keypkt; 1267238104Sdes ldns_rr * cur_key; 1268238104Sdes uint16_t key_i; uint16_t key_j; uint16_t key_k; 1269238104Sdes uint16_t sig_i; ldns_rr * cur_sig; 1270238104Sdes 1271238104Sdes ldns_rr_list * domain_keys = NULL; 1272238104Sdes ldns_rr_list * domain_sigs = NULL; 1273238104Sdes ldns_rr_list * trusted_keys = NULL; 1274238104Sdes 1275238104Sdes /* Fetch keys for the domain */ 1276238104Sdes keypkt = ldns_resolver_query(res, domain, 1277238104Sdes LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD); 1278238104Sdes if (keypkt) { 1279238104Sdes domain_keys = ldns_pkt_rr_list_by_type(keypkt, 1280238104Sdes LDNS_RR_TYPE_DNSKEY, 1281238104Sdes LDNS_SECTION_ANSWER); 1282238104Sdes domain_sigs = ldns_pkt_rr_list_by_type(keypkt, 1283238104Sdes LDNS_RR_TYPE_RRSIG, 1284238104Sdes LDNS_SECTION_ANSWER); 1285238104Sdes 1286238104Sdes /* Try to validate the record using our keys */ 1287238104Sdes for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) { 1288238104Sdes 1289238104Sdes cur_key = ldns_rr_list_rr(domain_keys, key_i); 1290238104Sdes for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) { 1291238104Sdes if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j), 1292238104Sdes cur_key)) { 1293238104Sdes 1294238104Sdes /* Current key is trusted -- validate */ 1295238104Sdes trusted_keys = ldns_rr_list_new(); 1296238104Sdes 1297238104Sdes for (sig_i=0; 1298238104Sdes sig_i<ldns_rr_list_rr_count(domain_sigs); 1299238104Sdes sig_i++) { 1300238104Sdes cur_sig = ldns_rr_list_rr(domain_sigs, sig_i); 1301238104Sdes /* Avoid non-matching sigs */ 1302238104Sdes if (ldns_rdf2native_int16( 1303238104Sdes ldns_rr_rrsig_keytag(cur_sig)) 1304238104Sdes == ldns_calc_keytag(cur_key)) { 1305238104Sdes if (ldns_verify_rrsig_time( 1306238104Sdes domain_keys, 1307238104Sdes cur_sig, 1308238104Sdes cur_key, 1309238104Sdes check_time) 1310238104Sdes == LDNS_STATUS_OK) { 1311238104Sdes 1312238104Sdes /* Push the whole rrset 1313238104Sdes -- we can't do much more */ 1314238104Sdes for (key_k=0; 1315238104Sdes key_k<ldns_rr_list_rr_count( 1316238104Sdes domain_keys); 1317238104Sdes key_k++) { 1318238104Sdes ldns_rr_list_push_rr( 1319238104Sdes trusted_keys, 1320238104Sdes ldns_rr_clone( 1321238104Sdes ldns_rr_list_rr( 1322238104Sdes domain_keys, 1323238104Sdes key_k))); 1324238104Sdes } 1325238104Sdes 1326238104Sdes ldns_rr_list_deep_free(domain_keys); 1327238104Sdes ldns_rr_list_deep_free(domain_sigs); 1328238104Sdes ldns_pkt_free(keypkt); 1329238104Sdes return trusted_keys; 1330238104Sdes } 1331238104Sdes } 1332238104Sdes } 1333238104Sdes 1334238104Sdes /* Only push our trusted key */ 1335238104Sdes ldns_rr_list_push_rr(trusted_keys, 1336238104Sdes ldns_rr_clone(cur_key)); 1337238104Sdes } 1338238104Sdes } 1339238104Sdes } 1340238104Sdes 1341238104Sdes ldns_rr_list_deep_free(domain_keys); 1342238104Sdes ldns_rr_list_deep_free(domain_sigs); 1343238104Sdes ldns_pkt_free(keypkt); 1344238104Sdes 1345238104Sdes } else { 1346238104Sdes /* LDNS_STATUS_CRYPTO_NO_DNSKEY */ 1347238104Sdes } 1348238104Sdes 1349238104Sdes return trusted_keys; 1350238104Sdes} 1351238104Sdes 1352238104Sdesldns_rr_list * 1353238104Sdesldns_validate_domain_dnskey(const ldns_resolver * res, 1354238104Sdes const ldns_rdf * domain, 1355238104Sdes const ldns_rr_list * keys) 1356238104Sdes{ 1357238104Sdes return ldns_validate_domain_dnskey_time( 1358238104Sdes res, domain, keys, ldns_time(NULL)); 1359238104Sdes} 1360238104Sdes 1361238104Sdesldns_rr_list * 1362238104Sdesldns_validate_domain_ds_time( 1363238104Sdes const ldns_resolver *res, 1364238104Sdes const ldns_rdf * domain, 1365238104Sdes const ldns_rr_list * keys, 1366238104Sdes time_t check_time) 1367238104Sdes{ 1368238104Sdes ldns_pkt * dspkt; 1369238104Sdes uint16_t key_i; 1370238104Sdes ldns_rr_list * rrset = NULL; 1371238104Sdes ldns_rr_list * sigs = NULL; 1372238104Sdes ldns_rr_list * trusted_keys = NULL; 1373238104Sdes 1374238104Sdes /* Fetch DS for the domain */ 1375238104Sdes dspkt = ldns_resolver_query(res, domain, 1376238104Sdes LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD); 1377238104Sdes if (dspkt) { 1378238104Sdes rrset = ldns_pkt_rr_list_by_type(dspkt, 1379238104Sdes LDNS_RR_TYPE_DS, 1380238104Sdes LDNS_SECTION_ANSWER); 1381238104Sdes sigs = ldns_pkt_rr_list_by_type(dspkt, 1382238104Sdes LDNS_RR_TYPE_RRSIG, 1383238104Sdes LDNS_SECTION_ANSWER); 1384238104Sdes 1385238104Sdes /* Validate sigs */ 1386238104Sdes if (ldns_verify_time(rrset, sigs, keys, check_time, NULL) 1387238104Sdes == LDNS_STATUS_OK) { 1388238104Sdes trusted_keys = ldns_rr_list_new(); 1389238104Sdes for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) { 1390238104Sdes ldns_rr_list_push_rr(trusted_keys, 1391238104Sdes ldns_rr_clone(ldns_rr_list_rr(rrset, 1392238104Sdes key_i) 1393238104Sdes ) 1394238104Sdes ); 1395238104Sdes } 1396238104Sdes } 1397238104Sdes 1398238104Sdes ldns_rr_list_deep_free(rrset); 1399238104Sdes ldns_rr_list_deep_free(sigs); 1400238104Sdes ldns_pkt_free(dspkt); 1401238104Sdes 1402238104Sdes } else { 1403238104Sdes /* LDNS_STATUS_CRYPTO_NO_DS */ 1404238104Sdes } 1405238104Sdes 1406238104Sdes return trusted_keys; 1407238104Sdes} 1408238104Sdes 1409238104Sdesldns_rr_list * 1410238104Sdesldns_validate_domain_ds(const ldns_resolver *res, 1411238104Sdes const ldns_rdf * domain, 1412238104Sdes const ldns_rr_list * keys) 1413238104Sdes{ 1414238104Sdes return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL)); 1415238104Sdes} 1416238104Sdes 1417238104Sdesldns_status 1418238104Sdesldns_verify_trusted_time( 1419238104Sdes ldns_resolver *res, 1420238104Sdes ldns_rr_list *rrset, 1421238104Sdes ldns_rr_list * rrsigs, 1422238104Sdes time_t check_time, 1423238104Sdes ldns_rr_list * validating_keys 1424238104Sdes ) 1425238104Sdes{ 1426238104Sdes uint16_t sig_i; uint16_t key_i; 1427238104Sdes ldns_rr * cur_sig; ldns_rr * cur_key; 1428238104Sdes ldns_rr_list * trusted_keys = NULL; 1429238104Sdes ldns_status result = LDNS_STATUS_ERR; 1430238104Sdes 1431238104Sdes if (!res || !rrset || !rrsigs) { 1432238104Sdes return LDNS_STATUS_ERR; 1433238104Sdes } 1434238104Sdes 1435238104Sdes if (ldns_rr_list_rr_count(rrset) < 1) { 1436238104Sdes return LDNS_STATUS_ERR; 1437238104Sdes } 1438238104Sdes 1439238104Sdes if (ldns_rr_list_rr_count(rrsigs) < 1) { 1440238104Sdes return LDNS_STATUS_CRYPTO_NO_RRSIG; 1441238104Sdes } 1442238104Sdes 1443238104Sdes /* Look at each sig */ 1444238104Sdes for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) { 1445238104Sdes 1446238104Sdes cur_sig = ldns_rr_list_rr(rrsigs, sig_i); 1447238104Sdes /* Get a valid signer key and validate the sig */ 1448238104Sdes if ((trusted_keys = ldns_fetch_valid_domain_keys_time( 1449238104Sdes res, 1450238104Sdes ldns_rr_rrsig_signame(cur_sig), 1451238104Sdes ldns_resolver_dnssec_anchors(res), 1452238104Sdes check_time, 1453238104Sdes &result))) { 1454238104Sdes 1455238104Sdes for (key_i = 0; 1456238104Sdes key_i < ldns_rr_list_rr_count(trusted_keys); 1457238104Sdes key_i++) { 1458238104Sdes cur_key = ldns_rr_list_rr(trusted_keys, key_i); 1459238104Sdes 1460238104Sdes if ((result = ldns_verify_rrsig_time(rrset, 1461238104Sdes cur_sig, 1462238104Sdes cur_key, 1463238104Sdes check_time)) 1464238104Sdes == LDNS_STATUS_OK) { 1465238104Sdes if (validating_keys) { 1466238104Sdes ldns_rr_list_push_rr(validating_keys, 1467238104Sdes ldns_rr_clone(cur_key)); 1468238104Sdes } 1469238104Sdes ldns_rr_list_deep_free(trusted_keys); 1470238104Sdes return LDNS_STATUS_OK; 1471238104Sdes } 1472238104Sdes } 1473238104Sdes } 1474238104Sdes } 1475238104Sdes 1476238104Sdes ldns_rr_list_deep_free(trusted_keys); 1477238104Sdes return result; 1478238104Sdes} 1479238104Sdes 1480238104Sdesldns_status 1481238104Sdesldns_verify_trusted( 1482238104Sdes ldns_resolver *res, 1483238104Sdes ldns_rr_list *rrset, 1484238104Sdes ldns_rr_list * rrsigs, 1485238104Sdes ldns_rr_list * validating_keys) 1486238104Sdes{ 1487238104Sdes return ldns_verify_trusted_time( 1488238104Sdes res, rrset, rrsigs, ldns_time(NULL), validating_keys); 1489238104Sdes} 1490238104Sdes 1491238104Sdes 1492238104Sdesldns_status 1493238104Sdesldns_dnssec_verify_denial(ldns_rr *rr, 1494238104Sdes ldns_rr_list *nsecs, 1495238104Sdes ldns_rr_list *rrsigs) 1496238104Sdes{ 1497238104Sdes ldns_rdf *rr_name; 1498238104Sdes ldns_rdf *wildcard_name; 1499238104Sdes ldns_rdf *chopped_dname; 1500238104Sdes ldns_rr *cur_nsec; 1501238104Sdes size_t i; 1502238104Sdes ldns_status result; 1503238104Sdes /* needed for wildcard check on exact match */ 1504238104Sdes ldns_rr *rrsig; 1505238104Sdes bool name_covered = false; 1506238104Sdes bool type_covered = false; 1507238104Sdes bool wildcard_covered = false; 1508238104Sdes bool wildcard_type_covered = false; 1509238104Sdes 1510238104Sdes wildcard_name = ldns_dname_new_frm_str("*"); 1511238104Sdes rr_name = ldns_rr_owner(rr); 1512238104Sdes chopped_dname = ldns_dname_left_chop(rr_name); 1513238104Sdes result = ldns_dname_cat(wildcard_name, chopped_dname); 1514246854Sdes ldns_rdf_deep_free(chopped_dname); 1515238104Sdes if (result != LDNS_STATUS_OK) { 1516238104Sdes return result; 1517238104Sdes } 1518238104Sdes 1519238104Sdes for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1520238104Sdes cur_nsec = ldns_rr_list_rr(nsecs, i); 1521238104Sdes if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { 1522238104Sdes /* see section 5.4 of RFC4035, if the label count of the NSEC's 1523238104Sdes RRSIG is equal, then it is proven that wildcard expansion 1524238104Sdes could not have been used to match the request */ 1525238104Sdes rrsig = ldns_dnssec_get_rrsig_for_name_and_type( 1526238104Sdes ldns_rr_owner(cur_nsec), 1527238104Sdes ldns_rr_get_type(cur_nsec), 1528238104Sdes rrsigs); 1529238104Sdes if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig)) 1530238104Sdes == ldns_dname_label_count(rr_name)) { 1531238104Sdes wildcard_covered = true; 1532238104Sdes } 1533238104Sdes 1534238104Sdes if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), 1535238104Sdes ldns_rr_get_type(rr))) { 1536238104Sdes type_covered = true; 1537238104Sdes } 1538238104Sdes } 1539238104Sdes if (ldns_nsec_covers_name(cur_nsec, rr_name)) { 1540238104Sdes name_covered = true; 1541238104Sdes } 1542238104Sdes 1543238104Sdes if (ldns_dname_compare(wildcard_name, 1544238104Sdes ldns_rr_owner(cur_nsec)) == 0) { 1545238104Sdes if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), 1546238104Sdes ldns_rr_get_type(rr))) { 1547238104Sdes wildcard_type_covered = true; 1548238104Sdes } 1549238104Sdes } 1550238104Sdes 1551238104Sdes if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { 1552238104Sdes wildcard_covered = true; 1553238104Sdes } 1554238104Sdes 1555238104Sdes } 1556238104Sdes 1557238104Sdes ldns_rdf_deep_free(wildcard_name); 1558238104Sdes 1559238104Sdes if (type_covered || !name_covered) { 1560238104Sdes return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1561238104Sdes } 1562238104Sdes 1563238104Sdes if (wildcard_type_covered || !wildcard_covered) { 1564238104Sdes return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; 1565238104Sdes } 1566238104Sdes 1567238104Sdes return LDNS_STATUS_OK; 1568238104Sdes} 1569238104Sdes 1570238104Sdesldns_status 1571238104Sdesldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr 1572238104Sdes , ldns_rr_list *nsecs 1573238104Sdes , ATTR_UNUSED(ldns_rr_list *rrsigs) 1574238104Sdes , ldns_pkt_rcode packet_rcode 1575238104Sdes , ldns_rr_type packet_qtype 1576238104Sdes , bool packet_nodata 1577238104Sdes , ldns_rr **match 1578238104Sdes ) 1579238104Sdes{ 1580238104Sdes ldns_rdf *closest_encloser; 1581238104Sdes ldns_rdf *wildcard; 1582238104Sdes ldns_rdf *hashed_wildcard_name; 1583238104Sdes bool wildcard_covered = false; 1584238104Sdes ldns_rdf *zone_name; 1585238104Sdes ldns_rdf *hashed_name; 1586238104Sdes /* self assignment to suppress uninitialized warning */ 1587238104Sdes ldns_rdf *next_closer = next_closer; 1588238104Sdes ldns_rdf *hashed_next_closer; 1589238104Sdes size_t i; 1590238104Sdes ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1591238104Sdes 1592238104Sdes if (match) { 1593238104Sdes *match = NULL; 1594238104Sdes } 1595238104Sdes 1596238104Sdes zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); 1597238104Sdes 1598238104Sdes /* section 8.4 */ 1599238104Sdes if (packet_rcode == LDNS_RCODE_NXDOMAIN) { 1600238104Sdes closest_encloser = ldns_dnssec_nsec3_closest_encloser( 1601238104Sdes ldns_rr_owner(rr), 1602238104Sdes ldns_rr_get_type(rr), 1603238104Sdes nsecs); 1604238104Sdes if(!closest_encloser) { 1605246854Sdes result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1606238104Sdes goto done; 1607238104Sdes } 1608238104Sdes 1609238104Sdes wildcard = ldns_dname_new_frm_str("*"); 1610238104Sdes (void) ldns_dname_cat(wildcard, closest_encloser); 1611238104Sdes 1612238104Sdes for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1613238104Sdes hashed_wildcard_name = 1614238104Sdes ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), 1615238104Sdes wildcard 1616238104Sdes ); 1617238104Sdes (void) ldns_dname_cat(hashed_wildcard_name, zone_name); 1618238104Sdes 1619238104Sdes if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), 1620238104Sdes hashed_wildcard_name)) { 1621238104Sdes wildcard_covered = true; 1622238104Sdes if (match) { 1623238104Sdes *match = ldns_rr_list_rr(nsecs, i); 1624238104Sdes } 1625238104Sdes } 1626238104Sdes ldns_rdf_deep_free(hashed_wildcard_name); 1627238104Sdes } 1628238104Sdes 1629246854Sdes if (! wildcard_covered) { 1630246854Sdes result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; 1631246854Sdes } else { 1632246854Sdes result = LDNS_STATUS_OK; 1633246854Sdes } 1634238104Sdes ldns_rdf_deep_free(closest_encloser); 1635238104Sdes ldns_rdf_deep_free(wildcard); 1636238104Sdes 1637238104Sdes } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { 1638238104Sdes /* section 8.5 */ 1639238104Sdes hashed_name = ldns_nsec3_hash_name_frm_nsec3( 1640238104Sdes ldns_rr_list_rr(nsecs, 0), 1641238104Sdes ldns_rr_owner(rr)); 1642238104Sdes (void) ldns_dname_cat(hashed_name, zone_name); 1643238104Sdes for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1644238104Sdes if (ldns_dname_compare(hashed_name, 1645238104Sdes ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) 1646238104Sdes == 0) { 1647238104Sdes if (!ldns_nsec_bitmap_covers_type( 1648238104Sdes ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1649238104Sdes packet_qtype) 1650238104Sdes && 1651238104Sdes !ldns_nsec_bitmap_covers_type( 1652238104Sdes ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1653238104Sdes LDNS_RR_TYPE_CNAME)) { 1654238104Sdes result = LDNS_STATUS_OK; 1655238104Sdes if (match) { 1656238104Sdes *match = ldns_rr_list_rr(nsecs, i); 1657238104Sdes } 1658238104Sdes goto done; 1659238104Sdes } 1660238104Sdes } 1661238104Sdes } 1662238104Sdes result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1663238104Sdes /* wildcard no data? section 8.7 */ 1664238104Sdes closest_encloser = ldns_dnssec_nsec3_closest_encloser( 1665238104Sdes ldns_rr_owner(rr), 1666238104Sdes ldns_rr_get_type(rr), 1667238104Sdes nsecs); 1668238104Sdes if(!closest_encloser) { 1669238104Sdes result = LDNS_STATUS_NSEC3_ERR; 1670238104Sdes goto done; 1671238104Sdes } 1672238104Sdes wildcard = ldns_dname_new_frm_str("*"); 1673238104Sdes (void) ldns_dname_cat(wildcard, closest_encloser); 1674238104Sdes for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1675238104Sdes hashed_wildcard_name = 1676238104Sdes ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), 1677238104Sdes wildcard); 1678238104Sdes (void) ldns_dname_cat(hashed_wildcard_name, zone_name); 1679238104Sdes 1680238104Sdes if (ldns_dname_compare(hashed_wildcard_name, 1681238104Sdes ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) 1682238104Sdes == 0) { 1683238104Sdes if (!ldns_nsec_bitmap_covers_type( 1684238104Sdes ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1685238104Sdes packet_qtype) 1686238104Sdes && 1687238104Sdes !ldns_nsec_bitmap_covers_type( 1688238104Sdes ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1689238104Sdes LDNS_RR_TYPE_CNAME)) { 1690238104Sdes result = LDNS_STATUS_OK; 1691238104Sdes if (match) { 1692238104Sdes *match = ldns_rr_list_rr(nsecs, i); 1693238104Sdes } 1694238104Sdes } 1695238104Sdes } 1696238104Sdes ldns_rdf_deep_free(hashed_wildcard_name); 1697238104Sdes if (result == LDNS_STATUS_OK) { 1698238104Sdes break; 1699238104Sdes } 1700238104Sdes } 1701238104Sdes ldns_rdf_deep_free(closest_encloser); 1702238104Sdes ldns_rdf_deep_free(wildcard); 1703238104Sdes } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) { 1704238104Sdes /* section 8.6 */ 1705238104Sdes /* note: up to XXX this is the same as for 8.5 */ 1706238104Sdes hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 1707238104Sdes 0), 1708238104Sdes ldns_rr_owner(rr) 1709238104Sdes ); 1710238104Sdes (void) ldns_dname_cat(hashed_name, zone_name); 1711238104Sdes for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1712238104Sdes if (ldns_dname_compare(hashed_name, 1713238104Sdes ldns_rr_owner(ldns_rr_list_rr(nsecs, 1714238104Sdes i))) 1715238104Sdes == 0) { 1716238104Sdes if (!ldns_nsec_bitmap_covers_type( 1717238104Sdes ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1718238104Sdes LDNS_RR_TYPE_DS) 1719238104Sdes && 1720238104Sdes !ldns_nsec_bitmap_covers_type( 1721238104Sdes ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1722238104Sdes LDNS_RR_TYPE_CNAME)) { 1723238104Sdes result = LDNS_STATUS_OK; 1724238104Sdes if (match) { 1725238104Sdes *match = ldns_rr_list_rr(nsecs, i); 1726238104Sdes } 1727238104Sdes goto done; 1728238104Sdes } 1729238104Sdes } 1730238104Sdes } 1731238104Sdes 1732238104Sdes /* XXX see note above */ 1733238104Sdes result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1734238104Sdes 1735238104Sdes closest_encloser = ldns_dnssec_nsec3_closest_encloser( 1736238104Sdes ldns_rr_owner(rr), 1737238104Sdes ldns_rr_get_type(rr), 1738238104Sdes nsecs); 1739238104Sdes if(!closest_encloser) { 1740238104Sdes result = LDNS_STATUS_NSEC3_ERR; 1741238104Sdes goto done; 1742238104Sdes } 1743238104Sdes /* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/ 1744238104Sdes 1745238104Sdes if (ldns_dname_label_count(closest_encloser) + 1 1746238104Sdes >= ldns_dname_label_count(ldns_rr_owner(rr))) { 1747238104Sdes 1748238104Sdes /* Query name *is* the "next closer". */ 1749238104Sdes hashed_next_closer = hashed_name; 1750238104Sdes } else { 1751238104Sdes 1752238104Sdes /* "next closer" has less labels than the query name. 1753238104Sdes * Create the name and hash it. 1754238104Sdes */ 1755238104Sdes next_closer = ldns_dname_clone_from( 1756238104Sdes ldns_rr_owner(rr), 1757238104Sdes ldns_dname_label_count(ldns_rr_owner(rr)) 1758238104Sdes - (ldns_dname_label_count(closest_encloser) + 1) 1759238104Sdes ); 1760238104Sdes hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3( 1761238104Sdes ldns_rr_list_rr(nsecs, 0), 1762238104Sdes next_closer 1763238104Sdes ); 1764238104Sdes (void) ldns_dname_cat(hashed_next_closer, zone_name); 1765238104Sdes } 1766238104Sdes /* Find the NSEC3 that covers the "next closer" */ 1767238104Sdes for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1768238104Sdes if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), 1769238104Sdes hashed_next_closer) && 1770238104Sdes ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) { 1771238104Sdes 1772238104Sdes result = LDNS_STATUS_OK; 1773238104Sdes if (match) { 1774238104Sdes *match = ldns_rr_list_rr(nsecs, i); 1775238104Sdes } 1776238104Sdes break; 1777238104Sdes } 1778238104Sdes } 1779238104Sdes if (ldns_dname_label_count(closest_encloser) + 1 1780238104Sdes < ldns_dname_label_count(ldns_rr_owner(rr))) { 1781238104Sdes 1782238104Sdes /* "next closer" has less labels than the query name. 1783238104Sdes * Dispose of the temporary variables that held that name. 1784238104Sdes */ 1785238104Sdes ldns_rdf_deep_free(hashed_next_closer); 1786238104Sdes ldns_rdf_deep_free(next_closer); 1787238104Sdes } 1788238104Sdes ldns_rdf_deep_free(closest_encloser); 1789238104Sdes } 1790238104Sdes 1791238104Sdes done: 1792238104Sdes ldns_rdf_deep_free(zone_name); 1793238104Sdes return result; 1794238104Sdes} 1795238104Sdes 1796238104Sdesldns_status 1797238104Sdesldns_dnssec_verify_denial_nsec3(ldns_rr *rr, 1798238104Sdes ldns_rr_list *nsecs, 1799238104Sdes ldns_rr_list *rrsigs, 1800238104Sdes ldns_pkt_rcode packet_rcode, 1801238104Sdes ldns_rr_type packet_qtype, 1802238104Sdes bool packet_nodata) 1803238104Sdes{ 1804238104Sdes return ldns_dnssec_verify_denial_nsec3_match( 1805238104Sdes rr, nsecs, rrsigs, packet_rcode, 1806238104Sdes packet_qtype, packet_nodata, NULL 1807238104Sdes ); 1808238104Sdes} 1809238104Sdes 1810238104Sdes#ifdef USE_GOST 1811238104SdesEVP_PKEY* 1812238104Sdesldns_gost2pkey_raw(unsigned char* key, size_t keylen) 1813238104Sdes{ 1814238104Sdes /* prefix header for X509 encoding */ 1815238104Sdes uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 1816238104Sdes 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 1817238104Sdes 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 1818238104Sdes 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; 1819238104Sdes unsigned char encoded[37+64]; 1820238104Sdes const unsigned char* pp; 1821238104Sdes if(keylen != 64) { 1822238104Sdes /* key wrong size */ 1823238104Sdes return NULL; 1824238104Sdes } 1825238104Sdes 1826238104Sdes /* create evp_key */ 1827238104Sdes memmove(encoded, asn, 37); 1828238104Sdes memmove(encoded+37, key, 64); 1829238104Sdes pp = (unsigned char*)&encoded[0]; 1830238104Sdes 1831238104Sdes return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 1832238104Sdes} 1833238104Sdes 1834238104Sdesstatic ldns_status 1835238104Sdesldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, 1836238104Sdes ldns_buffer* rrset, unsigned char* key, size_t keylen) 1837238104Sdes{ 1838238104Sdes EVP_PKEY *evp_key; 1839238104Sdes ldns_status result; 1840238104Sdes 1841238104Sdes (void) ldns_key_EVP_load_gost_id(); 1842238104Sdes evp_key = ldns_gost2pkey_raw(key, keylen); 1843238104Sdes if(!evp_key) { 1844238104Sdes /* could not convert key */ 1845238104Sdes return LDNS_STATUS_CRYPTO_BOGUS; 1846238104Sdes } 1847238104Sdes 1848238104Sdes /* verify signature */ 1849238104Sdes result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, 1850238104Sdes evp_key, EVP_get_digestbyname("md_gost94")); 1851238104Sdes EVP_PKEY_free(evp_key); 1852238104Sdes 1853238104Sdes return result; 1854238104Sdes} 1855238104Sdes#endif 1856238104Sdes 1857238104Sdes#ifdef USE_ECDSA 1858238104SdesEVP_PKEY* 1859238104Sdesldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 1860238104Sdes{ 1861238104Sdes unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 1862238104Sdes const unsigned char* pp = buf; 1863238104Sdes EVP_PKEY *evp_key; 1864238104Sdes EC_KEY *ec; 1865238104Sdes /* check length, which uncompressed must be 2 bignums */ 1866238104Sdes if(algo == LDNS_ECDSAP256SHA256) { 1867238104Sdes if(keylen != 2*256/8) return NULL; 1868238104Sdes ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 1869238104Sdes } else if(algo == LDNS_ECDSAP384SHA384) { 1870238104Sdes if(keylen != 2*384/8) return NULL; 1871238104Sdes ec = EC_KEY_new_by_curve_name(NID_secp384r1); 1872238104Sdes } else ec = NULL; 1873238104Sdes if(!ec) return NULL; 1874238104Sdes if(keylen+1 > sizeof(buf)) 1875238104Sdes return NULL; /* sanity check */ 1876238104Sdes /* prepend the 0x02 (from docs) (or actually 0x04 from implementation 1877238104Sdes * of openssl) for uncompressed data */ 1878238104Sdes buf[0] = POINT_CONVERSION_UNCOMPRESSED; 1879238104Sdes memmove(buf+1, key, keylen); 1880238104Sdes if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { 1881238104Sdes EC_KEY_free(ec); 1882238104Sdes return NULL; 1883238104Sdes } 1884238104Sdes evp_key = EVP_PKEY_new(); 1885238104Sdes if(!evp_key) { 1886238104Sdes EC_KEY_free(ec); 1887238104Sdes return NULL; 1888238104Sdes } 1889238104Sdes if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 1890238104Sdes EVP_PKEY_free(evp_key); 1891238104Sdes EC_KEY_free(ec); 1892238104Sdes return NULL; 1893238104Sdes } 1894238104Sdes return evp_key; 1895238104Sdes} 1896238104Sdes 1897238104Sdesstatic ldns_status 1898238104Sdesldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, 1899238104Sdes ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo) 1900238104Sdes{ 1901238104Sdes EVP_PKEY *evp_key; 1902238104Sdes ldns_status result; 1903238104Sdes const EVP_MD *d; 1904238104Sdes 1905238104Sdes evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo); 1906238104Sdes if(!evp_key) { 1907238104Sdes /* could not convert key */ 1908238104Sdes return LDNS_STATUS_CRYPTO_BOGUS; 1909238104Sdes } 1910238104Sdes if(algo == LDNS_ECDSAP256SHA256) 1911238104Sdes d = EVP_sha256(); 1912238104Sdes else d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */ 1913238104Sdes result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d); 1914238104Sdes EVP_PKEY_free(evp_key); 1915238104Sdes return result; 1916238104Sdes} 1917238104Sdes#endif 1918238104Sdes 1919238104Sdesldns_status 1920238104Sdesldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 1921238104Sdes ldns_buffer *key_buf, uint8_t algo) 1922238104Sdes{ 1923238104Sdes return ldns_verify_rrsig_buffers_raw( 1924238104Sdes (unsigned char*)ldns_buffer_begin(rawsig_buf), 1925238104Sdes ldns_buffer_position(rawsig_buf), 1926238104Sdes verify_buf, 1927238104Sdes (unsigned char*)ldns_buffer_begin(key_buf), 1928238104Sdes ldns_buffer_position(key_buf), algo); 1929238104Sdes} 1930238104Sdes 1931238104Sdesldns_status 1932238104Sdesldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen, 1933238104Sdes ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 1934238104Sdes uint8_t algo) 1935238104Sdes{ 1936238104Sdes /* check for right key */ 1937238104Sdes switch(algo) { 1938238104Sdes case LDNS_DSA: 1939238104Sdes case LDNS_DSA_NSEC3: 1940238104Sdes return ldns_verify_rrsig_dsa_raw(sig, 1941238104Sdes siglen, 1942238104Sdes verify_buf, 1943238104Sdes key, 1944238104Sdes keylen); 1945238104Sdes break; 1946238104Sdes case LDNS_RSASHA1: 1947238104Sdes case LDNS_RSASHA1_NSEC3: 1948238104Sdes return ldns_verify_rrsig_rsasha1_raw(sig, 1949238104Sdes siglen, 1950238104Sdes verify_buf, 1951238104Sdes key, 1952238104Sdes keylen); 1953238104Sdes break; 1954238104Sdes#ifdef USE_SHA2 1955238104Sdes case LDNS_RSASHA256: 1956238104Sdes return ldns_verify_rrsig_rsasha256_raw(sig, 1957238104Sdes siglen, 1958238104Sdes verify_buf, 1959238104Sdes key, 1960238104Sdes keylen); 1961238104Sdes break; 1962238104Sdes case LDNS_RSASHA512: 1963238104Sdes return ldns_verify_rrsig_rsasha512_raw(sig, 1964238104Sdes siglen, 1965238104Sdes verify_buf, 1966238104Sdes key, 1967238104Sdes keylen); 1968238104Sdes break; 1969238104Sdes#endif 1970238104Sdes#ifdef USE_GOST 1971238104Sdes case LDNS_ECC_GOST: 1972238104Sdes return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf, 1973238104Sdes key, keylen); 1974238104Sdes break; 1975238104Sdes#endif 1976238104Sdes#ifdef USE_ECDSA 1977238104Sdes case LDNS_ECDSAP256SHA256: 1978238104Sdes case LDNS_ECDSAP384SHA384: 1979238104Sdes return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf, 1980238104Sdes key, keylen, algo); 1981238104Sdes break; 1982238104Sdes#endif 1983238104Sdes case LDNS_RSAMD5: 1984238104Sdes return ldns_verify_rrsig_rsamd5_raw(sig, 1985238104Sdes siglen, 1986238104Sdes verify_buf, 1987238104Sdes key, 1988238104Sdes keylen); 1989238104Sdes break; 1990238104Sdes default: 1991238104Sdes /* do you know this alg?! */ 1992238104Sdes return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 1993238104Sdes } 1994238104Sdes} 1995238104Sdes 1996238104Sdes 1997238104Sdes/** 1998238104Sdes * Reset the ttl in the rrset with the orig_ttl from the sig 1999238104Sdes * and update owner name if it was wildcard 2000238104Sdes * Also canonicalizes the rrset. 2001238104Sdes * @param rrset: rrset to modify 2002238104Sdes * @param sig: signature to take TTL and wildcard values from 2003238104Sdes */ 2004238104Sdesstatic void 2005238104Sdesldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig) 2006238104Sdes{ 2007238104Sdes uint32_t orig_ttl; 2008238104Sdes uint16_t i; 2009238104Sdes uint8_t label_count; 2010238104Sdes ldns_rdf *wildcard_name; 2011238104Sdes ldns_rdf *wildcard_chopped; 2012238104Sdes ldns_rdf *wildcard_chopped_tmp; 2013238104Sdes 2014238104Sdes if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) { 2015238104Sdes return; 2016238104Sdes } 2017238104Sdes 2018238104Sdes orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3)); 2019238104Sdes label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2)); 2020238104Sdes 2021238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { 2022238104Sdes if (label_count < 2023238104Sdes ldns_dname_label_count( 2024238104Sdes ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { 2025238104Sdes (void) ldns_str2rdf_dname(&wildcard_name, "*"); 2026238104Sdes wildcard_chopped = ldns_rdf_clone(ldns_rr_owner( 2027238104Sdes ldns_rr_list_rr(rrset_clone, i))); 2028238104Sdes while (label_count < ldns_dname_label_count(wildcard_chopped)) { 2029238104Sdes wildcard_chopped_tmp = ldns_dname_left_chop( 2030238104Sdes wildcard_chopped); 2031238104Sdes ldns_rdf_deep_free(wildcard_chopped); 2032238104Sdes wildcard_chopped = wildcard_chopped_tmp; 2033238104Sdes } 2034238104Sdes (void) ldns_dname_cat(wildcard_name, wildcard_chopped); 2035238104Sdes ldns_rdf_deep_free(wildcard_chopped); 2036238104Sdes ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr( 2037238104Sdes rrset_clone, i))); 2038238104Sdes ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 2039238104Sdes wildcard_name); 2040238104Sdes } 2041238104Sdes ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl); 2042238104Sdes /* convert to lowercase */ 2043238104Sdes ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); 2044238104Sdes } 2045238104Sdes} 2046238104Sdes 2047238104Sdes/** 2048238104Sdes * Make raw signature buffer out of rrsig 2049238104Sdes * @param rawsig_buf: raw signature buffer for result 2050238104Sdes * @param rrsig: signature to convert 2051238104Sdes * @return OK or more specific error. 2052238104Sdes */ 2053238104Sdesstatic ldns_status 2054238104Sdesldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig) 2055238104Sdes{ 2056238104Sdes uint8_t sig_algo; 2057238104Sdes 2058238104Sdes if (rrsig == NULL) { 2059238104Sdes return LDNS_STATUS_CRYPTO_NO_RRSIG; 2060238104Sdes } 2061238104Sdes if (ldns_rr_rdf(rrsig, 1) == NULL) { 2062238104Sdes return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 2063238104Sdes } 2064238104Sdes sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); 2065238104Sdes /* check for known and implemented algo's now (otherwise 2066238104Sdes * the function could return a wrong error 2067238104Sdes */ 2068238104Sdes /* create a buffer with signature rdata */ 2069238104Sdes /* for some algorithms we need other data than for others... */ 2070238104Sdes /* (the DSA API wants DER encoding for instance) */ 2071238104Sdes 2072238104Sdes switch(sig_algo) { 2073238104Sdes case LDNS_RSAMD5: 2074238104Sdes case LDNS_RSASHA1: 2075238104Sdes case LDNS_RSASHA1_NSEC3: 2076238104Sdes#ifdef USE_SHA2 2077238104Sdes case LDNS_RSASHA256: 2078238104Sdes case LDNS_RSASHA512: 2079238104Sdes#endif 2080238104Sdes#ifdef USE_GOST 2081238104Sdes case LDNS_ECC_GOST: 2082238104Sdes#endif 2083238104Sdes if (ldns_rr_rdf(rrsig, 8) == NULL) { 2084238104Sdes return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 2085238104Sdes } 2086238104Sdes if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) 2087238104Sdes != LDNS_STATUS_OK) { 2088238104Sdes return LDNS_STATUS_MEM_ERR; 2089238104Sdes } 2090238104Sdes break; 2091238104Sdes case LDNS_DSA: 2092238104Sdes case LDNS_DSA_NSEC3: 2093238104Sdes /* EVP takes rfc2459 format, which is a tad longer than dns format */ 2094238104Sdes if (ldns_rr_rdf(rrsig, 8) == NULL) { 2095238104Sdes return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 2096238104Sdes } 2097238104Sdes if (ldns_convert_dsa_rrsig_rdf2asn1( 2098238104Sdes rawsig_buf, ldns_rr_rdf(rrsig, 8)) 2099238104Sdes != LDNS_STATUS_OK) { 2100238104Sdes /* 2101238104Sdes if (ldns_rdf2buffer_wire(rawsig_buf, 2102238104Sdes ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { 2103238104Sdes */ 2104238104Sdes return LDNS_STATUS_MEM_ERR; 2105238104Sdes } 2106238104Sdes break; 2107238104Sdes#ifdef USE_ECDSA 2108238104Sdes case LDNS_ECDSAP256SHA256: 2109238104Sdes case LDNS_ECDSAP384SHA384: 2110238104Sdes /* EVP produces an ASN prefix on the signature, which is 2111238104Sdes * not used in the DNS */ 2112238104Sdes if (ldns_rr_rdf(rrsig, 8) == NULL) { 2113238104Sdes return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 2114238104Sdes } 2115238104Sdes if (ldns_convert_ecdsa_rrsig_rdf2asn1( 2116238104Sdes rawsig_buf, ldns_rr_rdf(rrsig, 8)) 2117238104Sdes != LDNS_STATUS_OK) { 2118238104Sdes return LDNS_STATUS_MEM_ERR; 2119238104Sdes } 2120238104Sdes break; 2121238104Sdes#endif 2122238104Sdes case LDNS_DH: 2123238104Sdes case LDNS_ECC: 2124238104Sdes case LDNS_INDIRECT: 2125238104Sdes return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; 2126238104Sdes default: 2127238104Sdes return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 2128238104Sdes } 2129238104Sdes return LDNS_STATUS_OK; 2130238104Sdes} 2131238104Sdes 2132238104Sdes/** 2133238104Sdes * Check RRSIG timestamps against the given 'now' time. 2134238104Sdes * @param rrsig: signature to check. 2135238104Sdes * @param now: the current time in seconds epoch. 2136238104Sdes * @return status code LDNS_STATUS_OK if all is fine. 2137238104Sdes */ 2138238104Sdesstatic ldns_status 2139238104Sdesldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now) 2140238104Sdes{ 2141238104Sdes int32_t inception, expiration; 2142238104Sdes 2143238104Sdes /* check the signature time stamps */ 2144238104Sdes inception = (int32_t)ldns_rdf2native_time_t( 2145238104Sdes ldns_rr_rrsig_inception(rrsig)); 2146238104Sdes expiration = (int32_t)ldns_rdf2native_time_t( 2147238104Sdes ldns_rr_rrsig_expiration(rrsig)); 2148238104Sdes 2149238104Sdes if (expiration - inception < 0) { 2150238104Sdes /* bad sig, expiration before inception?? Tsssg */ 2151238104Sdes return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION; 2152238104Sdes } 2153238104Sdes if (((int32_t) now) - inception < 0) { 2154238104Sdes /* bad sig, inception date has not yet come to pass */ 2155238104Sdes return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED; 2156238104Sdes } 2157238104Sdes if (expiration - ((int32_t) now) < 0) { 2158238104Sdes /* bad sig, expiration date has passed */ 2159238104Sdes return LDNS_STATUS_CRYPTO_SIG_EXPIRED; 2160238104Sdes } 2161238104Sdes return LDNS_STATUS_OK; 2162238104Sdes} 2163238104Sdes 2164238104Sdes/** 2165238104Sdes * Prepare for verification. 2166238104Sdes * @param rawsig_buf: raw signature buffer made ready. 2167238104Sdes * @param verify_buf: data for verification buffer made ready. 2168238104Sdes * @param rrset_clone: made ready. 2169238104Sdes * @param rrsig: signature to prepare for. 2170238104Sdes * @return LDNS_STATUS_OK is all went well. Otherwise specific error. 2171238104Sdes */ 2172238104Sdesstatic ldns_status 2173238104Sdesldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 2174238104Sdes ldns_rr_list* rrset_clone, ldns_rr* rrsig) 2175238104Sdes{ 2176238104Sdes ldns_status result; 2177238104Sdes 2178238104Sdes /* canonicalize the sig */ 2179238104Sdes ldns_dname2canonical(ldns_rr_owner(rrsig)); 2180238104Sdes 2181238104Sdes /* check if the typecovered is equal to the type checked */ 2182238104Sdes if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) != 2183238104Sdes ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) 2184238104Sdes return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR; 2185238104Sdes 2186238104Sdes /* create a buffer with b64 signature rdata */ 2187238104Sdes result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig); 2188238104Sdes if(result != LDNS_STATUS_OK) 2189238104Sdes return result; 2190238104Sdes 2191238104Sdes /* use TTL from signature. Use wildcard names for wildcards */ 2192238104Sdes /* also canonicalizes rrset_clone */ 2193238104Sdes ldns_rrset_use_signature_ttl(rrset_clone, rrsig); 2194238104Sdes 2195238104Sdes /* sort the rrset in canonical order */ 2196238104Sdes ldns_rr_list_sort(rrset_clone); 2197238104Sdes 2198238104Sdes /* put the signature rr (without the b64) to the verify_buf */ 2199238104Sdes if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK) 2200238104Sdes return LDNS_STATUS_MEM_ERR; 2201238104Sdes 2202238104Sdes /* add the rrset in verify_buf */ 2203238104Sdes if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) 2204238104Sdes != LDNS_STATUS_OK) 2205238104Sdes return LDNS_STATUS_MEM_ERR; 2206238104Sdes 2207238104Sdes return LDNS_STATUS_OK; 2208238104Sdes} 2209238104Sdes 2210238104Sdes/** 2211238104Sdes * Check if a key matches a signature. 2212238104Sdes * Checks keytag, sigalgo and signature. 2213238104Sdes * @param rawsig_buf: raw signature buffer for verify 2214238104Sdes * @param verify_buf: raw data buffer for verify 2215238104Sdes * @param rrsig: the rrsig 2216238104Sdes * @param key: key to attempt. 2217238104Sdes * @return LDNS_STATUS_OK if OK, else some specific error. 2218238104Sdes */ 2219238104Sdesstatic ldns_status 2220238104Sdesldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 2221238104Sdes ldns_rr* rrsig, ldns_rr* key) 2222238104Sdes{ 2223238104Sdes uint8_t sig_algo; 2224238104Sdes 2225238104Sdes if (rrsig == NULL) { 2226238104Sdes return LDNS_STATUS_CRYPTO_NO_RRSIG; 2227238104Sdes } 2228238104Sdes if (ldns_rr_rdf(rrsig, 1) == NULL) { 2229238104Sdes return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 2230238104Sdes } 2231238104Sdes sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); 2232238104Sdes 2233238104Sdes /* before anything, check if the keytags match */ 2234238104Sdes if (ldns_calc_keytag(key) 2235238104Sdes == 2236238104Sdes ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) 2237238104Sdes ) { 2238238104Sdes ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 2239238104Sdes ldns_status result = LDNS_STATUS_ERR; 2240238104Sdes 2241238104Sdes /* put the key-data in a buffer, that's the third rdf, with 2242238104Sdes * the base64 encoded key data */ 2243238104Sdes if (ldns_rr_rdf(key, 3) == NULL) { 2244238104Sdes ldns_buffer_free(key_buf); 2245238104Sdes return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; 2246238104Sdes } 2247238104Sdes if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3)) 2248238104Sdes != LDNS_STATUS_OK) { 2249238104Sdes ldns_buffer_free(key_buf); 2250238104Sdes /* returning is bad might screw up 2251238104Sdes good keys later in the list 2252238104Sdes what to do? */ 2253238104Sdes return LDNS_STATUS_ERR; 2254238104Sdes } 2255238104Sdes 2256238104Sdes if (ldns_rr_rdf(key, 2) == NULL) { 2257238104Sdes result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; 2258238104Sdes } 2259238104Sdes else if (sig_algo == ldns_rdf2native_int8( 2260238104Sdes ldns_rr_rdf(key, 2))) { 2261238104Sdes result = ldns_verify_rrsig_buffers(rawsig_buf, 2262238104Sdes verify_buf, key_buf, sig_algo); 2263238104Sdes } else { 2264238104Sdes /* No keys with the corresponding algorithm are found */ 2265238104Sdes result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 2266238104Sdes } 2267238104Sdes 2268238104Sdes ldns_buffer_free(key_buf); 2269238104Sdes return result; 2270238104Sdes } 2271238104Sdes else { 2272238104Sdes /* No keys with the corresponding keytag are found */ 2273238104Sdes return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 2274238104Sdes } 2275238104Sdes} 2276238104Sdes 2277238104Sdes/* 2278238104Sdes * to verify: 2279238104Sdes * - create the wire fmt of the b64 key rdata 2280238104Sdes * - create the wire fmt of the sorted rrset 2281238104Sdes * - create the wire fmt of the b64 sig rdata 2282238104Sdes * - create the wire fmt of the sig without the b64 rdata 2283238104Sdes * - cat the sig data (without b64 rdata) to the rrset 2284238104Sdes * - verify the rrset+sig, with the b64 data and the b64 key data 2285238104Sdes */ 2286238104Sdesldns_status 2287238104Sdesldns_verify_rrsig_keylist_time( 2288238104Sdes ldns_rr_list *rrset, 2289238104Sdes ldns_rr *rrsig, 2290238104Sdes const ldns_rr_list *keys, 2291238104Sdes time_t check_time, 2292238104Sdes ldns_rr_list *good_keys) 2293238104Sdes{ 2294238104Sdes ldns_status result; 2295238104Sdes ldns_rr_list *valid = ldns_rr_list_new(); 2296238104Sdes if (!valid) 2297238104Sdes return LDNS_STATUS_MEM_ERR; 2298238104Sdes 2299238104Sdes result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); 2300238104Sdes if(result != LDNS_STATUS_OK) { 2301238104Sdes ldns_rr_list_free(valid); 2302238104Sdes return result; 2303238104Sdes } 2304238104Sdes 2305238104Sdes /* check timestamps last; its OK except time */ 2306238104Sdes result = ldns_rrsig_check_timestamps(rrsig, check_time); 2307238104Sdes if(result != LDNS_STATUS_OK) { 2308238104Sdes ldns_rr_list_free(valid); 2309238104Sdes return result; 2310238104Sdes } 2311238104Sdes 2312238104Sdes ldns_rr_list_cat(good_keys, valid); 2313238104Sdes ldns_rr_list_free(valid); 2314238104Sdes return LDNS_STATUS_OK; 2315238104Sdes} 2316238104Sdes 2317238104Sdes/* 2318238104Sdes * to verify: 2319238104Sdes * - create the wire fmt of the b64 key rdata 2320238104Sdes * - create the wire fmt of the sorted rrset 2321238104Sdes * - create the wire fmt of the b64 sig rdata 2322238104Sdes * - create the wire fmt of the sig without the b64 rdata 2323238104Sdes * - cat the sig data (without b64 rdata) to the rrset 2324238104Sdes * - verify the rrset+sig, with the b64 data and the b64 key data 2325238104Sdes */ 2326238104Sdesldns_status 2327238104Sdesldns_verify_rrsig_keylist(ldns_rr_list *rrset, 2328238104Sdes ldns_rr *rrsig, 2329238104Sdes const ldns_rr_list *keys, 2330238104Sdes ldns_rr_list *good_keys) 2331238104Sdes{ 2332238104Sdes return ldns_verify_rrsig_keylist_time( 2333238104Sdes rrset, rrsig, keys, ldns_time(NULL), good_keys); 2334238104Sdes} 2335238104Sdes 2336238104Sdesldns_status 2337238104Sdesldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, 2338238104Sdes ldns_rr *rrsig, 2339238104Sdes const ldns_rr_list *keys, 2340238104Sdes ldns_rr_list *good_keys) 2341238104Sdes{ 2342238104Sdes ldns_buffer *rawsig_buf; 2343238104Sdes ldns_buffer *verify_buf; 2344238104Sdes uint16_t i; 2345238104Sdes ldns_status result, status; 2346238104Sdes ldns_rr_list *rrset_clone; 2347238104Sdes ldns_rr_list *validkeys; 2348238104Sdes 2349238104Sdes if (!rrset) { 2350238104Sdes return LDNS_STATUS_ERR; 2351238104Sdes } 2352238104Sdes 2353238104Sdes validkeys = ldns_rr_list_new(); 2354238104Sdes if (!validkeys) { 2355238104Sdes return LDNS_STATUS_MEM_ERR; 2356238104Sdes } 2357238104Sdes 2358238104Sdes /* clone the rrset so that we can fiddle with it */ 2359238104Sdes rrset_clone = ldns_rr_list_clone(rrset); 2360238104Sdes 2361238104Sdes /* create the buffers which will certainly hold the raw data */ 2362238104Sdes rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 2363238104Sdes verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 2364238104Sdes 2365238104Sdes result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 2366238104Sdes rrset_clone, rrsig); 2367238104Sdes if(result != LDNS_STATUS_OK) { 2368238104Sdes ldns_buffer_free(verify_buf); 2369238104Sdes ldns_buffer_free(rawsig_buf); 2370238104Sdes ldns_rr_list_deep_free(rrset_clone); 2371238104Sdes ldns_rr_list_free(validkeys); 2372238104Sdes return result; 2373238104Sdes } 2374238104Sdes 2375238104Sdes result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 2376238104Sdes for(i = 0; i < ldns_rr_list_rr_count(keys); i++) { 2377238104Sdes status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 2378238104Sdes rrsig, ldns_rr_list_rr(keys, i)); 2379238104Sdes if (status == LDNS_STATUS_OK) { 2380238104Sdes /* one of the keys has matched, don't break 2381238104Sdes * here, instead put the 'winning' key in 2382238104Sdes * the validkey list and return the list 2383238104Sdes * later */ 2384238104Sdes if (!ldns_rr_list_push_rr(validkeys, 2385238104Sdes ldns_rr_list_rr(keys,i))) { 2386238104Sdes /* couldn't push the key?? */ 2387238104Sdes ldns_buffer_free(rawsig_buf); 2388238104Sdes ldns_buffer_free(verify_buf); 2389238104Sdes ldns_rr_list_deep_free(rrset_clone); 2390238104Sdes ldns_rr_list_free(validkeys); 2391238104Sdes return LDNS_STATUS_MEM_ERR; 2392238104Sdes } 2393238104Sdes 2394238104Sdes result = status; 2395238104Sdes } 2396238104Sdes 2397238104Sdes if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { 2398238104Sdes result = status; 2399238104Sdes } 2400238104Sdes } 2401238104Sdes 2402238104Sdes /* no longer needed */ 2403238104Sdes ldns_rr_list_deep_free(rrset_clone); 2404238104Sdes ldns_buffer_free(rawsig_buf); 2405238104Sdes ldns_buffer_free(verify_buf); 2406238104Sdes 2407238104Sdes if (ldns_rr_list_rr_count(validkeys) == 0) { 2408238104Sdes /* no keys were added, return last error */ 2409238104Sdes ldns_rr_list_free(validkeys); 2410238104Sdes return result; 2411238104Sdes } 2412238104Sdes 2413238104Sdes /* do not check timestamps */ 2414238104Sdes 2415238104Sdes ldns_rr_list_cat(good_keys, validkeys); 2416238104Sdes ldns_rr_list_free(validkeys); 2417238104Sdes return LDNS_STATUS_OK; 2418238104Sdes} 2419238104Sdes 2420238104Sdesldns_status 2421238104Sdesldns_verify_rrsig_time( 2422238104Sdes ldns_rr_list *rrset, 2423238104Sdes ldns_rr *rrsig, 2424238104Sdes ldns_rr *key, 2425238104Sdes time_t check_time) 2426238104Sdes{ 2427238104Sdes ldns_buffer *rawsig_buf; 2428238104Sdes ldns_buffer *verify_buf; 2429238104Sdes ldns_status result; 2430238104Sdes ldns_rr_list *rrset_clone; 2431238104Sdes 2432238104Sdes if (!rrset) { 2433238104Sdes return LDNS_STATUS_NO_DATA; 2434238104Sdes } 2435238104Sdes /* clone the rrset so that we can fiddle with it */ 2436238104Sdes rrset_clone = ldns_rr_list_clone(rrset); 2437238104Sdes /* create the buffers which will certainly hold the raw data */ 2438238104Sdes rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 2439238104Sdes verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 2440238104Sdes 2441238104Sdes result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 2442238104Sdes rrset_clone, rrsig); 2443238104Sdes if(result != LDNS_STATUS_OK) { 2444238104Sdes ldns_rr_list_deep_free(rrset_clone); 2445238104Sdes ldns_buffer_free(rawsig_buf); 2446238104Sdes ldns_buffer_free(verify_buf); 2447238104Sdes return result; 2448238104Sdes } 2449238104Sdes result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 2450238104Sdes rrsig, key); 2451238104Sdes /* no longer needed */ 2452238104Sdes ldns_rr_list_deep_free(rrset_clone); 2453238104Sdes ldns_buffer_free(rawsig_buf); 2454238104Sdes ldns_buffer_free(verify_buf); 2455238104Sdes 2456238104Sdes /* check timestamp last, apart from time its OK */ 2457238104Sdes if(result == LDNS_STATUS_OK) 2458238104Sdes result = ldns_rrsig_check_timestamps(rrsig, check_time); 2459238104Sdes 2460238104Sdes return result; 2461238104Sdes} 2462238104Sdes 2463238104Sdesldns_status 2464238104Sdesldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) 2465238104Sdes{ 2466238104Sdes return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL)); 2467238104Sdes} 2468238104Sdes 2469238104Sdes 2470238104Sdesldns_status 2471238104Sdesldns_verify_rrsig_evp(ldns_buffer *sig, 2472238104Sdes ldns_buffer *rrset, 2473238104Sdes EVP_PKEY *key, 2474238104Sdes const EVP_MD *digest_type) 2475238104Sdes{ 2476238104Sdes return ldns_verify_rrsig_evp_raw( 2477238104Sdes (unsigned char*)ldns_buffer_begin(sig), 2478238104Sdes ldns_buffer_position(sig), 2479238104Sdes rrset, 2480238104Sdes key, 2481238104Sdes digest_type); 2482238104Sdes} 2483238104Sdes 2484238104Sdesldns_status 2485238104Sdesldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 2486238104Sdes ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type) 2487238104Sdes{ 2488238104Sdes EVP_MD_CTX ctx; 2489238104Sdes int res; 2490238104Sdes 2491238104Sdes EVP_MD_CTX_init(&ctx); 2492238104Sdes 2493238104Sdes EVP_VerifyInit(&ctx, digest_type); 2494238104Sdes EVP_VerifyUpdate(&ctx, 2495238104Sdes ldns_buffer_begin(rrset), 2496238104Sdes ldns_buffer_position(rrset)); 2497238104Sdes res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key); 2498238104Sdes 2499238104Sdes EVP_MD_CTX_cleanup(&ctx); 2500238104Sdes 2501238104Sdes if (res == 1) { 2502238104Sdes return LDNS_STATUS_OK; 2503238104Sdes } else if (res == 0) { 2504238104Sdes return LDNS_STATUS_CRYPTO_BOGUS; 2505238104Sdes } 2506238104Sdes /* TODO how to communicate internal SSL error? 2507238104Sdes let caller use ssl's get_error() */ 2508238104Sdes return LDNS_STATUS_SSL_ERR; 2509238104Sdes} 2510238104Sdes 2511238104Sdesldns_status 2512238104Sdesldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 2513238104Sdes{ 2514238104Sdes return ldns_verify_rrsig_dsa_raw( 2515238104Sdes (unsigned char*) ldns_buffer_begin(sig), 2516238104Sdes ldns_buffer_position(sig), 2517238104Sdes rrset, 2518238104Sdes (unsigned char*) ldns_buffer_begin(key), 2519238104Sdes ldns_buffer_position(key)); 2520238104Sdes} 2521238104Sdes 2522238104Sdesldns_status 2523238104Sdesldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 2524238104Sdes{ 2525238104Sdes return ldns_verify_rrsig_rsasha1_raw( 2526238104Sdes (unsigned char*)ldns_buffer_begin(sig), 2527238104Sdes ldns_buffer_position(sig), 2528238104Sdes rrset, 2529238104Sdes (unsigned char*) ldns_buffer_begin(key), 2530238104Sdes ldns_buffer_position(key)); 2531238104Sdes} 2532238104Sdes 2533238104Sdesldns_status 2534238104Sdesldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 2535238104Sdes{ 2536238104Sdes return ldns_verify_rrsig_rsamd5_raw( 2537238104Sdes (unsigned char*)ldns_buffer_begin(sig), 2538238104Sdes ldns_buffer_position(sig), 2539238104Sdes rrset, 2540238104Sdes (unsigned char*) ldns_buffer_begin(key), 2541238104Sdes ldns_buffer_position(key)); 2542238104Sdes} 2543238104Sdes 2544238104Sdesldns_status 2545238104Sdesldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen, 2546238104Sdes ldns_buffer* rrset, unsigned char* key, size_t keylen) 2547238104Sdes{ 2548238104Sdes EVP_PKEY *evp_key; 2549238104Sdes ldns_status result; 2550238104Sdes 2551238104Sdes evp_key = EVP_PKEY_new(); 2552238104Sdes if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) { 2553238104Sdes result = ldns_verify_rrsig_evp_raw(sig, 2554238104Sdes siglen, 2555238104Sdes rrset, 2556238104Sdes evp_key, 2557238104Sdes EVP_dss1()); 2558238104Sdes } else { 2559238104Sdes result = LDNS_STATUS_SSL_ERR; 2560238104Sdes } 2561238104Sdes EVP_PKEY_free(evp_key); 2562238104Sdes return result; 2563238104Sdes 2564238104Sdes} 2565238104Sdes 2566238104Sdesldns_status 2567238104Sdesldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen, 2568238104Sdes ldns_buffer* rrset, unsigned char* key, size_t keylen) 2569238104Sdes{ 2570238104Sdes EVP_PKEY *evp_key; 2571238104Sdes ldns_status result; 2572238104Sdes 2573238104Sdes evp_key = EVP_PKEY_new(); 2574238104Sdes if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 2575238104Sdes result = ldns_verify_rrsig_evp_raw(sig, 2576238104Sdes siglen, 2577238104Sdes rrset, 2578238104Sdes evp_key, 2579238104Sdes EVP_sha1()); 2580238104Sdes } else { 2581238104Sdes result = LDNS_STATUS_SSL_ERR; 2582238104Sdes } 2583238104Sdes EVP_PKEY_free(evp_key); 2584238104Sdes 2585238104Sdes return result; 2586238104Sdes} 2587238104Sdes 2588238104Sdesldns_status 2589238104Sdesldns_verify_rrsig_rsasha256_raw(unsigned char* sig, 2590238104Sdes size_t siglen, 2591238104Sdes ldns_buffer* rrset, 2592238104Sdes unsigned char* key, 2593238104Sdes size_t keylen) 2594238104Sdes{ 2595238104Sdes#ifdef USE_SHA2 2596238104Sdes EVP_PKEY *evp_key; 2597238104Sdes ldns_status result; 2598238104Sdes 2599238104Sdes evp_key = EVP_PKEY_new(); 2600238104Sdes if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 2601238104Sdes result = ldns_verify_rrsig_evp_raw(sig, 2602238104Sdes siglen, 2603238104Sdes rrset, 2604238104Sdes evp_key, 2605238104Sdes EVP_sha256()); 2606238104Sdes } else { 2607238104Sdes result = LDNS_STATUS_SSL_ERR; 2608238104Sdes } 2609238104Sdes EVP_PKEY_free(evp_key); 2610238104Sdes 2611238104Sdes return result; 2612238104Sdes#else 2613238104Sdes /* touch these to prevent compiler warnings */ 2614238104Sdes (void) sig; 2615238104Sdes (void) siglen; 2616238104Sdes (void) rrset; 2617238104Sdes (void) key; 2618238104Sdes (void) keylen; 2619238104Sdes return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 2620238104Sdes#endif 2621238104Sdes} 2622238104Sdes 2623238104Sdesldns_status 2624238104Sdesldns_verify_rrsig_rsasha512_raw(unsigned char* sig, 2625238104Sdes size_t siglen, 2626238104Sdes ldns_buffer* rrset, 2627238104Sdes unsigned char* key, 2628238104Sdes size_t keylen) 2629238104Sdes{ 2630238104Sdes#ifdef USE_SHA2 2631238104Sdes EVP_PKEY *evp_key; 2632238104Sdes ldns_status result; 2633238104Sdes 2634238104Sdes evp_key = EVP_PKEY_new(); 2635238104Sdes if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 2636238104Sdes result = ldns_verify_rrsig_evp_raw(sig, 2637238104Sdes siglen, 2638238104Sdes rrset, 2639238104Sdes evp_key, 2640238104Sdes EVP_sha512()); 2641238104Sdes } else { 2642238104Sdes result = LDNS_STATUS_SSL_ERR; 2643238104Sdes } 2644238104Sdes EVP_PKEY_free(evp_key); 2645238104Sdes 2646238104Sdes return result; 2647238104Sdes#else 2648238104Sdes /* touch these to prevent compiler warnings */ 2649238104Sdes (void) sig; 2650238104Sdes (void) siglen; 2651238104Sdes (void) rrset; 2652238104Sdes (void) key; 2653238104Sdes (void) keylen; 2654238104Sdes return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 2655238104Sdes#endif 2656238104Sdes} 2657238104Sdes 2658238104Sdes 2659238104Sdesldns_status 2660238104Sdesldns_verify_rrsig_rsamd5_raw(unsigned char* sig, 2661238104Sdes size_t siglen, 2662238104Sdes ldns_buffer* rrset, 2663238104Sdes unsigned char* key, 2664238104Sdes size_t keylen) 2665238104Sdes{ 2666238104Sdes EVP_PKEY *evp_key; 2667238104Sdes ldns_status result; 2668238104Sdes 2669238104Sdes evp_key = EVP_PKEY_new(); 2670238104Sdes if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 2671238104Sdes result = ldns_verify_rrsig_evp_raw(sig, 2672238104Sdes siglen, 2673238104Sdes rrset, 2674238104Sdes evp_key, 2675238104Sdes EVP_md5()); 2676238104Sdes } else { 2677238104Sdes result = LDNS_STATUS_SSL_ERR; 2678238104Sdes } 2679238104Sdes EVP_PKEY_free(evp_key); 2680238104Sdes 2681238104Sdes return result; 2682238104Sdes} 2683238104Sdes 2684238104Sdes#endif 2685