dnssec_verify.c revision 246883
119370Spst#include <ldns/config.h> 298948Sobrien 3130809Smarcel#include <ldns/ldns.h> 419370Spst 519370Spst#include <strings.h> 698948Sobrien#include <time.h> 719370Spst 898948Sobrien#ifdef HAVE_SSL 998948Sobrien/* this entire file is rather useless when you don't have 1098948Sobrien * crypto... 1198948Sobrien */ 1219370Spst#include <openssl/ssl.h> 1398948Sobrien#include <openssl/evp.h> 1498948Sobrien#include <openssl/rand.h> 1598948Sobrien#include <openssl/err.h> 1698948Sobrien#include <openssl/md5.h> 1719370Spst 1898948Sobrienldns_dnssec_data_chain * 1998948Sobrienldns_dnssec_data_chain_new(void) 2098948Sobrien{ 2198948Sobrien ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); 2219370Spst if(!nc) return NULL; 2319370Spst /* 2419370Spst * not needed anymore because CALLOC initalizes everything to zero. 2519370Spst 2619370Spst nc->rrset = NULL; 2719370Spst nc->parent_type = 0; 2819370Spst nc->parent = NULL; 2919370Spst nc->signatures = NULL; 3019370Spst nc->packet_rcode = 0; 3119370Spst nc->packet_qtype = 0; 3219370Spst nc->packet_nodata = false; 3319370Spst 3419370Spst */ 3519370Spst return nc; 3619370Spst} 3719370Spst 3819370Spstvoid 3919370Spstldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain) 4019370Spst{ 4119370Spst LDNS_FREE(chain); 4219370Spst} 4319370Spst 4419370Spstvoid 45130809Smarcelldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain) 4619370Spst{ 4719370Spst ldns_rr_list_deep_free(chain->rrset); 4819370Spst ldns_rr_list_deep_free(chain->signatures); 4919370Spst if (chain->parent) { 5019370Spst ldns_dnssec_data_chain_deep_free(chain->parent); 5198948Sobrien } 5219370Spst LDNS_FREE(chain); 5319370Spst} 5419370Spst 5519370Spstvoid 5619370Spstldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt, 5798948Sobrien const ldns_dnssec_data_chain *chain) 5819370Spst{ 5998948Sobrien ldns_lookup_table *rcode; 60130809Smarcel const ldns_rr_descriptor *rr_descriptor; 6119370Spst if (chain) { 6219370Spst ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent); 6319370Spst if (ldns_rr_list_rr_count(chain->rrset) > 0) { 6498948Sobrien rcode = ldns_lookup_by_id(ldns_rcodes, 6519370Spst (int) chain->packet_rcode); 6619370Spst if (rcode) { 6719370Spst fprintf(out, ";; rcode: %s\n", rcode->name); 6819370Spst } 6998948Sobrien 7098948Sobrien rr_descriptor = ldns_rr_descript(chain->packet_qtype); 7198948Sobrien if (rr_descriptor && rr_descriptor->_name) { 7298948Sobrien fprintf(out, ";; qtype: %s\n", rr_descriptor->_name); 7319370Spst } else if (chain->packet_qtype != 0) { 7498948Sobrien fprintf(out, "TYPE%u", 7519370Spst chain->packet_qtype); 7698948Sobrien } 7798948Sobrien if (chain->packet_nodata) { 7898948Sobrien fprintf(out, ";; NODATA response\n"); 7998948Sobrien } 8098948Sobrien fprintf(out, "rrset:\n"); 8119370Spst ldns_rr_list_print_fmt(out, fmt, chain->rrset); 8298948Sobrien fprintf(out, "sigs:\n"); 8319370Spst ldns_rr_list_print_fmt(out, fmt, chain->signatures); 8498948Sobrien fprintf(out, "---\n"); 8519370Spst } else { 8698948Sobrien fprintf(out, "<no data>\n"); 8719370Spst } 8898948Sobrien } 8998948Sobrien} 9019370Spstvoid 9198948Sobrienldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain) 9298948Sobrien{ 9398948Sobrien ldns_dnssec_data_chain_print_fmt( 9498948Sobrien out, ldns_output_format_default, chain); 9519370Spst} 9619370Spst 9719370Spst 9819370Spststatic void 9919370Spstldns_dnssec_build_data_chain_dnskey(ldns_resolver *res, 10019370Spst uint16_t qflags, 10119370Spst const ldns_pkt *pkt, 10219370Spst ldns_rr_list *signatures, 10398948Sobrien ldns_dnssec_data_chain *new_chain, 10419370Spst ldns_rdf *key_name, 10519370Spst ldns_rr_class c) { 10619370Spst ldns_rr_list *keys; 10719370Spst ldns_pkt *my_pkt; 10819370Spst if (signatures && ldns_rr_list_rr_count(signatures) > 0) { 10919370Spst new_chain->signatures = ldns_rr_list_clone(signatures); 11019370Spst new_chain->parent_type = 0; 11119370Spst 11219370Spst keys = ldns_pkt_rr_list_by_name_and_type( 11319370Spst pkt, 11419370Spst key_name, 11519370Spst LDNS_RR_TYPE_DNSKEY, 11619370Spst LDNS_SECTION_ANY_NOQUESTION 11719370Spst ); 11819370Spst if (!keys) { 11946283Sdfr my_pkt = ldns_resolver_query(res, 12046283Sdfr key_name, 12119370Spst LDNS_RR_TYPE_DNSKEY, 12219370Spst c, 12346283Sdfr qflags); 12446283Sdfr if (my_pkt) { 12519370Spst keys = ldns_pkt_rr_list_by_name_and_type( 12619370Spst my_pkt, 12719370Spst key_name, 12846283Sdfr LDNS_RR_TYPE_DNSKEY, 12946283Sdfr LDNS_SECTION_ANY_NOQUESTION 13046283Sdfr ); 13146283Sdfr new_chain->parent = ldns_dnssec_build_data_chain(res, 13246283Sdfr qflags, 13319370Spst keys, 13419370Spst my_pkt, 13519370Spst NULL); 13646283Sdfr new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; 13746283Sdfr ldns_pkt_free(my_pkt); 13846283Sdfr } 13919370Spst } else { 14019370Spst new_chain->parent = ldns_dnssec_build_data_chain(res, 14119370Spst qflags, 14246283Sdfr keys, 14346283Sdfr pkt, 14419370Spst NULL); 14519370Spst new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; 14619370Spst } 14719370Spst ldns_rr_list_deep_free(keys); 14819370Spst } 14919370Spst} 15019370Spst 15119370Spststatic void 15246283Sdfrldns_dnssec_build_data_chain_other(ldns_resolver *res, 15319370Spst uint16_t qflags, 15419370Spst ldns_dnssec_data_chain *new_chain, 15546283Sdfr ldns_rdf *key_name, 15646283Sdfr ldns_rr_class c, 15746283Sdfr ldns_rr_list *dss) 15846283Sdfr{ 15946283Sdfr /* 'self-signed', parent is a DS */ 16019370Spst 16119370Spst /* okay, either we have other keys signing the current one, 162130809Smarcel * or the current 163130809Smarcel * one should have a DS record in the parent zone. 164130809Smarcel * How do we find this out? Try both? 165130809Smarcel * 166130809Smarcel * request DNSKEYS for current zone, 16719370Spst * add all signatures to current level 168130809Smarcel */ 169130809Smarcel ldns_pkt *my_pkt; 170130809Smarcel ldns_rr_list *signatures2; 171130809Smarcel 172130809Smarcel new_chain->parent_type = 1; 173130809Smarcel 17419370Spst my_pkt = ldns_resolver_query(res, 175130809Smarcel key_name, 176130809Smarcel LDNS_RR_TYPE_DS, 177130809Smarcel c, 178130809Smarcel qflags); 179130809Smarcel if (my_pkt) { 180130809Smarcel dss = ldns_pkt_rr_list_by_name_and_type(my_pkt, 181130809Smarcel key_name, 18219370Spst LDNS_RR_TYPE_DS, 18398948Sobrien LDNS_SECTION_ANY_NOQUESTION 18498948Sobrien ); 18598948Sobrien if (dss) { 18698948Sobrien new_chain->parent = ldns_dnssec_build_data_chain(res, 18798948Sobrien qflags, 18898948Sobrien dss, 18998948Sobrien my_pkt, 19098948Sobrien NULL); 19198948Sobrien new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; 19298948Sobrien ldns_rr_list_deep_free(dss); 19398948Sobrien } 19498948Sobrien ldns_pkt_free(my_pkt); 19598948Sobrien } 19698948Sobrien 19798948Sobrien my_pkt = ldns_resolver_query(res, 19898948Sobrien key_name, 19998948Sobrien LDNS_RR_TYPE_DNSKEY, 20098948Sobrien c, 20198948Sobrien qflags); 20298948Sobrien if (my_pkt) { 20398948Sobrien signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt, 20498948Sobrien key_name, 20598948Sobrien LDNS_RR_TYPE_RRSIG, 20698948Sobrien LDNS_SECTION_ANSWER); 20798948Sobrien if (signatures2) { 20898948Sobrien if (new_chain->signatures) { 20998948Sobrien printf("There were already sigs!\n"); 21098948Sobrien ldns_rr_list_deep_free(new_chain->signatures); 21198948Sobrien printf("replacing the old sigs\n"); 21298948Sobrien } 21398948Sobrien new_chain->signatures = signatures2; 21498948Sobrien } 21598948Sobrien ldns_pkt_free(my_pkt); 21698948Sobrien } 21798948Sobrien} 21898948Sobrien 21998948Sobrienstatic ldns_dnssec_data_chain * 22098948Sobrienldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res, 22198948Sobrien uint16_t qflags, 22298948Sobrien ldns_rr *orig_rr, 22398948Sobrien const ldns_rr_list *rrset, 22498948Sobrien ldns_dnssec_data_chain *new_chain) 22598948Sobrien{ 22698948Sobrien ldns_rdf *possible_parent_name; 22798948Sobrien ldns_pkt *my_pkt; 22898948Sobrien /* apparently we were not able to find a signing key, so 22998948Sobrien we assume the chain ends here 23098948Sobrien */ 23119370Spst /* try parents for auth denial of DS */ 23219370Spst if (orig_rr) { 23319370Spst possible_parent_name = ldns_rr_owner(orig_rr); 23419370Spst } else if (rrset && ldns_rr_list_rr_count(rrset) > 0) { 23519370Spst possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0)); 23619370Spst } else { 23719370Spst /* no information to go on, give up */ 23819370Spst return new_chain; 23919370Spst } 24019370Spst 24119370Spst my_pkt = ldns_resolver_query(res, 24219370Spst possible_parent_name, 24319370Spst LDNS_RR_TYPE_DS, 24419370Spst LDNS_RR_CLASS_IN, 24519370Spst qflags); 24619370Spst if (!my_pkt) { 24719370Spst return new_chain; 24819370Spst } 24919370Spst 25098948Sobrien if (ldns_pkt_ancount(my_pkt) > 0) { 25146283Sdfr /* add error, no sigs but DS in parent */ 25298948Sobrien /*ldns_pkt_print(stdout, my_pkt);*/ 25319370Spst ldns_pkt_free(my_pkt); 25498948Sobrien } else { 25519370Spst /* are there signatures? */ 25698948Sobrien new_chain->parent = ldns_dnssec_build_data_chain(res, 25719370Spst qflags, 25898948Sobrien NULL, 25919370Spst my_pkt, 26098948Sobrien NULL); 26119370Spst 26298948Sobrien new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; 26319370Spst 26498948Sobrien } 26519370Spst return new_chain; 26698948Sobrien} 26719370Spst 26898948Sobrien 26919370Spstldns_dnssec_data_chain * 27098948Sobrienldns_dnssec_build_data_chain(ldns_resolver *res, 27119370Spst uint16_t qflags, 27298948Sobrien const ldns_rr_list *rrset, 27319370Spst const ldns_pkt *pkt, 27498948Sobrien ldns_rr *orig_rr) 27519370Spst{ 27698948Sobrien ldns_rr_list *signatures = NULL; 27719370Spst ldns_rr_list *dss = NULL; 27898948Sobrien 27919370Spst ldns_rr_list *my_rrset; 28098948Sobrien 28119370Spst ldns_pkt *my_pkt; 28298948Sobrien 28319370Spst ldns_rdf *name = NULL, *key_name = NULL; 28498948Sobrien ldns_rr_type type = 0; 28519370Spst ldns_rr_class c = 0; 28698948Sobrien 28719370Spst bool other_rrset = false; 28898948Sobrien 28919370Spst ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new(); 29098948Sobrien 29198948Sobrien assert(pkt != NULL); 29298948Sobrien 29398948Sobrien if (!ldns_dnssec_pkt_has_rrsigs(pkt)) { 29419370Spst /* hmm. no dnssec data in the packet. go up to try and deny 29519370Spst * DS? */ 29619370Spst return new_chain; 29798948Sobrien } 29898948Sobrien 29919370Spst if (orig_rr) { 30019370Spst new_chain->rrset = ldns_rr_list_new(); 30119370Spst ldns_rr_list_push_rr(new_chain->rrset, orig_rr); 30298948Sobrien new_chain->parent = ldns_dnssec_build_data_chain(res, 30319370Spst qflags, 30419370Spst rrset, 30519370Spst pkt, 30619370Spst NULL); 30719370Spst new_chain->packet_rcode = ldns_pkt_get_rcode(pkt); 30819370Spst new_chain->packet_qtype = ldns_rr_get_type(orig_rr); 30919370Spst if (ldns_pkt_ancount(pkt) == 0) { 31098948Sobrien new_chain->packet_nodata = true; 31198948Sobrien } 31219370Spst return new_chain; 31319370Spst } 31419370Spst 31519370Spst if (!rrset || ldns_rr_list_rr_count(rrset) < 1) { 31619370Spst /* hmm, no data, do we have denial? only works if pkt was given, 31719370Spst otherwise caller has to do the check himself */ 31819370Spst new_chain->packet_nodata = true; 31919370Spst if (pkt) { 32019370Spst my_rrset = ldns_pkt_rr_list_by_type(pkt, 32198948Sobrien LDNS_RR_TYPE_NSEC, 32219370Spst LDNS_SECTION_ANY_NOQUESTION 32319370Spst ); 32419370Spst if (my_rrset) { 32519370Spst if (ldns_rr_list_rr_count(my_rrset) > 0) { 32619370Spst type = LDNS_RR_TYPE_NSEC; 32719370Spst other_rrset = true; 32898948Sobrien } else { 32919370Spst ldns_rr_list_deep_free(my_rrset); 33019370Spst my_rrset = NULL; 33119370Spst } 33219370Spst } else { 33319370Spst /* nothing, try nsec3 */ 33419370Spst my_rrset = ldns_pkt_rr_list_by_type(pkt, 33519370Spst LDNS_RR_TYPE_NSEC3, 33619370Spst LDNS_SECTION_ANY_NOQUESTION); 33719370Spst if (my_rrset) { 33819370Spst if (ldns_rr_list_rr_count(my_rrset) > 0) { 33919370Spst type = LDNS_RR_TYPE_NSEC3; 34098948Sobrien other_rrset = true; 34119370Spst } else { 342130809Smarcel ldns_rr_list_deep_free(my_rrset); 343130809Smarcel my_rrset = NULL; 34419370Spst } 34546283Sdfr } else { 346130809Smarcel /* nothing, stop */ 34719370Spst /* try parent zone? for denied insecure? */ 34819370Spst return new_chain; 34919370Spst } 35019370Spst } 351130809Smarcel } else { 35219370Spst return new_chain; 35319370Spst } 35419370Spst } else { 35519370Spst my_rrset = (ldns_rr_list *) rrset; 35619370Spst } 35719370Spst 35819370Spst if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) { 35919370Spst new_chain->rrset = ldns_rr_list_clone(my_rrset); 36019370Spst name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0)); 36119370Spst type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0)); 36219370Spst c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0)); 36319370Spst } 36419370Spst 36519370Spst if (other_rrset) { 36698948Sobrien ldns_rr_list_deep_free(my_rrset); 36719370Spst } 368130809Smarcel 369130809Smarcel /* normally there will only be 1 signature 'set' 37019370Spst but there can be more than 1 denial (wildcards) 37119370Spst so check for NSEC 37219370Spst */ 37346283Sdfr if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) { 37446283Sdfr /* just throw in all signatures, the tree builder must sort 37546283Sdfr this out */ 37619370Spst if (pkt) { 37746283Sdfr signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); 37846283Sdfr } else { 37946283Sdfr my_pkt = ldns_resolver_query(res, name, type, c, qflags); 38046283Sdfr if (my_pkt) { 38146283Sdfr signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); 38246283Sdfr ldns_pkt_free(my_pkt); 38346283Sdfr } 38446283Sdfr } 38546283Sdfr } else { 38646283Sdfr if (pkt) { 38746283Sdfr signatures = 38846283Sdfr ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, 38946283Sdfr name, 39046283Sdfr type); 39119370Spst } 39219370Spst if (!signatures) { 39319370Spst my_pkt = ldns_resolver_query(res, name, type, c, qflags); 39419370Spst if (my_pkt) { 39546283Sdfr signatures = 39646283Sdfr ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt, 39798948Sobrien name, 39846283Sdfr type); 39946283Sdfr ldns_pkt_free(my_pkt); 40046283Sdfr } 40119370Spst } 40246283Sdfr } 40319370Spst 40419370Spst if (signatures && ldns_rr_list_rr_count(signatures) > 0) { 40519370Spst key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7); 40619370Spst } 40719370Spst if (!key_name) { 40819370Spst if (signatures) { 40998948Sobrien ldns_rr_list_deep_free(signatures); 41019370Spst } 411130809Smarcel return ldns_dnssec_build_data_chain_nokeyname(res, 41219370Spst qflags, 41319370Spst orig_rr, 41419370Spst rrset, 41519370Spst new_chain); 41619370Spst } 41719370Spst if (type != LDNS_RR_TYPE_DNSKEY) { 41819370Spst ldns_dnssec_build_data_chain_dnskey(res, 41998948Sobrien qflags, 42019370Spst pkt, 42119370Spst signatures, 42219370Spst new_chain, 42319370Spst key_name, 42419370Spst c 42519370Spst ); 42698948Sobrien } else { 42798948Sobrien ldns_dnssec_build_data_chain_other(res, 42819370Spst qflags, 42919370Spst new_chain, 43019370Spst key_name, 43146283Sdfr c, 43219370Spst dss 43319370Spst ); 43419370Spst } 43519370Spst if (signatures) { 43619370Spst ldns_rr_list_deep_free(signatures); 43798948Sobrien } 43846283Sdfr return new_chain; 43919370Spst} 44019370Spst 44119370Spstldns_dnssec_trust_tree * 44298948Sobrienldns_dnssec_trust_tree_new(void) 44346283Sdfr{ 44419370Spst ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, 44519370Spst 1); 44619370Spst if(!new_tree) return NULL; 44798948Sobrien new_tree->rr = NULL; 44846283Sdfr new_tree->rrset = NULL; 44919370Spst new_tree->parent_count = 0; 45019370Spst 45119370Spst return new_tree; 45219370Spst} 45346283Sdfr 45419370Spstvoid 45519370Spstldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree) 45619370Spst{ 45719370Spst size_t i; 45898948Sobrien if (tree) { 45946283Sdfr for (i = 0; i < tree->parent_count; i++) { 46019370Spst ldns_dnssec_trust_tree_free(tree->parents[i]); 46119370Spst } 46219370Spst } 46398948Sobrien LDNS_FREE(tree); 46498948Sobrien} 46519370Spst 46698948Sobriensize_t 46746283Sdfrldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree) 46819370Spst{ 46919370Spst size_t result = 0; 47019370Spst size_t parent = 0; 47119370Spst size_t i; 47219370Spst 47319370Spst for (i = 0; i < tree->parent_count; i++) { 47419370Spst parent = ldns_dnssec_trust_tree_depth(tree->parents[i]); 47598948Sobrien if (parent > result) { 47646283Sdfr result = parent; 47719370Spst } 47819370Spst } 47919370Spst return 1 + result; 48019370Spst} 48119370Spst 48298948Sobrien/* TODO ldns_ */ 48398948Sobrienstatic void 48498948Sobrienprint_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth) 485130809Smarcel{ 48619370Spst size_t i; 48719370Spst for (i = 0; i < nr; i++) { 48819370Spst if (i == nr - 1) { 48919370Spst fprintf(out, "|---"); 49019370Spst } else if (map && i < treedepth && map[i] == 1) { 49119370Spst fprintf(out, "| "); 49219370Spst } else { 49398948Sobrien fprintf(out, " "); 49419370Spst } 49519370Spst } 49698948Sobrien} 49746283Sdfr 49819370Spststatic void 49919370Spstldns_dnssec_trust_tree_print_sm_fmt(FILE *out, 50019370Spst const ldns_output_format *fmt, 50198948Sobrien ldns_dnssec_trust_tree *tree, 50246283Sdfr size_t tabs, 50319370Spst bool extended, 50419370Spst uint8_t *sibmap, 50519370Spst size_t treedepth) 50619370Spst{ 50746283Sdfr size_t i; 50819370Spst const ldns_rr_descriptor *descriptor; 50998948Sobrien bool mapset = false; 51019370Spst 51119370Spst if (!sibmap) { 51219370Spst treedepth = ldns_dnssec_trust_tree_depth(tree); 51319370Spst sibmap = LDNS_XMALLOC(uint8_t, treedepth); 51419370Spst if(!sibmap) 51519370Spst return; /* mem err */ 51646283Sdfr memset(sibmap, 0, treedepth); 51719370Spst mapset = true; 51819370Spst } 51919370Spst 52019370Spst if (tree) { 52119370Spst if (tree->rr) { 52219370Spst print_tabs(out, tabs, sibmap, treedepth); 52319370Spst ldns_rdf_print(out, ldns_rr_owner(tree->rr)); 52419370Spst descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr)); 52519370Spst 52619370Spst if (descriptor->_name) { 52719370Spst fprintf(out, " (%s", descriptor->_name); 52898948Sobrien } else { 52919370Spst fprintf(out, " (TYPE%d", 53019370Spst ldns_rr_get_type(tree->rr)); 53119370Spst } 53219370Spst if (tabs > 0) { 53319370Spst if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) { 53446283Sdfr fprintf(out, " keytag: %u", 53546283Sdfr (unsigned int) ldns_calc_keytag(tree->rr)); 53619370Spst fprintf(out, " alg: "); 53719370Spst ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); 53846283Sdfr fprintf(out, " flags: "); 53919370Spst ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 54046283Sdfr } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) { 54119370Spst fprintf(out, " keytag: "); 54219370Spst ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 54319370Spst fprintf(out, " digest type: "); 54419370Spst ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); 54519370Spst } 54619370Spst if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) { 54746283Sdfr fprintf(out, " "); 54846283Sdfr ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 54946283Sdfr fprintf(out, " "); 55046283Sdfr ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1)); 55198948Sobrien } 55246283Sdfr } 55319370Spst 55446283Sdfr fprintf(out, ")\n"); 55519370Spst for (i = 0; i < tree->parent_count; i++) { 55619370Spst if (tree->parent_count > 1 && i < tree->parent_count - 1) { 55719370Spst sibmap[tabs] = 1; 55819370Spst } else { 55919370Spst sibmap[tabs] = 0; 56098948Sobrien } 56198948Sobrien /* only print errors */ 56219370Spst if (ldns_rr_get_type(tree->parents[i]->rr) == 56319370Spst LDNS_RR_TYPE_NSEC || 56419370Spst ldns_rr_get_type(tree->parents[i]->rr) == 56519370Spst LDNS_RR_TYPE_NSEC3) { 56619370Spst if (tree->parent_status[i] == LDNS_STATUS_OK) { 56746283Sdfr print_tabs(out, tabs + 1, sibmap, treedepth); 56898948Sobrien if (tabs == 0 && 56919370Spst ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS && 57019370Spst ldns_rr_rd_count(tree->rr) > 0) { 57198948Sobrien fprintf(out, "Existence of DS is denied by:\n"); 57219370Spst } else { 57398948Sobrien fprintf(out, "Existence is denied by:\n"); 57419370Spst } 57598948Sobrien } else { 57619370Spst /* NS records aren't signed */ 57719370Spst if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) { 57819370Spst fprintf(out, "Existence of DS is denied by:\n"); 57998948Sobrien } else { 58019370Spst print_tabs(out, tabs + 1, sibmap, treedepth); 58119370Spst fprintf(out, 58219370Spst "Error in denial of existence: %s\n", 58319370Spst ldns_get_errorstr_by_id( 58419370Spst tree->parent_status[i])); 58519370Spst } 58619370Spst } 58719370Spst } else 58819370Spst if (tree->parent_status[i] != LDNS_STATUS_OK) { 58919370Spst print_tabs(out, tabs + 1, sibmap, treedepth); 59019370Spst fprintf(out, 59119370Spst "%s:\n", 59219370Spst ldns_get_errorstr_by_id( 59319370Spst tree->parent_status[i])); 59498948Sobrien if (tree->parent_status[i] 59519370Spst == LDNS_STATUS_SSL_ERR) { 59619370Spst printf("; SSL Error: "); 59719370Spst ERR_load_crypto_strings(); 59819370Spst ERR_print_errors_fp(stdout); 59919370Spst printf("\n"); 60019370Spst } 60119370Spst ldns_rr_print_fmt(out, fmt, 60219370Spst tree-> 60319370Spst parent_signature[i]); 60419370Spst printf("For RRset:\n"); 60519370Spst ldns_rr_list_print_fmt(out, fmt, 60619370Spst tree->rrset); 60719370Spst printf("With key:\n"); 60819370Spst ldns_rr_print_fmt(out, fmt, 60919370Spst tree->parents[i]->rr); 61019370Spst } 61119370Spst ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 61219370Spst tree->parents[i], 61319370Spst tabs+1, 61419370Spst extended, 61598948Sobrien sibmap, 61619370Spst treedepth); 61719370Spst } 61898948Sobrien } else { 61919370Spst print_tabs(out, tabs, sibmap, treedepth); 62019370Spst fprintf(out, "<no data>\n"); 62119370Spst } 62219370Spst } else { 62319370Spst fprintf(out, "<null pointer>\n"); 62419370Spst } 62519370Spst 62619370Spst if (mapset) { 62746283Sdfr LDNS_FREE(sibmap); 62898948Sobrien } 629130809Smarcel} 63019370Spst 63146283Sdfr#if 0 63246283Sdfrstatic void 63346283Sdfrldns_dnssec_trust_tree_print_sm(FILE *out, 63446283Sdfr ldns_dnssec_trust_tree *tree, 63519370Spst size_t tabs, 63619370Spst bool extended, 63719370Spst uint8_t *sibmap, 63819370Spst size_t treedepth) 63919370Spst{ 64019370Spst ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default, 64119370Spst tree, tabs, extended, sibmap, treedepth); 64298948Sobrien} 64319370Spst#endif 64419370Spst 64519370Spstvoid 64619370Spstldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt, 64719370Spst ldns_dnssec_trust_tree *tree, 64819370Spst size_t tabs, 64919370Spst bool extended) 65019370Spst{ 65119370Spst ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 65219370Spst tree, tabs, extended, NULL, 0); 653130809Smarcel} 654130809Smarcel 65519370Spstvoid 65619370Spstldns_dnssec_trust_tree_print(FILE *out, 65719370Spst ldns_dnssec_trust_tree *tree, 65819370Spst size_t tabs, 659130809Smarcel bool extended) 66019370Spst{ 66119370Spst ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, 66219370Spst tree, tabs, extended); 66319370Spst} 66419370Spst 66519370Spst 66619370Spstldns_status 66719370Spstldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, 66819370Spst const ldns_dnssec_trust_tree *parent, 66998948Sobrien const ldns_rr *signature, 67098948Sobrien const ldns_status parent_status) 67119370Spst{ 67219370Spst if (tree 67319370Spst && parent 67419370Spst && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) { 67519370Spst /* 67619370Spst printf("Add parent for: "); 67719370Spst ldns_rr_print(stdout, tree->rr); 67819370Spst printf("parent: "); 67998948Sobrien ldns_rr_print(stdout, parent->rr); 680130809Smarcel */ 681130809Smarcel tree->parents[tree->parent_count] = 68219370Spst (ldns_dnssec_trust_tree *) parent; 68319370Spst tree->parent_status[tree->parent_count] = parent_status; 68419370Spst tree->parent_signature[tree->parent_count] = (ldns_rr *) signature; 68519370Spst tree->parent_count++; 68619370Spst return LDNS_STATUS_OK; 68719370Spst } else { 68819370Spst return LDNS_STATUS_ERR; 68919370Spst } 69019370Spst} 69119370Spst 69219370Spst/* if rr is null, take the first from the rrset */ 69319370Spstldns_dnssec_trust_tree * 69419370Spstldns_dnssec_derive_trust_tree_time( 69519370Spst ldns_dnssec_data_chain *data_chain, 69619370Spst ldns_rr *rr, 69719370Spst time_t check_time 69819370Spst ) 69919370Spst{ 70019370Spst ldns_rr_list *cur_rrset; 70119370Spst ldns_rr_list *cur_sigs; 70219370Spst ldns_rr *cur_rr = NULL; 70319370Spst ldns_rr *cur_sig_rr; 70498948Sobrien size_t i, j; 70519370Spst 70619370Spst ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); 70719370Spst if(!new_tree) 70819370Spst return NULL; 70998948Sobrien 71019370Spst if (data_chain && data_chain->rrset) { 711130809Smarcel cur_rrset = data_chain->rrset; 71219370Spst 71319370Spst cur_sigs = data_chain->signatures; 71498948Sobrien 71519370Spst if (rr) { 71698948Sobrien cur_rr = rr; 71719370Spst } 71819370Spst 71919370Spst if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) { 72098948Sobrien cur_rr = ldns_rr_list_rr(cur_rrset, 0); 72198948Sobrien } 72298948Sobrien 72319370Spst if (cur_rr) { 72419370Spst new_tree->rr = cur_rr; 72519370Spst new_tree->rrset = cur_rrset; 72619370Spst /* there are three possibilities: 72719370Spst 1 - 'normal' rrset, signed by a key 72819370Spst 2 - dnskey signed by other dnskey 72919370Spst 3 - dnskey proven by higher level DS 73019370Spst (data denied by nsec is a special case that can 73119370Spst occur in multiple places) 73219370Spst 73319370Spst */ 73419370Spst if (cur_sigs) { 73598948Sobrien for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { 73619370Spst /* find the appropriate key in the parent list */ 73719370Spst cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); 73819370Spst 73946283Sdfr if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { 74046283Sdfr if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 741130809Smarcel ldns_rr_owner(cur_rr))) 742130809Smarcel { 74346283Sdfr /* find first that does match */ 74446283Sdfr 74546283Sdfr for (j = 0; 74698948Sobrien j < ldns_rr_list_rr_count(cur_rrset) && 74798948Sobrien ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0; 74846283Sdfr j++) { 74998948Sobrien cur_rr = ldns_rr_list_rr(cur_rrset, j); 75046283Sdfr 75198948Sobrien } 75219370Spst if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 75319370Spst ldns_rr_owner(cur_rr))) 75419370Spst { 75598948Sobrien break; 75619370Spst } 75719370Spst } 75846283Sdfr 75919370Spst } 76019370Spst /* option 1 */ 76119370Spst if (data_chain->parent) { 76219370Spst ldns_dnssec_derive_trust_tree_normal_rrset_time( 76319370Spst new_tree, 76419370Spst data_chain, 76519370Spst cur_sig_rr, 76619370Spst check_time); 76719370Spst } 76819370Spst 76919370Spst /* option 2 */ 77019370Spst ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 77119370Spst new_tree, 77219370Spst data_chain, 77319370Spst cur_rr, 77419370Spst cur_sig_rr, 77519370Spst check_time); 77619370Spst } 77719370Spst 77819370Spst ldns_dnssec_derive_trust_tree_ds_rrset_time( 77919370Spst new_tree, data_chain, 78019370Spst cur_rr, check_time); 78119370Spst } else { 782130809Smarcel /* no signatures? maybe it's nsec data */ 783130809Smarcel 784130809Smarcel /* just add every rr from parent as new parent */ 785130809Smarcel ldns_dnssec_derive_trust_tree_no_sig_time( 78619370Spst new_tree, data_chain, check_time); 78719370Spst } 78819370Spst } 78919370Spst } 79019370Spst 79119370Spst return new_tree; 79219370Spst} 79398948Sobrien 79419370Spstldns_dnssec_trust_tree * 79519370Spstldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) 79619370Spst{ 79719370Spst return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL)); 798130809Smarcel} 799130809Smarcel 800130809Smarcelvoid 801130809Smarcelldns_dnssec_derive_trust_tree_normal_rrset_time( 802130809Smarcel ldns_dnssec_trust_tree *new_tree, 803130809Smarcel ldns_dnssec_data_chain *data_chain, 804130809Smarcel ldns_rr *cur_sig_rr, 805130809Smarcel time_t check_time) 806130809Smarcel{ 807130809Smarcel size_t i, j; 808130809Smarcel ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 809130809Smarcel ldns_dnssec_trust_tree *cur_parent_tree; 81019370Spst ldns_rr *cur_parent_rr; 81119370Spst uint16_t cur_keytag; 81219370Spst ldns_rr_list *tmp_rrset = NULL; 81319370Spst ldns_status cur_status; 81419370Spst 81519370Spst cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); 81619370Spst 81719370Spst for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) { 81819370Spst cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); 81919370Spst if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { 82019370Spst if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) { 82119370Spst 82219370Spst /* TODO: check wildcard nsec too */ 82319370Spst if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { 82419370Spst tmp_rrset = cur_rrset; 825130809Smarcel if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) 82619370Spst == LDNS_RR_TYPE_NSEC || 82719370Spst ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) 82819370Spst == LDNS_RR_TYPE_NSEC3) { 82919370Spst /* might contain different names! 83019370Spst sort and split */ 83119370Spst ldns_rr_list_sort(cur_rrset); 83219370Spst assert(tmp_rrset == cur_rrset); 83319370Spst tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset); 83419370Spst 83519370Spst /* with nsecs, this might be the wrong one */ 83619370Spst while (tmp_rrset && 83719370Spst ldns_rr_list_rr_count(cur_rrset) > 0 && 838130809Smarcel ldns_dname_compare( 839130809Smarcel ldns_rr_owner(ldns_rr_list_rr( 840130809Smarcel tmp_rrset, 0)), 841130809Smarcel ldns_rr_owner(cur_sig_rr)) != 0) { 842130809Smarcel ldns_rr_list_deep_free(tmp_rrset); 843130809Smarcel tmp_rrset = 844130809Smarcel ldns_rr_list_pop_rrset(cur_rrset); 845130809Smarcel } 846130809Smarcel } 847130809Smarcel cur_status = ldns_verify_rrsig_time( 848130809Smarcel tmp_rrset, 849130809Smarcel cur_sig_rr, 85046283Sdfr cur_parent_rr, 85146283Sdfr check_time); 85246283Sdfr if (tmp_rrset && tmp_rrset != cur_rrset 85346283Sdfr ) { 85446283Sdfr ldns_rr_list_deep_free( 85598948Sobrien tmp_rrset); 85698948Sobrien tmp_rrset = NULL; 85798948Sobrien } 85898948Sobrien /* avoid dupes */ 85946283Sdfr for (i = 0; i < new_tree->parent_count; i++) { 86046283Sdfr if (cur_parent_rr == new_tree->parents[i]->rr) { 86119370Spst goto done; 86219370Spst } 86319370Spst } 86419370Spst 86519370Spst cur_parent_tree = 86619370Spst ldns_dnssec_derive_trust_tree_time( 86719370Spst data_chain->parent, 86819370Spst cur_parent_rr, 86919370Spst check_time); 87019370Spst (void)ldns_dnssec_trust_tree_add_parent(new_tree, 87198948Sobrien cur_parent_tree, 87219370Spst cur_sig_rr, 87346283Sdfr cur_status); 87446283Sdfr } 87519370Spst } 87619370Spst } 87746283Sdfr } 87819370Spst done: 87998948Sobrien ldns_rr_list_deep_free(cur_rrset); 88019370Spst} 88146283Sdfr 88246283Sdfrvoid 88346283Sdfrldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, 88446283Sdfr ldns_dnssec_data_chain *data_chain, 88519370Spst ldns_rr *cur_sig_rr) 88619370Spst{ 88719370Spst ldns_dnssec_derive_trust_tree_normal_rrset_time( 88819370Spst new_tree, data_chain, cur_sig_rr, ldns_time(NULL)); 88919370Spst} 89019370Spst 89198948Sobrienvoid 89219370Spstldns_dnssec_derive_trust_tree_dnskey_rrset_time( 89319370Spst ldns_dnssec_trust_tree *new_tree, 89419370Spst ldns_dnssec_data_chain *data_chain, 89598948Sobrien ldns_rr *cur_rr, 89619370Spst ldns_rr *cur_sig_rr, 89719370Spst time_t check_time) 89819370Spst{ 89919370Spst size_t j; 90019370Spst ldns_rr_list *cur_rrset = data_chain->rrset; 90198948Sobrien ldns_dnssec_trust_tree *cur_parent_tree; 90219370Spst ldns_rr *cur_parent_rr; 90319370Spst uint16_t cur_keytag; 90419370Spst ldns_status cur_status; 90519370Spst 90619370Spst cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); 90719370Spst 90898948Sobrien for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) { 90998948Sobrien cur_parent_rr = ldns_rr_list_rr(cur_rrset, j); 91019370Spst if (cur_parent_rr != cur_rr && 91119370Spst ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { 91219370Spst if (ldns_calc_keytag(cur_parent_rr) == cur_keytag 91319370Spst ) { 91419370Spst cur_parent_tree = ldns_dnssec_trust_tree_new(); 91519370Spst cur_parent_tree->rr = cur_parent_rr; 91619370Spst cur_parent_tree->rrset = cur_rrset; 91719370Spst cur_status = ldns_verify_rrsig_time( 91819370Spst cur_rrset, cur_sig_rr, 91919370Spst cur_parent_rr, check_time); 92019370Spst (void) ldns_dnssec_trust_tree_add_parent(new_tree, 92119370Spst cur_parent_tree, cur_sig_rr, cur_status); 92298948Sobrien } 92319370Spst } 92419370Spst } 92519370Spst} 92619370Spst 92719370Spstvoid 928130809Smarcelldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, 92919370Spst ldns_dnssec_data_chain *data_chain, 93019370Spst ldns_rr *cur_rr, 931130809Smarcel ldns_rr *cur_sig_rr) 93219370Spst{ 93319370Spst ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 93419370Spst new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL)); 93519370Spst} 93619370Spst 93719370Spstvoid 93898948Sobrienldns_dnssec_derive_trust_tree_ds_rrset_time( 93919370Spst ldns_dnssec_trust_tree *new_tree, 940130809Smarcel ldns_dnssec_data_chain *data_chain, 94119370Spst ldns_rr *cur_rr, 94219370Spst time_t check_time) 94319370Spst{ 94498948Sobrien size_t j, h; 94598948Sobrien ldns_rr_list *cur_rrset = data_chain->rrset; 94698948Sobrien ldns_dnssec_trust_tree *cur_parent_tree; 94798948Sobrien ldns_rr *cur_parent_rr; 94898948Sobrien 94998948Sobrien /* try the parent to see whether there are DSs there */ 95098948Sobrien if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY && 95198948Sobrien data_chain->parent && 95298948Sobrien data_chain->parent->rrset 95398948Sobrien ) { 95498948Sobrien for (j = 0; 95598948Sobrien j < ldns_rr_list_rr_count(data_chain->parent->rrset); 95698948Sobrien j++) { 95798948Sobrien cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); 95898948Sobrien if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) { 95998948Sobrien for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) { 96098948Sobrien cur_rr = ldns_rr_list_rr(cur_rrset, h); 96198948Sobrien if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) { 96298948Sobrien cur_parent_tree = 96398948Sobrien ldns_dnssec_derive_trust_tree_time( 96498948Sobrien data_chain->parent, 96598948Sobrien cur_parent_rr, 96698948Sobrien check_time); 96798948Sobrien (void) ldns_dnssec_trust_tree_add_parent( 968130809Smarcel new_tree, 969130809Smarcel cur_parent_tree, 97098948Sobrien NULL, 97198948Sobrien LDNS_STATUS_OK); 97298948Sobrien } else { 97398948Sobrien /*ldns_rr_print(stdout, cur_parent_rr);*/ 97498948Sobrien } 97598948Sobrien } 97698948Sobrien } 97798948Sobrien } 97819370Spst } 97919370Spst} 98019370Spst 98119370Spstvoid 98298948Sobrienldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, 98319370Spst ldns_dnssec_data_chain *data_chain, 98419370Spst ldns_rr *cur_rr) 98519370Spst{ 98619370Spst ldns_dnssec_derive_trust_tree_ds_rrset_time( 98719370Spst new_tree, data_chain, cur_rr, ldns_time(NULL)); 98819370Spst} 98919370Spst 99019370Spstvoid 99119370Spstldns_dnssec_derive_trust_tree_no_sig_time( 99219370Spst ldns_dnssec_trust_tree *new_tree, 99319370Spst ldns_dnssec_data_chain *data_chain, 99419370Spst time_t check_time) 99519370Spst{ 99619370Spst size_t i; 99719370Spst ldns_rr_list *cur_rrset; 99819370Spst ldns_rr *cur_parent_rr; 99919370Spst ldns_dnssec_trust_tree *cur_parent_tree; 100019370Spst ldns_status result; 100119370Spst 100219370Spst if (data_chain->parent && data_chain->parent->rrset) { 100319370Spst cur_rrset = data_chain->parent->rrset; 100419370Spst /* nsec? */ 100519370Spst if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { 100619370Spst if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == 100719370Spst LDNS_RR_TYPE_NSEC3) { 100819370Spst result = ldns_dnssec_verify_denial_nsec3( 100919370Spst new_tree->rr, 101019370Spst cur_rrset, 101119370Spst data_chain->parent->signatures, 101219370Spst data_chain->packet_rcode, 101398948Sobrien data_chain->packet_qtype, 101419370Spst data_chain->packet_nodata); 101519370Spst } else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == 101619370Spst LDNS_RR_TYPE_NSEC) { 101719370Spst result = ldns_dnssec_verify_denial( 101819370Spst new_tree->rr, 101919370Spst cur_rrset, 102019370Spst data_chain->parent->signatures); 102119370Spst } else { 102219370Spst /* unsigned zone, unsigned parent */ 102319370Spst result = LDNS_STATUS_OK; 102419370Spst } 102519370Spst } else { 102619370Spst result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 102719370Spst } 102819370Spst for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) { 102919370Spst cur_parent_rr = ldns_rr_list_rr(cur_rrset, i); 103019370Spst cur_parent_tree = 103119370Spst ldns_dnssec_derive_trust_tree_time( 103219370Spst data_chain->parent, 103319370Spst cur_parent_rr, 103419370Spst check_time); 103519370Spst (void) ldns_dnssec_trust_tree_add_parent(new_tree, 103619370Spst cur_parent_tree, NULL, result); 103719370Spst } 103819370Spst } 103919370Spst} 104098948Sobrien 104119370Spstvoid 104219370Spstldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, 104319370Spst ldns_dnssec_data_chain *data_chain) 104419370Spst{ 104598948Sobrien ldns_dnssec_derive_trust_tree_no_sig_time( 104619370Spst new_tree, data_chain, ldns_time(NULL)); 104719370Spst} 104819370Spst 104919370Spst/* 105098948Sobrien * returns OK if there is a path from tree to key with only OK 105119370Spst * the (first) error in between otherwise 105219370Spst * or NOT_FOUND if the key wasn't present at all 105319370Spst */ 105419370Spstldns_status 105519370Spstldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, 105619370Spst ldns_rr_list *trusted_keys) 105719370Spst{ 105819370Spst size_t i; 105919370Spst ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY; 106019370Spst bool equal; 106119370Spst ldns_status parent_result; 106219370Spst 106319370Spst if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0) 106419370Spst { if (tree->rr) { 106519370Spst for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { 106619370Spst equal = ldns_rr_compare_ds( 106719370Spst tree->rr, 106819370Spst ldns_rr_list_rr(trusted_keys, i)); 106919370Spst if (equal) { 107019370Spst result = LDNS_STATUS_OK; 107119370Spst return result; 107219370Spst } 107319370Spst } 107498948Sobrien } 107519370Spst for (i = 0; i < tree->parent_count; i++) { 107698948Sobrien parent_result = 107719370Spst ldns_dnssec_trust_tree_contains_keys(tree->parents[i], 107819370Spst trusted_keys); 107919370Spst if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) { 108019370Spst if (tree->parent_status[i] != LDNS_STATUS_OK) { 108119370Spst result = tree->parent_status[i]; 108219370Spst } else { 108319370Spst if (tree->rr && 108419370Spst ldns_rr_get_type(tree->rr) 108519370Spst == LDNS_RR_TYPE_NSEC && 108619370Spst parent_result == LDNS_STATUS_OK 108719370Spst ) { 108819370Spst result = 108919370Spst LDNS_STATUS_DNSSEC_EXISTENCE_DENIED; 109019370Spst } else { 109198948Sobrien result = parent_result; 109219370Spst } 109319370Spst } 109419370Spst } 109519370Spst } 109619370Spst } else { 109719370Spst result = LDNS_STATUS_ERR; 109819370Spst } 109919370Spst 110019370Spst return result; 110119370Spst} 110219370Spst 110319370Spstldns_status 110419370Spstldns_verify_time( 110519370Spst ldns_rr_list *rrset, 110619370Spst ldns_rr_list *rrsig, 110719370Spst const ldns_rr_list *keys, 110819370Spst time_t check_time, 110919370Spst ldns_rr_list *good_keys 111019370Spst ) 111119370Spst{ 111219370Spst uint16_t i; 111346283Sdfr ldns_status verify_result = LDNS_STATUS_ERR; 111446283Sdfr 111519370Spst if (!rrset || !rrsig || !keys) { 111619370Spst return LDNS_STATUS_ERR; 111719370Spst } 111819370Spst 111919370Spst if (ldns_rr_list_rr_count(rrset) < 1) { 1120130809Smarcel return LDNS_STATUS_ERR; 1121130809Smarcel } 1122130809Smarcel 1123130809Smarcel if (ldns_rr_list_rr_count(rrsig) < 1) { 1124130809Smarcel return LDNS_STATUS_CRYPTO_NO_RRSIG; 1125130809Smarcel } 1126130809Smarcel 1127130809Smarcel if (ldns_rr_list_rr_count(keys) < 1) { 1128130809Smarcel verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 1129130809Smarcel } else { 1130130809Smarcel for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { 1131130809Smarcel ldns_status s = ldns_verify_rrsig_keylist_time( 1132130809Smarcel rrset, ldns_rr_list_rr(rrsig, i), 1133130809Smarcel keys, check_time, good_keys); 1134130809Smarcel /* try a little to get more descriptive error */ 1135130809Smarcel if(s == LDNS_STATUS_OK) { 1136130809Smarcel verify_result = LDNS_STATUS_OK; 1137130809Smarcel } else if(verify_result == LDNS_STATUS_ERR) 1138130809Smarcel verify_result = s; 1139130809Smarcel else if(s != LDNS_STATUS_ERR && verify_result == 1140130809Smarcel LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) 1141130809Smarcel verify_result = s; 1142130809Smarcel } 1143130809Smarcel } 1144130809Smarcel return verify_result; 1145130809Smarcel} 1146130809Smarcel 1147130809Smarcelldns_status 1148130809Smarcelldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 1149130809Smarcel ldns_rr_list *good_keys) 1150130809Smarcel{ 1151130809Smarcel return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys); 1152130809Smarcel} 1153130809Smarcel 1154130809Smarcelldns_status 1155130809Smarcelldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig, 1156130809Smarcel const ldns_rr_list *keys, ldns_rr_list *good_keys) 1157130809Smarcel{ 1158130809Smarcel uint16_t i; 1159130809Smarcel ldns_status verify_result = LDNS_STATUS_ERR; 1160130809Smarcel 1161130809Smarcel if (!rrset || !rrsig || !keys) { 1162130809Smarcel return LDNS_STATUS_ERR; 1163130809Smarcel } 1164130809Smarcel 1165130809Smarcel if (ldns_rr_list_rr_count(rrset) < 1) { 1166130809Smarcel return LDNS_STATUS_ERR; 1167130809Smarcel } 1168130809Smarcel 1169130809Smarcel if (ldns_rr_list_rr_count(rrsig) < 1) { 1170130809Smarcel return LDNS_STATUS_CRYPTO_NO_RRSIG; 1171130809Smarcel } 1172130809Smarcel 1173130809Smarcel if (ldns_rr_list_rr_count(keys) < 1) { 117498948Sobrien verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 117598948Sobrien } else { 117619370Spst for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { 117719370Spst ldns_status s = ldns_verify_rrsig_keylist_notime(rrset, 117898948Sobrien ldns_rr_list_rr(rrsig, i), keys, good_keys); 117919370Spst 1180130809Smarcel /* try a little to get more descriptive error */ 118146283Sdfr if (s == LDNS_STATUS_OK) { 118298948Sobrien verify_result = LDNS_STATUS_OK; 118398948Sobrien } else if (verify_result == LDNS_STATUS_ERR) { 118446283Sdfr verify_result = s; 1185130809Smarcel } else if (s != LDNS_STATUS_ERR && verify_result == 118619370Spst LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { 118719370Spst verify_result = s; 118819370Spst } 118919370Spst } 119019370Spst } 119119370Spst return verify_result; 119246283Sdfr} 1193130809Smarcel 119419370Spstldns_rr_list * 119519370Spstldns_fetch_valid_domain_keys_time(const ldns_resolver *res, 119619370Spst const ldns_rdf *domain, 119719370Spst const ldns_rr_list *keys, 119819370Spst time_t check_time, 119919370Spst ldns_status *status) 120019370Spst{ 120119370Spst ldns_rr_list * trusted_keys = NULL; 120219370Spst ldns_rr_list * ds_keys = NULL; 120319370Spst ldns_rdf * prev_parent_domain; 120419370Spst ldns_rdf * parent_domain; 120519370Spst ldns_rr_list * parent_keys = NULL; 120619370Spst 120798948Sobrien if (res && domain && keys) { 120898948Sobrien 120998948Sobrien if ((trusted_keys = ldns_validate_domain_dnskey_time(res, 121019370Spst domain, keys, check_time))) { 121119370Spst *status = LDNS_STATUS_OK; 121219370Spst } else { 121319370Spst /* No trusted keys in this domain, we'll have to find some in the parent domain */ 121419370Spst *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 121519370Spst 121698948Sobrien parent_domain = ldns_dname_left_chop(domain); 121719370Spst while (parent_domain && /* Fail if we are at the root*/ 121819370Spst ldns_rdf_size(parent_domain) > 0) { 121919370Spst 122019370Spst if ((parent_keys = 122119370Spst ldns_fetch_valid_domain_keys_time(res, 122219370Spst parent_domain, 122319370Spst keys, 122419370Spst check_time, 122519370Spst status))) { 122619370Spst /* Check DS records */ 122719370Spst if ((ds_keys = 122819370Spst ldns_validate_domain_ds_time(res, 122919370Spst domain, 123019370Spst parent_keys, 123119370Spst check_time))) { 123298948Sobrien trusted_keys = 123319370Spst ldns_fetch_valid_domain_keys_time( 123419370Spst res, 123519370Spst domain, 123698948Sobrien ds_keys, 123719370Spst check_time, 123819370Spst status); 123919370Spst ldns_rr_list_deep_free(ds_keys); 124019370Spst } else { 124119370Spst /* No valid DS at the parent -- fail */ 124246283Sdfr *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ; 124346283Sdfr } 124419370Spst ldns_rr_list_deep_free(parent_keys); 1245130809Smarcel break; 1246130809Smarcel } else { 1247130809Smarcel parent_domain = ldns_dname_left_chop(( 1248130809Smarcel prev_parent_domain 1249130809Smarcel = parent_domain 1250130809Smarcel )); 1251130809Smarcel ldns_rdf_deep_free(prev_parent_domain); 1252130809Smarcel } 1253130809Smarcel } 1254130809Smarcel if (parent_domain) { 1255130809Smarcel ldns_rdf_deep_free(parent_domain); 1256130809Smarcel } 1257130809Smarcel } 1258130809Smarcel } 1259130809Smarcel return trusted_keys; 1260130809Smarcel} 1261130809Smarcel 1262130809Smarcelldns_rr_list * 1263130809Smarcelldns_fetch_valid_domain_keys(const ldns_resolver *res, 1264130809Smarcel const ldns_rdf *domain, 1265130809Smarcel const ldns_rr_list *keys, 1266130809Smarcel ldns_status *status) 1267130809Smarcel{ 1268130809Smarcel return ldns_fetch_valid_domain_keys_time( 1269130809Smarcel res, domain, keys, ldns_time(NULL), status); 1270130809Smarcel} 1271130809Smarcel 1272130809Smarcelldns_rr_list * 1273130809Smarcelldns_validate_domain_dnskey_time( 1274130809Smarcel const ldns_resolver * res, 1275130809Smarcel const ldns_rdf * domain, 1276130809Smarcel const ldns_rr_list * keys, 127719370Spst time_t check_time 127819370Spst ) 127919370Spst{ 128098948Sobrien ldns_pkt * keypkt; 128119370Spst ldns_rr * cur_key; 128219370Spst uint16_t key_i; uint16_t key_j; uint16_t key_k; 128319370Spst uint16_t sig_i; ldns_rr * cur_sig; 128419370Spst 128519370Spst ldns_rr_list * domain_keys = NULL; 128619370Spst ldns_rr_list * domain_sigs = NULL; 128719370Spst ldns_rr_list * trusted_keys = NULL; 128846283Sdfr 128946283Sdfr /* Fetch keys for the domain */ 129046283Sdfr keypkt = ldns_resolver_query(res, domain, 129146283Sdfr LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD); 129246283Sdfr if (keypkt) { 129319370Spst domain_keys = ldns_pkt_rr_list_by_type(keypkt, 129446283Sdfr LDNS_RR_TYPE_DNSKEY, 129519370Spst LDNS_SECTION_ANSWER); 129619370Spst domain_sigs = ldns_pkt_rr_list_by_type(keypkt, 129719370Spst LDNS_RR_TYPE_RRSIG, 129819370Spst LDNS_SECTION_ANSWER); 129919370Spst 130019370Spst /* Try to validate the record using our keys */ 130119370Spst for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) { 130298948Sobrien 130398948Sobrien cur_key = ldns_rr_list_rr(domain_keys, key_i); 130498948Sobrien for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) { 130598948Sobrien if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j), 130698948Sobrien cur_key)) { 130798948Sobrien 130819370Spst /* Current key is trusted -- validate */ 130998948Sobrien trusted_keys = ldns_rr_list_new(); 131098948Sobrien 131198948Sobrien for (sig_i=0; 131298948Sobrien sig_i<ldns_rr_list_rr_count(domain_sigs); 131398948Sobrien sig_i++) { 131498948Sobrien cur_sig = ldns_rr_list_rr(domain_sigs, sig_i); 131519370Spst /* Avoid non-matching sigs */ 131698948Sobrien if (ldns_rdf2native_int16( 131798948Sobrien ldns_rr_rrsig_keytag(cur_sig)) 131898948Sobrien == ldns_calc_keytag(cur_key)) { 131998948Sobrien if (ldns_verify_rrsig_time( 132019370Spst domain_keys, 132198948Sobrien cur_sig, 132298948Sobrien cur_key, 132398948Sobrien check_time) 132498948Sobrien == LDNS_STATUS_OK) { 132598948Sobrien 132698948Sobrien /* Push the whole rrset 132798948Sobrien -- we can't do much more */ 132898948Sobrien for (key_k=0; 132998948Sobrien key_k<ldns_rr_list_rr_count( 133098948Sobrien domain_keys); 133198948Sobrien key_k++) { 133298948Sobrien ldns_rr_list_push_rr( 133398948Sobrien trusted_keys, 133498948Sobrien ldns_rr_clone( 133598948Sobrien ldns_rr_list_rr( 133698948Sobrien domain_keys, 133798948Sobrien key_k))); 133898948Sobrien } 133998948Sobrien 134098948Sobrien ldns_rr_list_deep_free(domain_keys); 134198948Sobrien ldns_rr_list_deep_free(domain_sigs); 134298948Sobrien ldns_pkt_free(keypkt); 134398948Sobrien return trusted_keys; 134498948Sobrien } 134598948Sobrien } 134698948Sobrien } 134798948Sobrien 134898948Sobrien /* Only push our trusted key */ 134998948Sobrien ldns_rr_list_push_rr(trusted_keys, 135098948Sobrien ldns_rr_clone(cur_key)); 135198948Sobrien } 135298948Sobrien } 135398948Sobrien } 135498948Sobrien 135598948Sobrien ldns_rr_list_deep_free(domain_keys); 135698948Sobrien ldns_rr_list_deep_free(domain_sigs); 135798948Sobrien ldns_pkt_free(keypkt); 135898948Sobrien 135998948Sobrien } else { 136098948Sobrien /* LDNS_STATUS_CRYPTO_NO_DNSKEY */ 136198948Sobrien } 136298948Sobrien 136398948Sobrien return trusted_keys; 1364130809Smarcel} 1365130809Smarcel 136698948Sobrienldns_rr_list * 136798948Sobrienldns_validate_domain_dnskey(const ldns_resolver * res, 136898948Sobrien const ldns_rdf * domain, 136998948Sobrien const ldns_rr_list * keys) 1370130809Smarcel{ 137198948Sobrien return ldns_validate_domain_dnskey_time( 137298948Sobrien res, domain, keys, ldns_time(NULL)); 137398948Sobrien} 1374130809Smarcel 1375130809Smarcelldns_rr_list * 137698948Sobrienldns_validate_domain_ds_time( 137798948Sobrien const ldns_resolver *res, 137898948Sobrien const ldns_rdf * domain, 137998948Sobrien const ldns_rr_list * keys, 138098948Sobrien time_t check_time) 138198948Sobrien{ 138298948Sobrien ldns_pkt * dspkt; 138398948Sobrien uint16_t key_i; 138498948Sobrien ldns_rr_list * rrset = NULL; 138598948Sobrien ldns_rr_list * sigs = NULL; 138698948Sobrien ldns_rr_list * trusted_keys = NULL; 138798948Sobrien 138898948Sobrien /* Fetch DS for the domain */ 138998948Sobrien dspkt = ldns_resolver_query(res, domain, 139098948Sobrien LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD); 139198948Sobrien if (dspkt) { 139298948Sobrien rrset = ldns_pkt_rr_list_by_type(dspkt, 139398948Sobrien LDNS_RR_TYPE_DS, 139498948Sobrien LDNS_SECTION_ANSWER); 139598948Sobrien sigs = ldns_pkt_rr_list_by_type(dspkt, 139698948Sobrien LDNS_RR_TYPE_RRSIG, 139798948Sobrien LDNS_SECTION_ANSWER); 139898948Sobrien 139998948Sobrien /* Validate sigs */ 140098948Sobrien if (ldns_verify_time(rrset, sigs, keys, check_time, NULL) 140198948Sobrien == LDNS_STATUS_OK) { 140298948Sobrien trusted_keys = ldns_rr_list_new(); 140398948Sobrien for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) { 140498948Sobrien ldns_rr_list_push_rr(trusted_keys, 140598948Sobrien ldns_rr_clone(ldns_rr_list_rr(rrset, 140698948Sobrien key_i) 140798948Sobrien ) 140898948Sobrien ); 140998948Sobrien } 141098948Sobrien } 141198948Sobrien 141298948Sobrien ldns_rr_list_deep_free(rrset); 141398948Sobrien ldns_rr_list_deep_free(sigs); 141498948Sobrien ldns_pkt_free(dspkt); 141598948Sobrien 141698948Sobrien } else { 141798948Sobrien /* LDNS_STATUS_CRYPTO_NO_DS */ 141898948Sobrien } 141998948Sobrien 142098948Sobrien return trusted_keys; 142198948Sobrien} 142298948Sobrien 142398948Sobrienldns_rr_list * 142498948Sobrienldns_validate_domain_ds(const ldns_resolver *res, 142598948Sobrien const ldns_rdf * domain, 142698948Sobrien const ldns_rr_list * keys) 142798948Sobrien{ 142898948Sobrien return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL)); 142998948Sobrien} 143098948Sobrien 143198948Sobrienldns_status 143298948Sobrienldns_verify_trusted_time( 143398948Sobrien ldns_resolver *res, 143498948Sobrien ldns_rr_list *rrset, 143598948Sobrien ldns_rr_list * rrsigs, 143698948Sobrien time_t check_time, 143798948Sobrien ldns_rr_list * validating_keys 143898948Sobrien ) 143998948Sobrien{ 144098948Sobrien uint16_t sig_i; uint16_t key_i; 144198948Sobrien ldns_rr * cur_sig; ldns_rr * cur_key; 144298948Sobrien ldns_rr_list * trusted_keys = NULL; 144398948Sobrien ldns_status result = LDNS_STATUS_ERR; 144498948Sobrien 144598948Sobrien if (!res || !rrset || !rrsigs) { 144698948Sobrien return LDNS_STATUS_ERR; 144798948Sobrien } 144898948Sobrien 144998948Sobrien if (ldns_rr_list_rr_count(rrset) < 1) { 145098948Sobrien return LDNS_STATUS_ERR; 145198948Sobrien } 145298948Sobrien 145398948Sobrien if (ldns_rr_list_rr_count(rrsigs) < 1) { 145498948Sobrien return LDNS_STATUS_CRYPTO_NO_RRSIG; 145598948Sobrien } 145698948Sobrien 145798948Sobrien /* Look at each sig */ 145898948Sobrien for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) { 145998948Sobrien 146098948Sobrien cur_sig = ldns_rr_list_rr(rrsigs, sig_i); 146198948Sobrien /* Get a valid signer key and validate the sig */ 146298948Sobrien if ((trusted_keys = ldns_fetch_valid_domain_keys_time( 146398948Sobrien res, 146498948Sobrien ldns_rr_rrsig_signame(cur_sig), 146598948Sobrien ldns_resolver_dnssec_anchors(res), 146698948Sobrien check_time, 146798948Sobrien &result))) { 146898948Sobrien 146998948Sobrien for (key_i = 0; 147098948Sobrien key_i < ldns_rr_list_rr_count(trusted_keys); 147198948Sobrien key_i++) { 147298948Sobrien cur_key = ldns_rr_list_rr(trusted_keys, key_i); 147398948Sobrien 147498948Sobrien if ((result = ldns_verify_rrsig_time(rrset, 147598948Sobrien cur_sig, 147698948Sobrien cur_key, 147798948Sobrien check_time)) 147898948Sobrien == LDNS_STATUS_OK) { 147998948Sobrien if (validating_keys) { 148098948Sobrien ldns_rr_list_push_rr(validating_keys, 148198948Sobrien ldns_rr_clone(cur_key)); 148298948Sobrien } 148398948Sobrien ldns_rr_list_deep_free(trusted_keys); 148498948Sobrien return LDNS_STATUS_OK; 148598948Sobrien } 148698948Sobrien } 148798948Sobrien } 148898948Sobrien } 148998948Sobrien 149098948Sobrien ldns_rr_list_deep_free(trusted_keys); 149198948Sobrien return result; 149298948Sobrien} 149398948Sobrien 149498948Sobrienldns_status 149598948Sobrienldns_verify_trusted( 149698948Sobrien ldns_resolver *res, 1497130809Smarcel ldns_rr_list *rrset, 149898948Sobrien ldns_rr_list * rrsigs, 149998948Sobrien ldns_rr_list * validating_keys) 150098948Sobrien{ 150198948Sobrien return ldns_verify_trusted_time( 150298948Sobrien res, rrset, rrsigs, ldns_time(NULL), validating_keys); 150398948Sobrien} 150498948Sobrien 150598948Sobrien 150698948Sobrienldns_status 150798948Sobrienldns_dnssec_verify_denial(ldns_rr *rr, 150898948Sobrien ldns_rr_list *nsecs, 150998948Sobrien ldns_rr_list *rrsigs) 151098948Sobrien{ 151198948Sobrien ldns_rdf *rr_name; 151298948Sobrien ldns_rdf *wildcard_name; 151398948Sobrien ldns_rdf *chopped_dname; 151498948Sobrien ldns_rr *cur_nsec; 151598948Sobrien size_t i; 151698948Sobrien ldns_status result; 151798948Sobrien /* needed for wildcard check on exact match */ 151898948Sobrien ldns_rr *rrsig; 151998948Sobrien bool name_covered = false; 152098948Sobrien bool type_covered = false; 152198948Sobrien bool wildcard_covered = false; 152298948Sobrien bool wildcard_type_covered = false; 152398948Sobrien 152498948Sobrien wildcard_name = ldns_dname_new_frm_str("*"); 152598948Sobrien rr_name = ldns_rr_owner(rr); 152698948Sobrien chopped_dname = ldns_dname_left_chop(rr_name); 152798948Sobrien result = ldns_dname_cat(wildcard_name, chopped_dname); 152898948Sobrien ldns_rdf_deep_free(chopped_dname); 152998948Sobrien if (result != LDNS_STATUS_OK) { 153098948Sobrien return result; 153198948Sobrien } 153298948Sobrien 153398948Sobrien for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 153498948Sobrien cur_nsec = ldns_rr_list_rr(nsecs, i); 153598948Sobrien if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { 153698948Sobrien /* see section 5.4 of RFC4035, if the label count of the NSEC's 153798948Sobrien RRSIG is equal, then it is proven that wildcard expansion 153898948Sobrien could not have been used to match the request */ 153998948Sobrien rrsig = ldns_dnssec_get_rrsig_for_name_and_type( 154098948Sobrien ldns_rr_owner(cur_nsec), 154198948Sobrien ldns_rr_get_type(cur_nsec), 154298948Sobrien rrsigs); 154398948Sobrien if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig)) 154498948Sobrien == ldns_dname_label_count(rr_name)) { 154598948Sobrien wildcard_covered = true; 154698948Sobrien } 154798948Sobrien 154898948Sobrien if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), 154998948Sobrien ldns_rr_get_type(rr))) { 155098948Sobrien type_covered = true; 155198948Sobrien } 155298948Sobrien } 155398948Sobrien if (ldns_nsec_covers_name(cur_nsec, rr_name)) { 155498948Sobrien name_covered = true; 155598948Sobrien } 155698948Sobrien 155798948Sobrien if (ldns_dname_compare(wildcard_name, 155898948Sobrien ldns_rr_owner(cur_nsec)) == 0) { 155998948Sobrien if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), 156098948Sobrien ldns_rr_get_type(rr))) { 1561130809Smarcel wildcard_type_covered = true; 1562130809Smarcel } 1563130809Smarcel } 156498948Sobrien 156598948Sobrien if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { 156698948Sobrien wildcard_covered = true; 156798948Sobrien } 156898948Sobrien 156998948Sobrien } 157098948Sobrien 157198948Sobrien ldns_rdf_deep_free(wildcard_name); 157298948Sobrien 157398948Sobrien if (type_covered || !name_covered) { 157498948Sobrien return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 157598948Sobrien } 157698948Sobrien 157798948Sobrien if (wildcard_type_covered || !wildcard_covered) { 157898948Sobrien return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; 157998948Sobrien } 158098948Sobrien 158198948Sobrien return LDNS_STATUS_OK; 158298948Sobrien} 158398948Sobrien 158498948Sobrienldns_status 158598948Sobrienldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr 158698948Sobrien , ldns_rr_list *nsecs 158798948Sobrien , ATTR_UNUSED(ldns_rr_list *rrsigs) 158898948Sobrien , ldns_pkt_rcode packet_rcode 158998948Sobrien , ldns_rr_type packet_qtype 159098948Sobrien , bool packet_nodata 159198948Sobrien , ldns_rr **match 159298948Sobrien ) 159398948Sobrien{ 159498948Sobrien ldns_rdf *closest_encloser; 159598948Sobrien ldns_rdf *wildcard; 159698948Sobrien ldns_rdf *hashed_wildcard_name; 159798948Sobrien bool wildcard_covered = false; 159898948Sobrien ldns_rdf *zone_name; 159998948Sobrien ldns_rdf *hashed_name; 1600130809Smarcel /* self assignment to suppress uninitialized warning */ 160198948Sobrien ldns_rdf *next_closer = next_closer; 160298948Sobrien ldns_rdf *hashed_next_closer; 1603130809Smarcel size_t i; 160498948Sobrien ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 1605130809Smarcel 160698948Sobrien if (match) { 160798948Sobrien *match = NULL; 160898948Sobrien } 160998948Sobrien 161098948Sobrien zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); 161198948Sobrien 161298948Sobrien /* section 8.4 */ 161398948Sobrien if (packet_rcode == LDNS_RCODE_NXDOMAIN) { 161498948Sobrien closest_encloser = ldns_dnssec_nsec3_closest_encloser( 161598948Sobrien ldns_rr_owner(rr), 161698948Sobrien ldns_rr_get_type(rr), 161798948Sobrien nsecs); 161898948Sobrien if(!closest_encloser) { 161998948Sobrien result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 162098948Sobrien goto done; 162198948Sobrien } 162298948Sobrien 162398948Sobrien wildcard = ldns_dname_new_frm_str("*"); 1624130809Smarcel (void) ldns_dname_cat(wildcard, closest_encloser); 162598948Sobrien 162698948Sobrien for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 162798948Sobrien hashed_wildcard_name = 162898948Sobrien ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), 162998948Sobrien wildcard 163098948Sobrien ); 163198948Sobrien (void) ldns_dname_cat(hashed_wildcard_name, zone_name); 163298948Sobrien 163398948Sobrien if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), 163498948Sobrien hashed_wildcard_name)) { 163598948Sobrien wildcard_covered = true; 163698948Sobrien if (match) { 163798948Sobrien *match = ldns_rr_list_rr(nsecs, i); 163898948Sobrien } 163998948Sobrien } 164098948Sobrien ldns_rdf_deep_free(hashed_wildcard_name); 164198948Sobrien } 164298948Sobrien 164398948Sobrien if (! wildcard_covered) { 164498948Sobrien result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; 164598948Sobrien } else { 164698948Sobrien result = LDNS_STATUS_OK; 164798948Sobrien } 164898948Sobrien ldns_rdf_deep_free(closest_encloser); 164998948Sobrien ldns_rdf_deep_free(wildcard); 165098948Sobrien 165198948Sobrien } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { 165298948Sobrien /* section 8.5 */ 165398948Sobrien hashed_name = ldns_nsec3_hash_name_frm_nsec3( 165498948Sobrien ldns_rr_list_rr(nsecs, 0), 165598948Sobrien ldns_rr_owner(rr)); 165698948Sobrien (void) ldns_dname_cat(hashed_name, zone_name); 165798948Sobrien for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 1658130809Smarcel if (ldns_dname_compare(hashed_name, 1659130809Smarcel ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) 166098948Sobrien == 0) { 166198948Sobrien if (!ldns_nsec_bitmap_covers_type( 166298948Sobrien ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 166398948Sobrien packet_qtype) 166498948Sobrien && 166598948Sobrien !ldns_nsec_bitmap_covers_type( 166698948Sobrien ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 166798948Sobrien LDNS_RR_TYPE_CNAME)) { 166898948Sobrien result = LDNS_STATUS_OK; 166998948Sobrien if (match) { 167098948Sobrien *match = ldns_rr_list_rr(nsecs, i); 167198948Sobrien } 167298948Sobrien goto done; 167398948Sobrien } 167498948Sobrien } 167598948Sobrien } 167698948Sobrien result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 167798948Sobrien /* wildcard no data? section 8.7 */ 167898948Sobrien closest_encloser = ldns_dnssec_nsec3_closest_encloser( 1679130809Smarcel ldns_rr_owner(rr), 168098948Sobrien ldns_rr_get_type(rr), 168198948Sobrien nsecs); 168298948Sobrien if(!closest_encloser) { 168398948Sobrien result = LDNS_STATUS_NSEC3_ERR; 1684130809Smarcel goto done; 168598948Sobrien } 168698948Sobrien wildcard = ldns_dname_new_frm_str("*"); 168798948Sobrien (void) ldns_dname_cat(wildcard, closest_encloser); 168898948Sobrien for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 168998948Sobrien hashed_wildcard_name = 1690130809Smarcel ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), 169198948Sobrien wildcard); 169298948Sobrien (void) ldns_dname_cat(hashed_wildcard_name, zone_name); 169398948Sobrien 1694130809Smarcel if (ldns_dname_compare(hashed_wildcard_name, 169598948Sobrien ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) 169698948Sobrien == 0) { 169798948Sobrien if (!ldns_nsec_bitmap_covers_type( 169898948Sobrien ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 169998948Sobrien packet_qtype) 170098948Sobrien && 170198948Sobrien !ldns_nsec_bitmap_covers_type( 170298948Sobrien ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 170398948Sobrien LDNS_RR_TYPE_CNAME)) { 170498948Sobrien result = LDNS_STATUS_OK; 170598948Sobrien if (match) { 170698948Sobrien *match = ldns_rr_list_rr(nsecs, i); 170798948Sobrien } 170898948Sobrien } 170998948Sobrien } 171098948Sobrien ldns_rdf_deep_free(hashed_wildcard_name); 171198948Sobrien if (result == LDNS_STATUS_OK) { 1712130809Smarcel break; 171398948Sobrien } 171498948Sobrien } 171598948Sobrien ldns_rdf_deep_free(closest_encloser); 171698948Sobrien ldns_rdf_deep_free(wildcard); 171798948Sobrien } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) { 171898948Sobrien /* section 8.6 */ 171998948Sobrien /* note: up to XXX this is the same as for 8.5 */ 1720130809Smarcel hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 172198948Sobrien 0), 172298948Sobrien ldns_rr_owner(rr) 172398948Sobrien ); 172498948Sobrien (void) ldns_dname_cat(hashed_name, zone_name); 172598948Sobrien for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 172698948Sobrien if (ldns_dname_compare(hashed_name, 172798948Sobrien ldns_rr_owner(ldns_rr_list_rr(nsecs, 172898948Sobrien i))) 172998948Sobrien == 0) { 173098948Sobrien if (!ldns_nsec_bitmap_covers_type( 173198948Sobrien ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 1732130809Smarcel LDNS_RR_TYPE_DS) 173398948Sobrien && 173498948Sobrien !ldns_nsec_bitmap_covers_type( 173598948Sobrien ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 173698948Sobrien LDNS_RR_TYPE_CNAME)) { 173798948Sobrien result = LDNS_STATUS_OK; 173898948Sobrien if (match) { 173998948Sobrien *match = ldns_rr_list_rr(nsecs, i); 174098948Sobrien } 174198948Sobrien goto done; 174298948Sobrien } 174398948Sobrien } 174498948Sobrien } 174598948Sobrien 174698948Sobrien /* XXX see note above */ 174798948Sobrien result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 174898948Sobrien 174998948Sobrien closest_encloser = ldns_dnssec_nsec3_closest_encloser( 175098948Sobrien ldns_rr_owner(rr), 175198948Sobrien ldns_rr_get_type(rr), 175298948Sobrien nsecs); 175398948Sobrien if(!closest_encloser) { 175498948Sobrien result = LDNS_STATUS_NSEC3_ERR; 175598948Sobrien goto done; 175698948Sobrien } 175798948Sobrien /* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/ 175898948Sobrien 175998948Sobrien if (ldns_dname_label_count(closest_encloser) + 1 176098948Sobrien >= ldns_dname_label_count(ldns_rr_owner(rr))) { 176198948Sobrien 176298948Sobrien /* Query name *is* the "next closer". */ 176398948Sobrien hashed_next_closer = hashed_name; 176498948Sobrien } else { 176598948Sobrien 176698948Sobrien /* "next closer" has less labels than the query name. 176798948Sobrien * Create the name and hash it. 176898948Sobrien */ 176998948Sobrien next_closer = ldns_dname_clone_from( 177098948Sobrien ldns_rr_owner(rr), 177198948Sobrien ldns_dname_label_count(ldns_rr_owner(rr)) 177298948Sobrien - (ldns_dname_label_count(closest_encloser) + 1) 177398948Sobrien ); 177498948Sobrien hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3( 177598948Sobrien ldns_rr_list_rr(nsecs, 0), 177698948Sobrien next_closer 177798948Sobrien ); 177898948Sobrien (void) ldns_dname_cat(hashed_next_closer, zone_name); 177998948Sobrien } 178098948Sobrien /* Find the NSEC3 that covers the "next closer" */ 178198948Sobrien for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 178298948Sobrien if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), 178398948Sobrien hashed_next_closer) && 178498948Sobrien ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) { 178598948Sobrien 178698948Sobrien result = LDNS_STATUS_OK; 178798948Sobrien if (match) { 178898948Sobrien *match = ldns_rr_list_rr(nsecs, i); 178998948Sobrien } 179098948Sobrien break; 179198948Sobrien } 179298948Sobrien } 179398948Sobrien if (ldns_dname_label_count(closest_encloser) + 1 1794130809Smarcel < ldns_dname_label_count(ldns_rr_owner(rr))) { 179598948Sobrien 179698948Sobrien /* "next closer" has less labels than the query name. 179798948Sobrien * Dispose of the temporary variables that held that name. 179898948Sobrien */ 179998948Sobrien ldns_rdf_deep_free(hashed_next_closer); 180098948Sobrien ldns_rdf_deep_free(next_closer); 180198948Sobrien } 180298948Sobrien ldns_rdf_deep_free(closest_encloser); 180398948Sobrien } 180498948Sobrien 180598948Sobrien done: 180698948Sobrien ldns_rdf_deep_free(zone_name); 180798948Sobrien return result; 180898948Sobrien} 180998948Sobrien 181098948Sobrienldns_status 1811130809Smarcelldns_dnssec_verify_denial_nsec3(ldns_rr *rr, 181298948Sobrien ldns_rr_list *nsecs, 181398948Sobrien ldns_rr_list *rrsigs, 181498948Sobrien ldns_pkt_rcode packet_rcode, 181598948Sobrien ldns_rr_type packet_qtype, 181698948Sobrien bool packet_nodata) 181798948Sobrien{ 181898948Sobrien return ldns_dnssec_verify_denial_nsec3_match( 181998948Sobrien rr, nsecs, rrsigs, packet_rcode, 182098948Sobrien packet_qtype, packet_nodata, NULL 182198948Sobrien ); 182298948Sobrien} 1823130809Smarcel 182498948Sobrien#ifdef USE_GOST 182598948SobrienEVP_PKEY* 182698948Sobrienldns_gost2pkey_raw(unsigned char* key, size_t keylen) 182798948Sobrien{ 182898948Sobrien /* prefix header for X509 encoding */ 182998948Sobrien uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 183098948Sobrien 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 183198948Sobrien 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 183298948Sobrien 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; 183398948Sobrien unsigned char encoded[37+64]; 183498948Sobrien const unsigned char* pp; 183598948Sobrien if(keylen != 64) { 183698948Sobrien /* key wrong size */ 183798948Sobrien return NULL; 183898948Sobrien } 183998948Sobrien 184098948Sobrien /* create evp_key */ 184198948Sobrien memmove(encoded, asn, 37); 184298948Sobrien memmove(encoded+37, key, 64); 184398948Sobrien pp = (unsigned char*)&encoded[0]; 184498948Sobrien 184598948Sobrien return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 184698948Sobrien} 1847130809Smarcel 184898948Sobrienstatic ldns_status 184998948Sobrienldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, 185098948Sobrien ldns_buffer* rrset, unsigned char* key, size_t keylen) 185198948Sobrien{ 185298948Sobrien EVP_PKEY *evp_key; 185398948Sobrien ldns_status result; 185498948Sobrien 185598948Sobrien (void) ldns_key_EVP_load_gost_id(); 185698948Sobrien evp_key = ldns_gost2pkey_raw(key, keylen); 185798948Sobrien if(!evp_key) { 185898948Sobrien /* could not convert key */ 185998948Sobrien return LDNS_STATUS_CRYPTO_BOGUS; 186098948Sobrien } 186198948Sobrien 186298948Sobrien /* verify signature */ 1863130809Smarcel result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, 186498948Sobrien evp_key, EVP_get_digestbyname("md_gost94")); 186598948Sobrien EVP_PKEY_free(evp_key); 186698948Sobrien 186798948Sobrien return result; 1868130809Smarcel} 186998948Sobrien#endif 187098948Sobrien 187198948Sobrien#ifdef USE_ECDSA 1872130809SmarcelEVP_PKEY* 187398948Sobrienldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 187498948Sobrien{ 187598948Sobrien unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 187698948Sobrien const unsigned char* pp = buf; 187798948Sobrien EVP_PKEY *evp_key; 187898948Sobrien EC_KEY *ec; 187998948Sobrien /* check length, which uncompressed must be 2 bignums */ 188098948Sobrien if(algo == LDNS_ECDSAP256SHA256) { 188198948Sobrien if(keylen != 2*256/8) return NULL; 188298948Sobrien ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 188398948Sobrien } else if(algo == LDNS_ECDSAP384SHA384) { 188498948Sobrien if(keylen != 2*384/8) return NULL; 188598948Sobrien ec = EC_KEY_new_by_curve_name(NID_secp384r1); 188698948Sobrien } else ec = NULL; 188798948Sobrien if(!ec) return NULL; 1888130809Smarcel if(keylen+1 > sizeof(buf)) 188998948Sobrien return NULL; /* sanity check */ 189098948Sobrien /* prepend the 0x02 (from docs) (or actually 0x04 from implementation 189198948Sobrien * of openssl) for uncompressed data */ 189298948Sobrien buf[0] = POINT_CONVERSION_UNCOMPRESSED; 189398948Sobrien memmove(buf+1, key, keylen); 189498948Sobrien if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { 189598948Sobrien EC_KEY_free(ec); 189698948Sobrien return NULL; 189798948Sobrien } 189898948Sobrien evp_key = EVP_PKEY_new(); 189998948Sobrien if(!evp_key) { 190098948Sobrien EC_KEY_free(ec); 190198948Sobrien return NULL; 190298948Sobrien } 190398948Sobrien if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 190498948Sobrien EVP_PKEY_free(evp_key); 190598948Sobrien EC_KEY_free(ec); 190698948Sobrien return NULL; 190798948Sobrien } 190898948Sobrien return evp_key; 190998948Sobrien} 191098948Sobrien 191198948Sobrienstatic ldns_status 1912130809Smarcelldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, 191398948Sobrien ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo) 191498948Sobrien{ 191598948Sobrien EVP_PKEY *evp_key; 191698948Sobrien ldns_status result; 191798948Sobrien const EVP_MD *d; 191898948Sobrien 191998948Sobrien evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo); 192098948Sobrien if(!evp_key) { 192198948Sobrien /* could not convert key */ 192298948Sobrien return LDNS_STATUS_CRYPTO_BOGUS; 192398948Sobrien } 192498948Sobrien if(algo == LDNS_ECDSAP256SHA256) 192598948Sobrien d = EVP_sha256(); 192698948Sobrien else d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */ 192798948Sobrien result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d); 1928130809Smarcel EVP_PKEY_free(evp_key); 192998948Sobrien return result; 193098948Sobrien} 193198948Sobrien#endif 193298948Sobrien 1933130809Smarcelldns_status 193498948Sobrienldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 193598948Sobrien ldns_buffer *key_buf, uint8_t algo) 193698948Sobrien{ 1937130809Smarcel return ldns_verify_rrsig_buffers_raw( 193898948Sobrien (unsigned char*)ldns_buffer_begin(rawsig_buf), 193998948Sobrien ldns_buffer_position(rawsig_buf), 194098948Sobrien verify_buf, 194198948Sobrien (unsigned char*)ldns_buffer_begin(key_buf), 194298948Sobrien ldns_buffer_position(key_buf), algo); 194398948Sobrien} 194498948Sobrien 194598948Sobrienldns_status 194698948Sobrienldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen, 194798948Sobrien ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 194898948Sobrien uint8_t algo) 194998948Sobrien{ 195098948Sobrien /* check for right key */ 195198948Sobrien switch(algo) { 195298948Sobrien case LDNS_DSA: 195398948Sobrien case LDNS_DSA_NSEC3: 195498948Sobrien return ldns_verify_rrsig_dsa_raw(sig, 195598948Sobrien siglen, 195698948Sobrien verify_buf, 195798948Sobrien key, 195898948Sobrien keylen); 195998948Sobrien break; 196098948Sobrien case LDNS_RSASHA1: 196198948Sobrien case LDNS_RSASHA1_NSEC3: 196298948Sobrien return ldns_verify_rrsig_rsasha1_raw(sig, 196398948Sobrien siglen, 196498948Sobrien verify_buf, 196598948Sobrien key, 196698948Sobrien keylen); 196798948Sobrien break; 196898948Sobrien#ifdef USE_SHA2 196998948Sobrien case LDNS_RSASHA256: 197098948Sobrien return ldns_verify_rrsig_rsasha256_raw(sig, 197198948Sobrien siglen, 197298948Sobrien verify_buf, 197398948Sobrien key, 197498948Sobrien keylen); 197598948Sobrien break; 197698948Sobrien case LDNS_RSASHA512: 197798948Sobrien return ldns_verify_rrsig_rsasha512_raw(sig, 197898948Sobrien siglen, 197998948Sobrien verify_buf, 1980130809Smarcel key, 1981130809Smarcel keylen); 198298948Sobrien break; 198398948Sobrien#endif 198498948Sobrien#ifdef USE_GOST 198598948Sobrien case LDNS_ECC_GOST: 198698948Sobrien return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf, 198798948Sobrien key, keylen); 198898948Sobrien break; 198998948Sobrien#endif 199098948Sobrien#ifdef USE_ECDSA 199198948Sobrien case LDNS_ECDSAP256SHA256: 199298948Sobrien case LDNS_ECDSAP384SHA384: 199398948Sobrien return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf, 199498948Sobrien key, keylen, algo); 199598948Sobrien break; 199698948Sobrien#endif 199798948Sobrien case LDNS_RSAMD5: 199898948Sobrien return ldns_verify_rrsig_rsamd5_raw(sig, 199998948Sobrien siglen, 200098948Sobrien verify_buf, 200198948Sobrien key, 200298948Sobrien keylen); 200398948Sobrien break; 200498948Sobrien default: 200598948Sobrien /* do you know this alg?! */ 200698948Sobrien return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 200798948Sobrien } 200898948Sobrien} 200998948Sobrien 201098948Sobrien 201198948Sobrien/** 201298948Sobrien * Reset the ttl in the rrset with the orig_ttl from the sig 201398948Sobrien * and update owner name if it was wildcard 201498948Sobrien * Also canonicalizes the rrset. 201598948Sobrien * @param rrset: rrset to modify 201698948Sobrien * @param sig: signature to take TTL and wildcard values from 201798948Sobrien */ 201898948Sobrienstatic void 201998948Sobrienldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig) 202098948Sobrien{ 202198948Sobrien uint32_t orig_ttl; 202298948Sobrien uint16_t i; 202398948Sobrien uint8_t label_count; 202498948Sobrien ldns_rdf *wildcard_name; 202598948Sobrien ldns_rdf *wildcard_chopped; 202698948Sobrien ldns_rdf *wildcard_chopped_tmp; 2027130809Smarcel 202898948Sobrien if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) { 202998948Sobrien return; 203098948Sobrien } 203198948Sobrien 203298948Sobrien orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3)); 203398948Sobrien label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2)); 203498948Sobrien 203598948Sobrien for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { 203698948Sobrien if (label_count < 203798948Sobrien ldns_dname_label_count( 203898948Sobrien ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { 203998948Sobrien (void) ldns_str2rdf_dname(&wildcard_name, "*"); 204098948Sobrien wildcard_chopped = ldns_rdf_clone(ldns_rr_owner( 204198948Sobrien ldns_rr_list_rr(rrset_clone, i))); 204298948Sobrien while (label_count < ldns_dname_label_count(wildcard_chopped)) { 2043130809Smarcel wildcard_chopped_tmp = ldns_dname_left_chop( 204498948Sobrien wildcard_chopped); 204598948Sobrien ldns_rdf_deep_free(wildcard_chopped); 204698948Sobrien wildcard_chopped = wildcard_chopped_tmp; 204798948Sobrien } 204898948Sobrien (void) ldns_dname_cat(wildcard_name, wildcard_chopped); 204998948Sobrien ldns_rdf_deep_free(wildcard_chopped); 205098948Sobrien ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr( 205198948Sobrien rrset_clone, i))); 205298948Sobrien ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 205398948Sobrien wildcard_name); 205498948Sobrien } 205598948Sobrien ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl); 205698948Sobrien /* convert to lowercase */ 205798948Sobrien ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); 205898948Sobrien } 205998948Sobrien} 206098948Sobrien 206198948Sobrien/** 206298948Sobrien * Make raw signature buffer out of rrsig 206398948Sobrien * @param rawsig_buf: raw signature buffer for result 206498948Sobrien * @param rrsig: signature to convert 206598948Sobrien * @return OK or more specific error. 206698948Sobrien */ 206798948Sobrienstatic ldns_status 206898948Sobrienldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig) 206998948Sobrien{ 207098948Sobrien uint8_t sig_algo; 207198948Sobrien 207298948Sobrien if (rrsig == NULL) { 207398948Sobrien return LDNS_STATUS_CRYPTO_NO_RRSIG; 207498948Sobrien } 207598948Sobrien if (ldns_rr_rdf(rrsig, 1) == NULL) { 207698948Sobrien return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 207798948Sobrien } 207898948Sobrien sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); 207998948Sobrien /* check for known and implemented algo's now (otherwise 208098948Sobrien * the function could return a wrong error 208198948Sobrien */ 208298948Sobrien /* create a buffer with signature rdata */ 208398948Sobrien /* for some algorithms we need other data than for others... */ 208498948Sobrien /* (the DSA API wants DER encoding for instance) */ 208598948Sobrien 208698948Sobrien switch(sig_algo) { 208798948Sobrien case LDNS_RSAMD5: 2088130809Smarcel case LDNS_RSASHA1: 208998948Sobrien case LDNS_RSASHA1_NSEC3: 209098948Sobrien#ifdef USE_SHA2 209198948Sobrien case LDNS_RSASHA256: 209298948Sobrien case LDNS_RSASHA512: 209398948Sobrien#endif 209498948Sobrien#ifdef USE_GOST 209598948Sobrien case LDNS_ECC_GOST: 2096130809Smarcel#endif 209798948Sobrien if (ldns_rr_rdf(rrsig, 8) == NULL) { 209898948Sobrien return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 209919370Spst } 210019370Spst if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) 210119370Spst != LDNS_STATUS_OK) { 210298948Sobrien return LDNS_STATUS_MEM_ERR; 210398948Sobrien } 210419370Spst break; 210598948Sobrien case LDNS_DSA: 210698948Sobrien case LDNS_DSA_NSEC3: 210719370Spst /* EVP takes rfc2459 format, which is a tad longer than dns format */ 2108130809Smarcel if (ldns_rr_rdf(rrsig, 8) == NULL) { 2109130809Smarcel return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 211019370Spst } 211119370Spst if (ldns_convert_dsa_rrsig_rdf2asn1( 211219370Spst rawsig_buf, ldns_rr_rdf(rrsig, 8)) 211319370Spst != LDNS_STATUS_OK) { 211446283Sdfr /* 211546283Sdfr if (ldns_rdf2buffer_wire(rawsig_buf, 211698948Sobrien ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { 211798948Sobrien */ 211846283Sdfr return LDNS_STATUS_MEM_ERR; 211946283Sdfr } 212046283Sdfr break; 212119370Spst#ifdef USE_ECDSA 212219370Spst case LDNS_ECDSAP256SHA256: 2123130809Smarcel case LDNS_ECDSAP384SHA384: 212446283Sdfr /* EVP produces an ASN prefix on the signature, which is 212519370Spst * not used in the DNS */ 212619370Spst if (ldns_rr_rdf(rrsig, 8) == NULL) { 212719370Spst return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 212819370Spst } 212919370Spst if (ldns_convert_ecdsa_rrsig_rdf2asn1( 213019370Spst rawsig_buf, ldns_rr_rdf(rrsig, 8)) 213119370Spst != LDNS_STATUS_OK) { 213219370Spst return LDNS_STATUS_MEM_ERR; 213319370Spst } 213419370Spst break; 213519370Spst#endif 213619370Spst case LDNS_DH: 213719370Spst case LDNS_ECC: 213898948Sobrien case LDNS_INDIRECT: 213998948Sobrien return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; 214098948Sobrien default: 214198948Sobrien return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 214219370Spst } 214319370Spst return LDNS_STATUS_OK; 214498948Sobrien} 214598948Sobrien 214619370Spst/** 214719370Spst * Check RRSIG timestamps against the given 'now' time. 2148130809Smarcel * @param rrsig: signature to check. 214998948Sobrien * @param now: the current time in seconds epoch. 215019370Spst * @return status code LDNS_STATUS_OK if all is fine. 215198948Sobrien */ 215298948Sobrienstatic ldns_status 215398948Sobrienldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now) 215498948Sobrien{ 215519370Spst int32_t inception, expiration; 215619370Spst 215719370Spst /* check the signature time stamps */ 215819370Spst inception = (int32_t)ldns_rdf2native_time_t( 215919370Spst ldns_rr_rrsig_inception(rrsig)); 216019370Spst expiration = (int32_t)ldns_rdf2native_time_t( 216119370Spst ldns_rr_rrsig_expiration(rrsig)); 216219370Spst 216319370Spst if (expiration - inception < 0) { 216419370Spst /* bad sig, expiration before inception?? Tsssg */ 216519370Spst return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION; 216619370Spst } 216719370Spst if (((int32_t) now) - inception < 0) { 216819370Spst /* bad sig, inception date has not yet come to pass */ 216919370Spst return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED; 217019370Spst } 217119370Spst if (expiration - ((int32_t) now) < 0) { 217219370Spst /* bad sig, expiration date has passed */ 217319370Spst return LDNS_STATUS_CRYPTO_SIG_EXPIRED; 217498948Sobrien } 217598948Sobrien return LDNS_STATUS_OK; 217698948Sobrien} 217798948Sobrien 217819370Spst/** 217919370Spst * Prepare for verification. 218098948Sobrien * @param rawsig_buf: raw signature buffer made ready. 218119370Spst * @param verify_buf: data for verification buffer made ready. 218219370Spst * @param rrset_clone: made ready. 218398948Sobrien * @param rrsig: signature to prepare for. 2184130809Smarcel * @return LDNS_STATUS_OK is all went well. Otherwise specific error. 218519370Spst */ 218619370Spststatic ldns_status 218719370Spstldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 218819370Spst ldns_rr_list* rrset_clone, ldns_rr* rrsig) 218919370Spst{ 219098948Sobrien ldns_status result; 219119370Spst 219246283Sdfr /* canonicalize the sig */ 219346283Sdfr ldns_dname2canonical(ldns_rr_owner(rrsig)); 219419370Spst 219519370Spst /* check if the typecovered is equal to the type checked */ 219698948Sobrien if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) != 219719370Spst ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) 219819370Spst return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR; 219919370Spst 220019370Spst /* create a buffer with b64 signature rdata */ 220119370Spst result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig); 2202130809Smarcel if(result != LDNS_STATUS_OK) 220346283Sdfr return result; 220446283Sdfr 220546283Sdfr /* use TTL from signature. Use wildcard names for wildcards */ 220646283Sdfr /* also canonicalizes rrset_clone */ 220719370Spst ldns_rrset_use_signature_ttl(rrset_clone, rrsig); 220846283Sdfr 220946283Sdfr /* sort the rrset in canonical order */ 221046283Sdfr ldns_rr_list_sort(rrset_clone); 221146283Sdfr 221246283Sdfr /* put the signature rr (without the b64) to the verify_buf */ 221346283Sdfr if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK) 221446283Sdfr return LDNS_STATUS_MEM_ERR; 221598948Sobrien 221646283Sdfr /* add the rrset in verify_buf */ 221746283Sdfr if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) 221846283Sdfr != LDNS_STATUS_OK) 221946283Sdfr return LDNS_STATUS_MEM_ERR; 222046283Sdfr 222146283Sdfr return LDNS_STATUS_OK; 222246283Sdfr} 222346283Sdfr 222446283Sdfr/** 222546283Sdfr * Check if a key matches a signature. 222619370Spst * Checks keytag, sigalgo and signature. 222746283Sdfr * @param rawsig_buf: raw signature buffer for verify 2228130809Smarcel * @param verify_buf: raw data buffer for verify 222919370Spst * @param rrsig: the rrsig 223046283Sdfr * @param key: key to attempt. 223146283Sdfr * @return LDNS_STATUS_OK if OK, else some specific error. 223219370Spst */ 223319370Spststatic ldns_status 223446283Sdfrldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 2235130809Smarcel ldns_rr* rrsig, ldns_rr* key) 223646283Sdfr{ 223746283Sdfr uint8_t sig_algo; 223846283Sdfr 223919370Spst if (rrsig == NULL) { 224046283Sdfr return LDNS_STATUS_CRYPTO_NO_RRSIG; 224198948Sobrien } 224298948Sobrien if (ldns_rr_rdf(rrsig, 1) == NULL) { 224398948Sobrien return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 224498948Sobrien } 224519370Spst sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); 224646283Sdfr 224798948Sobrien /* before anything, check if the keytags match */ 2248130809Smarcel if (ldns_calc_keytag(key) 224998948Sobrien == 2250130809Smarcel ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) 225198948Sobrien ) { 2252130809Smarcel ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 2253130809Smarcel ldns_status result = LDNS_STATUS_ERR; 225498948Sobrien 225598948Sobrien /* put the key-data in a buffer, that's the third rdf, with 225619370Spst * the base64 encoded key data */ 225719370Spst if (ldns_rr_rdf(key, 3) == NULL) { 225819370Spst ldns_buffer_free(key_buf); 225919370Spst return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; 226019370Spst } 226119370Spst if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3)) 226219370Spst != LDNS_STATUS_OK) { 226319370Spst ldns_buffer_free(key_buf); 226419370Spst /* returning is bad might screw up 226519370Spst good keys later in the list 226619370Spst what to do? */ 226719370Spst return LDNS_STATUS_ERR; 226819370Spst } 226919370Spst 2270130809Smarcel if (ldns_rr_rdf(key, 2) == NULL) { 227198948Sobrien result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; 227219370Spst } 227398948Sobrien else if (sig_algo == ldns_rdf2native_int8( 227419370Spst ldns_rr_rdf(key, 2))) { 227519370Spst result = ldns_verify_rrsig_buffers(rawsig_buf, 227619370Spst verify_buf, key_buf, sig_algo); 227719370Spst } else { 227819370Spst /* No keys with the corresponding algorithm are found */ 227919370Spst result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 228019370Spst } 228198948Sobrien 228219370Spst ldns_buffer_free(key_buf); 228398948Sobrien return result; 228419370Spst } 228519370Spst else { 2286130809Smarcel /* No keys with the corresponding keytag are found */ 228798948Sobrien return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 228898948Sobrien } 228998948Sobrien} 2290130809Smarcel 2291130809Smarcel/* 229219370Spst * to verify: 229319370Spst * - create the wire fmt of the b64 key rdata 229498948Sobrien * - create the wire fmt of the sorted rrset 229519370Spst * - create the wire fmt of the b64 sig rdata 2296130809Smarcel * - create the wire fmt of the sig without the b64 rdata 229719370Spst * - cat the sig data (without b64 rdata) to the rrset 229819370Spst * - verify the rrset+sig, with the b64 data and the b64 key data 229919370Spst */ 230019370Spstldns_status 230119370Spstldns_verify_rrsig_keylist_time( 230219370Spst ldns_rr_list *rrset, 230398948Sobrien ldns_rr *rrsig, 230498948Sobrien const ldns_rr_list *keys, 230519370Spst time_t check_time, 230619370Spst ldns_rr_list *good_keys) 230719370Spst{ 230819370Spst ldns_status result; 230919370Spst ldns_rr_list *valid = ldns_rr_list_new(); 231019370Spst if (!valid) 231119370Spst return LDNS_STATUS_MEM_ERR; 231219370Spst 231319370Spst result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); 231419370Spst if(result != LDNS_STATUS_OK) { 231519370Spst ldns_rr_list_free(valid); 231619370Spst return result; 231719370Spst } 231819370Spst 231919370Spst /* check timestamps last; its OK except time */ 232019370Spst result = ldns_rrsig_check_timestamps(rrsig, check_time); 232146283Sdfr if(result != LDNS_STATUS_OK) { 232246283Sdfr ldns_rr_list_free(valid); 232319370Spst return result; 232419370Spst } 232598948Sobrien 232619370Spst ldns_rr_list_cat(good_keys, valid); 232798948Sobrien ldns_rr_list_free(valid); 232898948Sobrien return LDNS_STATUS_OK; 232998948Sobrien} 233098948Sobrien 233119370Spst/* 233246283Sdfr * to verify: 233319370Spst * - create the wire fmt of the b64 key rdata 233419370Spst * - create the wire fmt of the sorted rrset 233598948Sobrien * - create the wire fmt of the b64 sig rdata 233619370Spst * - create the wire fmt of the sig without the b64 rdata 233719370Spst * - cat the sig data (without b64 rdata) to the rrset 233819370Spst * - verify the rrset+sig, with the b64 data and the b64 key data 233919370Spst */ 234019370Spstldns_status 234198948Sobrienldns_verify_rrsig_keylist(ldns_rr_list *rrset, 234219370Spst ldns_rr *rrsig, 234319370Spst const ldns_rr_list *keys, 234419370Spst ldns_rr_list *good_keys) 234598948Sobrien{ 234619370Spst return ldns_verify_rrsig_keylist_time( 234719370Spst rrset, rrsig, keys, ldns_time(NULL), good_keys); 234819370Spst} 234919370Spst 235019370Spstldns_status 235119370Spstldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, 235298948Sobrien ldns_rr *rrsig, 235319370Spst const ldns_rr_list *keys, 235419370Spst ldns_rr_list *good_keys) 235519370Spst{ 235619370Spst ldns_buffer *rawsig_buf; 235719370Spst ldns_buffer *verify_buf; 235819370Spst uint16_t i; 235919370Spst ldns_status result, status; 236019370Spst ldns_rr_list *rrset_clone; 236119370Spst ldns_rr_list *validkeys; 236219370Spst 236319370Spst if (!rrset) { 236419370Spst return LDNS_STATUS_ERR; 236519370Spst } 236619370Spst 236719370Spst validkeys = ldns_rr_list_new(); 236898948Sobrien if (!validkeys) { 236919370Spst return LDNS_STATUS_MEM_ERR; 237019370Spst } 237119370Spst 237219370Spst /* clone the rrset so that we can fiddle with it */ 237319370Spst rrset_clone = ldns_rr_list_clone(rrset); 237498948Sobrien 237519370Spst /* create the buffers which will certainly hold the raw data */ 237619370Spst rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 237719370Spst verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 237819370Spst 237998948Sobrien result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 238019370Spst rrset_clone, rrsig); 238119370Spst if(result != LDNS_STATUS_OK) { 238219370Spst ldns_buffer_free(verify_buf); 238319370Spst ldns_buffer_free(rawsig_buf); 238419370Spst ldns_rr_list_deep_free(rrset_clone); 238519370Spst ldns_rr_list_free(validkeys); 238619370Spst return result; 238719370Spst } 238819370Spst 238919370Spst result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 239019370Spst for(i = 0; i < ldns_rr_list_rr_count(keys); i++) { 239119370Spst status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 239219370Spst rrsig, ldns_rr_list_rr(keys, i)); 239319370Spst if (status == LDNS_STATUS_OK) { 239419370Spst /* one of the keys has matched, don't break 239519370Spst * here, instead put the 'winning' key in 239619370Spst * the validkey list and return the list 239798948Sobrien * later */ 239819370Spst if (!ldns_rr_list_push_rr(validkeys, 239919370Spst ldns_rr_list_rr(keys,i))) { 2400130809Smarcel /* couldn't push the key?? */ 240119370Spst ldns_buffer_free(rawsig_buf); 240219370Spst ldns_buffer_free(verify_buf); 240319370Spst ldns_rr_list_deep_free(rrset_clone); 240419370Spst ldns_rr_list_free(validkeys); 240519370Spst return LDNS_STATUS_MEM_ERR; 240619370Spst } 240719370Spst 240898948Sobrien result = status; 240919370Spst } 241019370Spst 241119370Spst if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { 241298948Sobrien result = status; 241319370Spst } 241419370Spst } 241598948Sobrien 241619370Spst /* no longer needed */ 241719370Spst ldns_rr_list_deep_free(rrset_clone); 241819370Spst ldns_buffer_free(rawsig_buf); 241919370Spst ldns_buffer_free(verify_buf); 242019370Spst 242119370Spst if (ldns_rr_list_rr_count(validkeys) == 0) { 242219370Spst /* no keys were added, return last error */ 242319370Spst ldns_rr_list_free(validkeys); 242419370Spst return result; 242519370Spst } 2426130809Smarcel 2427130809Smarcel /* do not check timestamps */ 2428130809Smarcel 2429130809Smarcel ldns_rr_list_cat(good_keys, validkeys); 2430130809Smarcel ldns_rr_list_free(validkeys); 2431130809Smarcel return LDNS_STATUS_OK; 2432130809Smarcel} 2433130809Smarcel 2434130809Smarcelldns_status 2435130809Smarcelldns_verify_rrsig_time( 243619370Spst ldns_rr_list *rrset, 243719370Spst ldns_rr *rrsig, 2438130809Smarcel ldns_rr *key, 2439130809Smarcel time_t check_time) 2440130809Smarcel{ 244119370Spst ldns_buffer *rawsig_buf; 244219370Spst ldns_buffer *verify_buf; 244319370Spst ldns_status result; 244419370Spst ldns_rr_list *rrset_clone; 244519370Spst 244619370Spst if (!rrset) { 244719370Spst return LDNS_STATUS_NO_DATA; 244819370Spst } 244919370Spst /* clone the rrset so that we can fiddle with it */ 245019370Spst rrset_clone = ldns_rr_list_clone(rrset); 245119370Spst /* create the buffers which will certainly hold the raw data */ 245298948Sobrien rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 245319370Spst verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 245498948Sobrien 245519370Spst result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 2456130809Smarcel rrset_clone, rrsig); 2457130809Smarcel if(result != LDNS_STATUS_OK) { 245846283Sdfr ldns_rr_list_deep_free(rrset_clone); 245919370Spst ldns_buffer_free(rawsig_buf); 246019370Spst ldns_buffer_free(verify_buf); 2461130809Smarcel return result; 246219370Spst } 246319370Spst result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 246419370Spst rrsig, key); 246519370Spst /* no longer needed */ 246619370Spst ldns_rr_list_deep_free(rrset_clone); 246719370Spst ldns_buffer_free(rawsig_buf); 246819370Spst ldns_buffer_free(verify_buf); 246919370Spst 247098948Sobrien /* check timestamp last, apart from time its OK */ 247198948Sobrien if(result == LDNS_STATUS_OK) 2472130809Smarcel result = ldns_rrsig_check_timestamps(rrsig, check_time); 2473130809Smarcel 247498948Sobrien return result; 247598948Sobrien} 247698948Sobrien 247798948Sobrienldns_status 247819370Spstldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) 247919370Spst{ 248019370Spst return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL)); 248119370Spst} 248219370Spst 248319370Spst 248419370Spstldns_status 248519370Spstldns_verify_rrsig_evp(ldns_buffer *sig, 248619370Spst ldns_buffer *rrset, 248719370Spst EVP_PKEY *key, 248819370Spst const EVP_MD *digest_type) 2489130809Smarcel{ 2490130809Smarcel return ldns_verify_rrsig_evp_raw( 249119370Spst (unsigned char*)ldns_buffer_begin(sig), 249219370Spst ldns_buffer_position(sig), 249319370Spst rrset, 249419370Spst key, 249519370Spst digest_type); 249619370Spst} 249719370Spst 249898948Sobrienldns_status 249919370Spstldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 2500130809Smarcel ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type) 250119370Spst{ 250219370Spst EVP_MD_CTX ctx; 250346283Sdfr int res; 250419370Spst 250519370Spst EVP_MD_CTX_init(&ctx); 250698948Sobrien 250719370Spst EVP_VerifyInit(&ctx, digest_type); 250819370Spst EVP_VerifyUpdate(&ctx, 250946283Sdfr ldns_buffer_begin(rrset), 251019370Spst ldns_buffer_position(rrset)); 251119370Spst res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key); 251219370Spst 2513130809Smarcel EVP_MD_CTX_cleanup(&ctx); 251419370Spst 2515130809Smarcel if (res == 1) { 251619370Spst return LDNS_STATUS_OK; 251719370Spst } else if (res == 0) { 251819370Spst return LDNS_STATUS_CRYPTO_BOGUS; 2519130809Smarcel } 252019370Spst /* TODO how to communicate internal SSL error? 252119370Spst let caller use ssl's get_error() */ 252219370Spst return LDNS_STATUS_SSL_ERR; 252319370Spst} 252498948Sobrien 252519370Spstldns_status 252698948Sobrienldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 252798948Sobrien{ 252898948Sobrien return ldns_verify_rrsig_dsa_raw( 252919370Spst (unsigned char*) ldns_buffer_begin(sig), 253019370Spst ldns_buffer_position(sig), 253119370Spst rrset, 253219370Spst (unsigned char*) ldns_buffer_begin(key), 253319370Spst ldns_buffer_position(key)); 253419370Spst} 253519370Spst 253698948Sobrienldns_status 253719370Spstldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 253819370Spst{ 253919370Spst return ldns_verify_rrsig_rsasha1_raw( 254019370Spst (unsigned char*)ldns_buffer_begin(sig), 254198948Sobrien ldns_buffer_position(sig), 254298948Sobrien rrset, 2543130809Smarcel (unsigned char*) ldns_buffer_begin(key), 254419370Spst ldns_buffer_position(key)); 254519370Spst} 254619370Spst 254719370Spstldns_status 254819370Spstldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 254919370Spst{ 255046283Sdfr return ldns_verify_rrsig_rsamd5_raw( 255198948Sobrien (unsigned char*)ldns_buffer_begin(sig), 255219370Spst ldns_buffer_position(sig), 255319370Spst rrset, 255419370Spst (unsigned char*) ldns_buffer_begin(key), 255519370Spst ldns_buffer_position(key)); 255619370Spst} 255719370Spst 255819370Spstldns_status 255919370Spstldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen, 256019370Spst ldns_buffer* rrset, unsigned char* key, size_t keylen) 256198948Sobrien{ 256219370Spst EVP_PKEY *evp_key; 256346283Sdfr ldns_status result; 256419370Spst 256519370Spst evp_key = EVP_PKEY_new(); 256646283Sdfr if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) { 256719370Spst result = ldns_verify_rrsig_evp_raw(sig, 256898948Sobrien siglen, 256919370Spst rrset, 257098948Sobrien evp_key, 257198948Sobrien EVP_dss1()); 257246283Sdfr } else { 257319370Spst result = LDNS_STATUS_SSL_ERR; 257498948Sobrien } 257519370Spst EVP_PKEY_free(evp_key); 257619370Spst return result; 257719370Spst 257819370Spst} 257919370Spst 258019370Spstldns_status 258119370Spstldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen, 258219370Spst ldns_buffer* rrset, unsigned char* key, size_t keylen) 258319370Spst{ 258419370Spst EVP_PKEY *evp_key; 2585130809Smarcel ldns_status result; 258619370Spst 2587130809Smarcel evp_key = EVP_PKEY_new(); 258819370Spst if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 258919370Spst result = ldns_verify_rrsig_evp_raw(sig, 259098948Sobrien siglen, 259198948Sobrien rrset, 259298948Sobrien evp_key, 259319370Spst EVP_sha1()); 259419370Spst } else { 259519370Spst result = LDNS_STATUS_SSL_ERR; 259619370Spst } 259798948Sobrien EVP_PKEY_free(evp_key); 259819370Spst 259998948Sobrien return result; 260098948Sobrien} 260198948Sobrien 260298948Sobrienldns_status 260319370Spstldns_verify_rrsig_rsasha256_raw(unsigned char* sig, 260419370Spst size_t siglen, 260519370Spst ldns_buffer* rrset, 260619370Spst unsigned char* key, 260719370Spst size_t keylen) 260819370Spst{ 260919370Spst#ifdef USE_SHA2 261019370Spst EVP_PKEY *evp_key; 261119370Spst ldns_status result; 261219370Spst 261398948Sobrien evp_key = EVP_PKEY_new(); 261419370Spst if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 261519370Spst result = ldns_verify_rrsig_evp_raw(sig, 261619370Spst siglen, 261719370Spst rrset, 261819370Spst evp_key, 261919370Spst EVP_sha256()); 2620130809Smarcel } else { 262119370Spst result = LDNS_STATUS_SSL_ERR; 262219370Spst } 262319370Spst EVP_PKEY_free(evp_key); 262419370Spst 262519370Spst return result; 2626130809Smarcel#else 262719370Spst /* touch these to prevent compiler warnings */ 262819370Spst (void) sig; 262919370Spst (void) siglen; 263098948Sobrien (void) rrset; 263146283Sdfr (void) key; 263219370Spst (void) keylen; 263319370Spst return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 263498948Sobrien#endif 263519370Spst} 263619370Spst 263719370Spstldns_status 263819370Spstldns_verify_rrsig_rsasha512_raw(unsigned char* sig, 263919370Spst size_t siglen, 264019370Spst ldns_buffer* rrset, 264119370Spst unsigned char* key, 264219370Spst size_t keylen) 264319370Spst{ 264498948Sobrien#ifdef USE_SHA2 264598948Sobrien EVP_PKEY *evp_key; 264698948Sobrien ldns_status result; 264798948Sobrien 264898948Sobrien evp_key = EVP_PKEY_new(); 264919370Spst if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 265098948Sobrien result = ldns_verify_rrsig_evp_raw(sig, 265119370Spst siglen, 265219370Spst rrset, 265398948Sobrien evp_key, 265498948Sobrien EVP_sha512()); 265598948Sobrien } else { 265619370Spst result = LDNS_STATUS_SSL_ERR; 265719370Spst } 265819370Spst EVP_PKEY_free(evp_key); 265919370Spst 266019370Spst return result; 266119370Spst#else 266219370Spst /* touch these to prevent compiler warnings */ 266319370Spst (void) sig; 266419370Spst (void) siglen; 266519370Spst (void) rrset; 266619370Spst (void) key; 266719370Spst (void) keylen; 2668130809Smarcel return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 266919370Spst#endif 267019370Spst} 267119370Spst 267219370Spst 267319370Spstldns_status 267419370Spstldns_verify_rrsig_rsamd5_raw(unsigned char* sig, 267519370Spst size_t siglen, 267698948Sobrien ldns_buffer* rrset, 267798948Sobrien unsigned char* key, 267898948Sobrien size_t keylen) 267998948Sobrien{ 2680130809Smarcel EVP_PKEY *evp_key; 2681130809Smarcel ldns_status result; 2682130809Smarcel 2683130809Smarcel evp_key = EVP_PKEY_new(); 268498948Sobrien if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 268598948Sobrien result = ldns_verify_rrsig_evp_raw(sig, 268619370Spst siglen, 268719370Spst rrset, 268819370Spst evp_key, 268919370Spst EVP_md5()); 269019370Spst } else { 269119370Spst result = LDNS_STATUS_SSL_ERR; 269219370Spst } 269319370Spst EVP_PKEY_free(evp_key); 269419370Spst 269519370Spst return result; 269619370Spst} 269798948Sobrien 269819370Spst#endif 269919370Spst