Changeset View
Changeset View
Standalone View
Standalone View
contrib/ldns/dnssec_verify.c
Show All 15 Lines | |||||
#include <openssl/md5.h> | #include <openssl/md5.h> | ||||
ldns_dnssec_data_chain * | ldns_dnssec_data_chain * | ||||
ldns_dnssec_data_chain_new(void) | ldns_dnssec_data_chain_new(void) | ||||
{ | { | ||||
ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); | ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); | ||||
if(!nc) return NULL; | if(!nc) return NULL; | ||||
/* | /* | ||||
* not needed anymore because CALLOC initalizes everything to zero. | * not needed anymore because CALLOC initializes everything to zero. | ||||
nc->rrset = NULL; | nc->rrset = NULL; | ||||
nc->parent_type = 0; | nc->parent_type = 0; | ||||
nc->parent = NULL; | nc->parent = NULL; | ||||
nc->signatures = NULL; | nc->signatures = NULL; | ||||
nc->packet_rcode = 0; | nc->packet_rcode = 0; | ||||
nc->packet_qtype = 0; | nc->packet_qtype = 0; | ||||
nc->packet_nodata = false; | nc->packet_nodata = false; | ||||
▲ Show 20 Lines • Show All 377 Lines • ▼ Show 20 Lines | if (!key_name) { | ||||
} | } | ||||
return ldns_dnssec_build_data_chain_nokeyname(res, | return ldns_dnssec_build_data_chain_nokeyname(res, | ||||
qflags, | qflags, | ||||
orig_rr, | orig_rr, | ||||
rrset, | rrset, | ||||
new_chain); | new_chain); | ||||
} | } | ||||
if (type != LDNS_RR_TYPE_DNSKEY) { | if (type != LDNS_RR_TYPE_DNSKEY) { | ||||
if (type != LDNS_RR_TYPE_DS || | |||||
ldns_dname_is_subdomain(name, key_name)) { | |||||
ldns_dnssec_build_data_chain_dnskey(res, | ldns_dnssec_build_data_chain_dnskey(res, | ||||
qflags, | qflags, | ||||
pkt, | pkt, | ||||
signatures, | signatures, | ||||
new_chain, | new_chain, | ||||
key_name, | key_name, | ||||
c | c | ||||
); | ); | ||||
} | |||||
} else { | } else { | ||||
ldns_dnssec_build_data_chain_other(res, | ldns_dnssec_build_data_chain_other(res, | ||||
qflags, | qflags, | ||||
new_chain, | new_chain, | ||||
key_name, | key_name, | ||||
c, | c, | ||||
dss | dss | ||||
); | ); | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | if (tree->rr) { | ||||
print_tabs(out, tabs + 1, sibmap, treedepth); | print_tabs(out, tabs + 1, sibmap, treedepth); | ||||
fprintf(out, | fprintf(out, | ||||
"%s:\n", | "%s:\n", | ||||
ldns_get_errorstr_by_id( | ldns_get_errorstr_by_id( | ||||
tree->parent_status[i])); | tree->parent_status[i])); | ||||
if (tree->parent_status[i] | if (tree->parent_status[i] | ||||
== LDNS_STATUS_SSL_ERR) { | == LDNS_STATUS_SSL_ERR) { | ||||
printf("; SSL Error: "); | printf("; SSL Error: "); | ||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(HAVE_LIBRESSL) | |||||
ERR_load_crypto_strings(); | ERR_load_crypto_strings(); | ||||
#endif | |||||
ERR_print_errors_fp(stdout); | ERR_print_errors_fp(stdout); | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
ldns_rr_print_fmt(out, fmt, | ldns_rr_print_fmt(out, fmt, | ||||
tree-> | tree-> | ||||
parent_signature[i]); | parent_signature[i]); | ||||
printf("For RRset:\n"); | printf("For RRset:\n"); | ||||
ldns_rr_list_print_fmt(out, fmt, | ldns_rr_list_print_fmt(out, fmt, | ||||
▲ Show 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | if (cur_parent_rr != cur_rr && | ||||
if (ldns_calc_keytag(cur_parent_rr) == cur_keytag | if (ldns_calc_keytag(cur_parent_rr) == cur_keytag | ||||
) { | ) { | ||||
cur_parent_tree = ldns_dnssec_trust_tree_new(); | cur_parent_tree = ldns_dnssec_trust_tree_new(); | ||||
cur_parent_tree->rr = cur_parent_rr; | cur_parent_tree->rr = cur_parent_rr; | ||||
cur_parent_tree->rrset = cur_rrset; | cur_parent_tree->rrset = cur_rrset; | ||||
cur_status = ldns_verify_rrsig_time( | cur_status = ldns_verify_rrsig_time( | ||||
cur_rrset, cur_sig_rr, | cur_rrset, cur_sig_rr, | ||||
cur_parent_rr, check_time); | cur_parent_rr, check_time); | ||||
(void) ldns_dnssec_trust_tree_add_parent(new_tree, | if (ldns_dnssec_trust_tree_add_parent(new_tree, | ||||
cur_parent_tree, cur_sig_rr, cur_status); | cur_parent_tree, cur_sig_rr, cur_status)) | ||||
ldns_dnssec_trust_tree_free(cur_parent_tree); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void | void | ||||
ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, | ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, | ||||
ldns_dnssec_data_chain *data_chain, | ldns_dnssec_data_chain *data_chain, | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | if (data_chain->parent && data_chain->parent->rrset) { | ||||
} | } | ||||
for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) { | for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) { | ||||
cur_parent_rr = ldns_rr_list_rr(cur_rrset, i); | cur_parent_rr = ldns_rr_list_rr(cur_rrset, i); | ||||
cur_parent_tree = | cur_parent_tree = | ||||
ldns_dnssec_derive_trust_tree_time( | ldns_dnssec_derive_trust_tree_time( | ||||
data_chain->parent, | data_chain->parent, | ||||
cur_parent_rr, | cur_parent_rr, | ||||
check_time); | check_time); | ||||
(void) ldns_dnssec_trust_tree_add_parent(new_tree, | if (ldns_dnssec_trust_tree_add_parent(new_tree, | ||||
cur_parent_tree, NULL, result); | cur_parent_tree, NULL, result)) | ||||
ldns_dnssec_trust_tree_free(cur_parent_tree); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
void | void | ||||
ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, | ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, | ||||
ldns_dnssec_data_chain *data_chain) | ldns_dnssec_data_chain *data_chain) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 459 Lines • ▼ Show 20 Lines | |||||
ldns_status | ldns_status | ||||
ldns_dnssec_verify_denial(ldns_rr *rr, | ldns_dnssec_verify_denial(ldns_rr *rr, | ||||
ldns_rr_list *nsecs, | ldns_rr_list *nsecs, | ||||
ldns_rr_list *rrsigs) | ldns_rr_list *rrsigs) | ||||
{ | { | ||||
ldns_rdf *rr_name; | ldns_rdf *rr_name; | ||||
ldns_rdf *wildcard_name; | ldns_rdf *wildcard_name = NULL; | ||||
ldns_rdf *chopped_dname; | ldns_rdf *chopped_dname; | ||||
ldns_rr *cur_nsec; | ldns_rr *cur_nsec; | ||||
size_t i; | size_t i; | ||||
ldns_status result; | ldns_status result; | ||||
/* needed for wildcard check on exact match */ | /* needed for wildcard check on exact match */ | ||||
ldns_rr *rrsig; | ldns_rr *rrsig; | ||||
bool name_covered = false; | bool name_covered = false; | ||||
bool type_covered = false; | bool type_covered = false; | ||||
bool wildcard_covered = false; | bool wildcard_covered = false; | ||||
bool wildcard_type_covered = false; | bool wildcard_type_covered = false; | ||||
bool rr_name_is_root = false; | |||||
wildcard_name = ldns_dname_new_frm_str("*"); | |||||
rr_name = ldns_rr_owner(rr); | rr_name = ldns_rr_owner(rr); | ||||
rr_name_is_root = ldns_rdf_size(rr_name) == 1 | |||||
&& *ldns_rdf_data(rr_name) == 0; | |||||
if (!rr_name_is_root) { | |||||
wildcard_name = ldns_dname_new_frm_str("*"); | |||||
chopped_dname = ldns_dname_left_chop(rr_name); | chopped_dname = ldns_dname_left_chop(rr_name); | ||||
result = ldns_dname_cat(wildcard_name, chopped_dname); | result = ldns_dname_cat(wildcard_name, chopped_dname); | ||||
ldns_rdf_deep_free(chopped_dname); | ldns_rdf_deep_free(chopped_dname); | ||||
if (result != LDNS_STATUS_OK) { | if (result != LDNS_STATUS_OK) { | ||||
return result; | return result; | ||||
} | } | ||||
} | |||||
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { | for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { | ||||
cur_nsec = ldns_rr_list_rr(nsecs, i); | cur_nsec = ldns_rr_list_rr(nsecs, i); | ||||
if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { | if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { | ||||
/* see section 5.4 of RFC4035, if the label count of the NSEC's | /* see section 5.4 of RFC4035, if the label count of the NSEC's | ||||
RRSIG is equal, then it is proven that wildcard expansion | RRSIG is equal, then it is proven that wildcard expansion | ||||
could not have been used to match the request */ | could not have been used to match the request */ | ||||
rrsig = ldns_dnssec_get_rrsig_for_name_and_type( | rrsig = ldns_dnssec_get_rrsig_for_name_and_type( | ||||
Show All 9 Lines | if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { | ||||
ldns_rr_get_type(rr))) { | ldns_rr_get_type(rr))) { | ||||
type_covered = true; | type_covered = true; | ||||
} | } | ||||
} | } | ||||
if (ldns_nsec_covers_name(cur_nsec, rr_name)) { | if (ldns_nsec_covers_name(cur_nsec, rr_name)) { | ||||
name_covered = true; | name_covered = true; | ||||
} | } | ||||
if (rr_name_is_root) | |||||
continue; | |||||
if (ldns_dname_compare(wildcard_name, | if (ldns_dname_compare(wildcard_name, | ||||
ldns_rr_owner(cur_nsec)) == 0) { | ldns_rr_owner(cur_nsec)) == 0) { | ||||
if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), | if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), | ||||
ldns_rr_get_type(rr))) { | ldns_rr_get_type(rr))) { | ||||
wildcard_type_covered = true; | wildcard_type_covered = true; | ||||
} | } | ||||
} | } | ||||
if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { | if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { | ||||
wildcard_covered = true; | wildcard_covered = true; | ||||
} | } | ||||
} | } | ||||
ldns_rdf_deep_free(wildcard_name); | ldns_rdf_deep_free(wildcard_name); | ||||
if (type_covered || !name_covered) { | if (type_covered || !name_covered) { | ||||
return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; | return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; | ||||
} | } | ||||
if (rr_name_is_root) | |||||
return LDNS_STATUS_OK; | |||||
if (wildcard_type_covered || !wildcard_covered) { | if (wildcard_type_covered || !wildcard_covered) { | ||||
return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; | return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; | ||||
} | } | ||||
return LDNS_STATUS_OK; | return LDNS_STATUS_OK; | ||||
} | } | ||||
ldns_status | ldns_status | ||||
ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr | ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr | ||||
, ldns_rr_list *nsecs | , ldns_rr_list *nsecs | ||||
, ATTR_UNUSED(ldns_rr_list *rrsigs) | , ATTR_UNUSED(ldns_rr_list *rrsigs) | ||||
, ldns_pkt_rcode packet_rcode | , ldns_pkt_rcode packet_rcode | ||||
, ldns_rr_type packet_qtype | , ldns_rr_type packet_qtype | ||||
, bool packet_nodata | , bool packet_nodata | ||||
, ldns_rr **match | , ldns_rr **match | ||||
) | ) | ||||
{ | { | ||||
ldns_rdf *closest_encloser; | ldns_rdf *closest_encloser; | ||||
ldns_rdf *wildcard; | ldns_rdf *wildcard; | ||||
ldns_rdf *hashed_wildcard_name; | ldns_rdf *hashed_wildcard_name; | ||||
bool wildcard_covered = false; | bool wildcard_covered = false; | ||||
ldns_rdf *zone_name; | ldns_rdf *zone_name; | ||||
ldns_rdf *hashed_name; | ldns_rdf *hashed_name; | ||||
/* self assignment to suppress uninitialized warning */ | |||||
ldns_rdf *next_closer = next_closer; | |||||
ldns_rdf *hashed_next_closer; | ldns_rdf *hashed_next_closer; | ||||
size_t i; | size_t i; | ||||
ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; | ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; | ||||
if (match) { | if (match) { | ||||
*match = NULL; | *match = NULL; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { | ||||
result = LDNS_STATUS_OK; | result = LDNS_STATUS_OK; | ||||
if (match) { | if (match) { | ||||
*match = ldns_rr_list_rr(nsecs, i); | *match = ldns_rr_list_rr(nsecs, i); | ||||
} | } | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
ldns_rdf_deep_free(hashed_name); | |||||
result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; | result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; | ||||
/* wildcard no data? section 8.7 */ | /* wildcard no data? section 8.7 */ | ||||
closest_encloser = ldns_dnssec_nsec3_closest_encloser( | closest_encloser = ldns_dnssec_nsec3_closest_encloser( | ||||
ldns_rr_owner(rr), | ldns_rr_owner(rr), | ||||
ldns_rr_get_type(rr), | ldns_rr_get_type(rr), | ||||
nsecs); | nsecs); | ||||
if(!closest_encloser) { | if(!closest_encloser) { | ||||
result = LDNS_STATUS_NSEC3_ERR; | result = LDNS_STATUS_NSEC3_ERR; | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | if (packet_rcode == LDNS_RCODE_NXDOMAIN) { | ||||
/* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/ | /* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/ | ||||
if (ldns_dname_label_count(closest_encloser) + 1 | if (ldns_dname_label_count(closest_encloser) + 1 | ||||
>= ldns_dname_label_count(ldns_rr_owner(rr))) { | >= ldns_dname_label_count(ldns_rr_owner(rr))) { | ||||
/* Query name *is* the "next closer". */ | /* Query name *is* the "next closer". */ | ||||
hashed_next_closer = hashed_name; | hashed_next_closer = hashed_name; | ||||
} else { | } else { | ||||
ldns_rdf *next_closer; | |||||
ldns_rdf_deep_free(hashed_name); | |||||
/* "next closer" has less labels than the query name. | /* "next closer" has less labels than the query name. | ||||
* Create the name and hash it. | * Create the name and hash it. | ||||
*/ | */ | ||||
next_closer = ldns_dname_clone_from( | next_closer = ldns_dname_clone_from( | ||||
ldns_rr_owner(rr), | ldns_rr_owner(rr), | ||||
ldns_dname_label_count(ldns_rr_owner(rr)) | ldns_dname_label_count(ldns_rr_owner(rr)) | ||||
- (ldns_dname_label_count(closest_encloser) + 1) | - (ldns_dname_label_count(closest_encloser) + 1) | ||||
); | ); | ||||
hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3( | hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3( | ||||
ldns_rr_list_rr(nsecs, 0), | ldns_rr_list_rr(nsecs, 0), | ||||
next_closer | next_closer | ||||
); | ); | ||||
(void) ldns_dname_cat(hashed_next_closer, zone_name); | (void) ldns_dname_cat(hashed_next_closer, zone_name); | ||||
ldns_rdf_deep_free(next_closer); | |||||
} | } | ||||
/* Find the NSEC3 that covers the "next closer" */ | /* Find the NSEC3 that covers the "next closer" */ | ||||
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { | for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { | ||||
if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), | if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), | ||||
hashed_next_closer) && | hashed_next_closer) && | ||||
ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) { | ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) { | ||||
result = LDNS_STATUS_OK; | result = LDNS_STATUS_OK; | ||||
if (match) { | if (match) { | ||||
*match = ldns_rr_list_rr(nsecs, i); | *match = ldns_rr_list_rr(nsecs, i); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (ldns_dname_label_count(closest_encloser) + 1 | |||||
< ldns_dname_label_count(ldns_rr_owner(rr))) { | |||||
/* "next closer" has less labels than the query name. | |||||
* Dispose of the temporary variables that held that name. | |||||
*/ | |||||
ldns_rdf_deep_free(hashed_next_closer); | ldns_rdf_deep_free(hashed_next_closer); | ||||
ldns_rdf_deep_free(next_closer); | |||||
} | |||||
ldns_rdf_deep_free(closest_encloser); | ldns_rdf_deep_free(closest_encloser); | ||||
} | } | ||||
done: | done: | ||||
ldns_rdf_deep_free(zone_name); | ldns_rdf_deep_free(zone_name); | ||||
return result; | return result; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | ldns_verify_rrsig_gost_raw(const unsigned char* sig, size_t siglen, | ||||
return result; | return result; | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef USE_ED25519 | #ifdef USE_ED25519 | ||||
EVP_PKEY* | EVP_PKEY* | ||||
ldns_ed255192pkey_raw(const unsigned char* key, size_t keylen) | ldns_ed255192pkey_raw(const unsigned char* key, size_t keylen) | ||||
{ | { | ||||
const unsigned char* pp = key; /* pp gets modified by o2i() */ | /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */ | ||||
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, | |||||
0x70, 0x03, 0x21, 0x00}; | |||||
int pre_len = 12; | |||||
uint8_t buf[256]; | |||||
EVP_PKEY *evp_key; | EVP_PKEY *evp_key; | ||||
EC_KEY *ec; | /* pp gets modified by d2i() */ | ||||
if(keylen != 32) | const unsigned char* pp = (unsigned char*)buf; | ||||
if(keylen != 32 || keylen + pre_len > sizeof(buf)) | |||||
return NULL; /* wrong length */ | return NULL; /* wrong length */ | ||||
ec = EC_KEY_new_by_curve_name(NID_X25519); | memmove(buf, pre, pre_len); | ||||
if(!ec) return NULL; | memmove(buf+pre_len, key, keylen); | ||||
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen)) { | evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); | ||||
EC_KEY_free(ec); | |||||
return NULL; | |||||
} | |||||
evp_key = EVP_PKEY_new(); | |||||
if(!evp_key) { | |||||
EC_KEY_free(ec); | |||||
return NULL; | |||||
} | |||||
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { | |||||
EVP_PKEY_free(evp_key); | |||||
EC_KEY_free(ec); | |||||
return NULL; | |||||
} | |||||
return evp_key; | return evp_key; | ||||
} | } | ||||
static ldns_status | static ldns_status | ||||
ldns_verify_rrsig_ed25519_raw(unsigned char* sig, size_t siglen, | ldns_verify_rrsig_ed25519_raw(unsigned char* sig, size_t siglen, | ||||
ldns_buffer* rrset, unsigned char* key, size_t keylen) | ldns_buffer* rrset, unsigned char* key, size_t keylen) | ||||
{ | { | ||||
EVP_PKEY *evp_key; | EVP_PKEY *evp_key; | ||||
ldns_status result; | ldns_status result; | ||||
evp_key = ldns_ed255192pkey_raw(key, keylen); | evp_key = ldns_ed255192pkey_raw(key, keylen); | ||||
if(!evp_key) { | if(!evp_key) { | ||||
/* could not convert key */ | /* could not convert key */ | ||||
return LDNS_STATUS_CRYPTO_BOGUS; | return LDNS_STATUS_CRYPTO_BOGUS; | ||||
} | } | ||||
result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, | result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, NULL); | ||||
EVP_sha512()); | |||||
EVP_PKEY_free(evp_key); | EVP_PKEY_free(evp_key); | ||||
return result; | return result; | ||||
} | } | ||||
#endif /* USE_ED25519 */ | #endif /* USE_ED25519 */ | ||||
#ifdef USE_ED448 | #ifdef USE_ED448 | ||||
EVP_PKEY* | EVP_PKEY* | ||||
ldns_ed4482pkey_raw(const unsigned char* key, size_t keylen) | ldns_ed4482pkey_raw(const unsigned char* key, size_t keylen) | ||||
{ | { | ||||
const unsigned char* pp = key; /* pp gets modified by o2i() */ | /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */ | ||||
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, | |||||
0x71, 0x03, 0x3a, 0x00}; | |||||
int pre_len = 12; | |||||
uint8_t buf[256]; | |||||
EVP_PKEY *evp_key; | EVP_PKEY *evp_key; | ||||
EC_KEY *ec; | /* pp gets modified by d2i() */ | ||||
if(keylen != 57) | const unsigned char* pp = (unsigned char*)buf; | ||||
if(keylen != 57 || keylen + pre_len > sizeof(buf)) | |||||
return NULL; /* wrong length */ | return NULL; /* wrong length */ | ||||
ec = EC_KEY_new_by_curve_name(NID_X448); | memmove(buf, pre, pre_len); | ||||
if(!ec) return NULL; | memmove(buf+pre_len, key, keylen); | ||||
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen)) { | evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); | ||||
EC_KEY_free(ec); | |||||
return NULL; | |||||
} | |||||
evp_key = EVP_PKEY_new(); | |||||
if(!evp_key) { | |||||
EC_KEY_free(ec); | |||||
return NULL; | |||||
} | |||||
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { | |||||
EVP_PKEY_free(evp_key); | |||||
EC_KEY_free(ec); | |||||
return NULL; | |||||
} | |||||
return evp_key; | return evp_key; | ||||
} | } | ||||
static ldns_status | static ldns_status | ||||
ldns_verify_rrsig_ed448_raw(unsigned char* sig, size_t siglen, | ldns_verify_rrsig_ed448_raw(unsigned char* sig, size_t siglen, | ||||
ldns_buffer* rrset, unsigned char* key, size_t keylen) | ldns_buffer* rrset, unsigned char* key, size_t keylen) | ||||
{ | { | ||||
EVP_PKEY *evp_key; | EVP_PKEY *evp_key; | ||||
ldns_status result; | ldns_status result; | ||||
evp_key = ldns_ed4482pkey_raw(key, keylen); | evp_key = ldns_ed4482pkey_raw(key, keylen); | ||||
if(!evp_key) { | if(!evp_key) { | ||||
/* could not convert key */ | /* could not convert key */ | ||||
return LDNS_STATUS_CRYPTO_BOGUS; | return LDNS_STATUS_CRYPTO_BOGUS; | ||||
} | } | ||||
result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, | result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, NULL); | ||||
EVP_sha512()); | |||||
EVP_PKEY_free(evp_key); | EVP_PKEY_free(evp_key); | ||||
return result; | return result; | ||||
} | } | ||||
#endif /* USE_ED448 */ | #endif /* USE_ED448 */ | ||||
#ifdef USE_ECDSA | #ifdef USE_ECDSA | ||||
EVP_PKEY* | EVP_PKEY* | ||||
ldns_ecdsa2pkey_raw(const unsigned char* key, size_t keylen, uint8_t algo) | ldns_ecdsa2pkey_raw(const unsigned char* key, size_t keylen, uint8_t algo) | ||||
▲ Show 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, const ldns_rr* rrsig) | ||||
case LDNS_RSASHA1_NSEC3: | case LDNS_RSASHA1_NSEC3: | ||||
#ifdef USE_SHA2 | #ifdef USE_SHA2 | ||||
case LDNS_RSASHA256: | case LDNS_RSASHA256: | ||||
case LDNS_RSASHA512: | case LDNS_RSASHA512: | ||||
#endif | #endif | ||||
#ifdef USE_GOST | #ifdef USE_GOST | ||||
case LDNS_ECC_GOST: | case LDNS_ECC_GOST: | ||||
#endif | #endif | ||||
#ifdef USE_ED25519 | |||||
case LDNS_ED25519: | |||||
#endif | |||||
#ifdef USE_ED448 | |||||
case LDNS_ED448: | |||||
#endif | |||||
if (ldns_rr_rdf(rrsig, 8) == NULL) { | if (ldns_rr_rdf(rrsig, 8) == NULL) { | ||||
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; | return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; | ||||
} | } | ||||
if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) | if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) | ||||
!= LDNS_STATUS_OK) { | != LDNS_STATUS_OK) { | ||||
return LDNS_STATUS_MEM_ERR; | return LDNS_STATUS_MEM_ERR; | ||||
} | } | ||||
break; | break; | ||||
Show All 25 Lines | #ifdef USE_ECDSA | ||||
} | } | ||||
if (ldns_convert_ecdsa_rrsig_rdf2asn1( | if (ldns_convert_ecdsa_rrsig_rdf2asn1( | ||||
rawsig_buf, ldns_rr_rdf(rrsig, 8)) | rawsig_buf, ldns_rr_rdf(rrsig, 8)) | ||||
!= LDNS_STATUS_OK) { | != LDNS_STATUS_OK) { | ||||
return LDNS_STATUS_MEM_ERR; | return LDNS_STATUS_MEM_ERR; | ||||
} | } | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef USE_ED25519 | |||||
case LDNS_ED25519: | |||||
/* EVP produces an ASN prefix on the signature, which is | |||||
* not used in the DNS */ | |||||
if (ldns_rr_rdf(rrsig, 8) == NULL) { | |||||
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; | |||||
} | |||||
if (ldns_convert_ed25519_rrsig_rdf2asn1( | |||||
rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { | |||||
return LDNS_STATUS_MEM_ERR; | |||||
} | |||||
break; | |||||
#endif | |||||
#ifdef USE_ED448 | |||||
case LDNS_ED448: | |||||
/* EVP produces an ASN prefix on the signature, which is | |||||
* not used in the DNS */ | |||||
if (ldns_rr_rdf(rrsig, 8) == NULL) { | |||||
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; | |||||
} | |||||
if (ldns_convert_ed448_rrsig_rdf2asn1( | |||||
rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { | |||||
return LDNS_STATUS_MEM_ERR; | |||||
} | |||||
break; | |||||
#endif | |||||
case LDNS_DH: | case LDNS_DH: | ||||
case LDNS_ECC: | case LDNS_ECC: | ||||
case LDNS_INDIRECT: | case LDNS_INDIRECT: | ||||
return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; | return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; | ||||
default: | default: | ||||
return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; | return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; | ||||
} | } | ||||
return LDNS_STATUS_OK; | return LDNS_STATUS_OK; | ||||
▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | |||||
ldns_verify_rrsig_keylist_time( | ldns_verify_rrsig_keylist_time( | ||||
const ldns_rr_list *rrset, | const ldns_rr_list *rrset, | ||||
const ldns_rr *rrsig, | const ldns_rr *rrsig, | ||||
const ldns_rr_list *keys, | const ldns_rr_list *keys, | ||||
time_t check_time, | time_t check_time, | ||||
ldns_rr_list *good_keys) | ldns_rr_list *good_keys) | ||||
{ | { | ||||
ldns_status result; | ldns_status result; | ||||
ldns_rr_list *valid = ldns_rr_list_new(); | ldns_rr_list *valid; | ||||
if (!valid) | |||||
if (!good_keys) | |||||
valid = NULL; | |||||
else if (!(valid = ldns_rr_list_new())) | |||||
return LDNS_STATUS_MEM_ERR; | return LDNS_STATUS_MEM_ERR; | ||||
result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); | result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); | ||||
if(result != LDNS_STATUS_OK) { | if(result != LDNS_STATUS_OK) { | ||||
ldns_rr_list_free(valid); | ldns_rr_list_free(valid); | ||||
return result; | return result; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | #ifdef HAVE_EVP_MD_CTX_NEW | ||||
ctx = EVP_MD_CTX_new(); | ctx = EVP_MD_CTX_new(); | ||||
#else | #else | ||||
ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); | ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); | ||||
if(ctx) EVP_MD_CTX_init(ctx); | if(ctx) EVP_MD_CTX_init(ctx); | ||||
#endif | #endif | ||||
if(!ctx) | if(!ctx) | ||||
return LDNS_STATUS_MEM_ERR; | return LDNS_STATUS_MEM_ERR; | ||||
#if defined(USE_ED25519) || defined(USE_ED448) | |||||
if(!digest_type) { | |||||
res = EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, key); | |||||
if(res == 1) { | |||||
res = EVP_DigestVerify(ctx, sig, siglen, | |||||
ldns_buffer_begin(rrset), | |||||
ldns_buffer_position(rrset)); | |||||
} | |||||
} else { | |||||
#else | |||||
res = 0; | |||||
if(digest_type) { | |||||
#endif | |||||
EVP_VerifyInit(ctx, digest_type); | EVP_VerifyInit(ctx, digest_type); | ||||
EVP_VerifyUpdate(ctx, | EVP_VerifyUpdate(ctx, | ||||
ldns_buffer_begin(rrset), | ldns_buffer_begin(rrset), | ||||
ldns_buffer_position(rrset)); | ldns_buffer_position(rrset)); | ||||
res = EVP_VerifyFinal(ctx, sig, (unsigned int) siglen, key); | res = EVP_VerifyFinal(ctx, sig, (unsigned int) siglen, key); | ||||
} | |||||
EVP_MD_CTX_destroy(ctx); | EVP_MD_CTX_destroy(ctx); | ||||
if (res == 1) { | if (res == 1) { | ||||
return LDNS_STATUS_OK; | return LDNS_STATUS_OK; | ||||
} else if (res == 0) { | } else if (res == 0) { | ||||
return LDNS_STATUS_CRYPTO_BOGUS; | return LDNS_STATUS_CRYPTO_BOGUS; | ||||
} | } | ||||
/* TODO how to communicate internal SSL error? | /* TODO how to communicate internal SSL error? | ||||
let caller use ssl's get_error() */ | let caller use ssl's get_error() */ | ||||
return LDNS_STATUS_SSL_ERR; | return LDNS_STATUS_SSL_ERR; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 183 Lines • Show Last 20 Lines |