Changeset View
Changeset View
Standalone View
Standalone View
contrib/ldns/dnssec.c
Show All 17 Lines | |||||
#include <time.h> | #include <time.h> | ||||
#ifdef HAVE_SSL | #ifdef HAVE_SSL | ||||
#include <openssl/ssl.h> | #include <openssl/ssl.h> | ||||
#include <openssl/evp.h> | #include <openssl/evp.h> | ||||
#include <openssl/rand.h> | #include <openssl/rand.h> | ||||
#include <openssl/err.h> | #include <openssl/err.h> | ||||
#include <openssl/md5.h> | #include <openssl/md5.h> | ||||
#include <openssl/bn.h> | |||||
#include <openssl/rsa.h> | |||||
#ifdef USE_DSA | |||||
#include <openssl/dsa.h> | |||||
#endif | #endif | ||||
#endif | |||||
ldns_rr * | ldns_rr * | ||||
ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, | ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, | ||||
const ldns_rr_type type, | const ldns_rr_type type, | ||||
const ldns_rr_list *rrs) | const ldns_rr_list *rrs) | ||||
{ | { | ||||
size_t i; | size_t i; | ||||
ldns_rr *candidate; | ldns_rr *candidate; | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | hashed_sname = ldns_nsec3_hash_name(sname, | ||||
salt_length, | salt_length, | ||||
salt); | salt); | ||||
status = ldns_dname_cat(hashed_sname, zone_name); | status = ldns_dname_cat(hashed_sname, zone_name); | ||||
if(status != LDNS_STATUS_OK) { | if(status != LDNS_STATUS_OK) { | ||||
LDNS_FREE(salt); | LDNS_FREE(salt); | ||||
ldns_rdf_deep_free(zone_name); | ldns_rdf_deep_free(zone_name); | ||||
ldns_rdf_deep_free(sname); | ldns_rdf_deep_free(sname); | ||||
ldns_rdf_deep_free(hashed_sname); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { | for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { | ||||
nsec = ldns_rr_list_rr(nsec3s, nsec_i); | nsec = ldns_rr_list_rr(nsec3s, nsec_i); | ||||
/* check values of iterations etc! */ | /* check values of iterations etc! */ | ||||
▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | for (i = 0; (size_t)i < keysize; ++i) { | ||||
ac32 += (i & 1) ? key[i] : key[i] << 8; | ac32 += (i & 1) ? key[i] : key[i] << 8; | ||||
} | } | ||||
ac32 += (ac32 >> 16) & 0xFFFF; | ac32 += (ac32 >> 16) & 0xFFFF; | ||||
return (uint16_t) (ac32 & 0xFFFF); | return (uint16_t) (ac32 & 0xFFFF); | ||||
} | } | ||||
} | } | ||||
#ifdef HAVE_SSL | #ifdef HAVE_SSL | ||||
#ifdef USE_DSA | |||||
DSA * | DSA * | ||||
ldns_key_buf2dsa(const ldns_buffer *key) | ldns_key_buf2dsa(const ldns_buffer *key) | ||||
{ | { | ||||
return ldns_key_buf2dsa_raw((const unsigned char*)ldns_buffer_begin(key), | return ldns_key_buf2dsa_raw((const unsigned char*)ldns_buffer_begin(key), | ||||
ldns_buffer_position(key)); | ldns_buffer_position(key)); | ||||
} | } | ||||
DSA * | DSA * | ||||
Show All 23 Lines | ldns_key_buf2dsa_raw(const unsigned char* key, size_t len) | ||||
P = BN_bin2bn(key+offset, (int)length, NULL); | P = BN_bin2bn(key+offset, (int)length, NULL); | ||||
offset += length; | offset += length; | ||||
G = BN_bin2bn(key+offset, (int)length, NULL); | G = BN_bin2bn(key+offset, (int)length, NULL); | ||||
offset += length; | offset += length; | ||||
Y = BN_bin2bn(key+offset, (int)length, NULL); | Y = BN_bin2bn(key+offset, (int)length, NULL); | ||||
offset += length; | |||||
/* create the key and set its properties */ | /* create the key and set its properties */ | ||||
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { | if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { | ||||
BN_free(Q); | BN_free(Q); | ||||
BN_free(P); | BN_free(P); | ||||
BN_free(G); | BN_free(G); | ||||
BN_free(Y); | BN_free(Y); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) | #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) | ||||
#ifndef S_SPLINT_S | #ifndef S_SPLINT_S | ||||
dsa->p = P; | dsa->p = P; | ||||
dsa->q = Q; | dsa->q = Q; | ||||
dsa->g = G; | dsa->g = G; | ||||
dsa->pub_key = Y; | dsa->pub_key = Y; | ||||
#endif /* splint */ | #endif /* splint */ | ||||
#else /* OPENSSL_VERSION_NUMBER */ | #else /* OPENSSL_VERSION_NUMBER */ | ||||
if (!DSA_set0_pqg(dsa, P, Q, G)) { | if (!DSA_set0_pqg(dsa, P, Q, G)) { | ||||
Show All 10 Lines | if (!DSA_set0_key(dsa, Y, NULL)) { | ||||
/* QPG attached, cleaned up by DSA_fre() */ | /* QPG attached, cleaned up by DSA_fre() */ | ||||
DSA_free(dsa); | DSA_free(dsa); | ||||
BN_free(Y); | BN_free(Y); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
#endif /* OPENSSL_VERSION_NUMBER */ | #endif /* OPENSSL_VERSION_NUMBER */ | ||||
return dsa; | return dsa; | ||||
} | } | ||||
#endif /* USE_DSA */ | |||||
RSA * | RSA * | ||||
ldns_key_buf2rsa(const ldns_buffer *key) | ldns_key_buf2rsa(const ldns_buffer *key) | ||||
{ | { | ||||
return ldns_key_buf2rsa_raw((const unsigned char*)ldns_buffer_begin(key), | return ldns_key_buf2rsa_raw((const unsigned char*)ldns_buffer_begin(key), | ||||
ldns_buffer_position(key)); | ldns_buffer_position(key)); | ||||
} | } | ||||
Show All 9 Lines | ldns_key_buf2rsa_raw(const unsigned char* key, size_t len) | ||||
if (len == 0) | if (len == 0) | ||||
return NULL; | return NULL; | ||||
if (key[0] == 0) { | if (key[0] == 0) { | ||||
if(len < 3) | if(len < 3) | ||||
return NULL; | return NULL; | ||||
/* need some smart comment here XXX*/ | /* need some smart comment here XXX*/ | ||||
/* the exponent is too large so it's places | /* the exponent is too large so it's places | ||||
* futher...???? */ | * further...???? */ | ||||
memmove(&int16, key+1, 2); | memmove(&int16, key+1, 2); | ||||
exp = ntohs(int16); | exp = ntohs(int16); | ||||
offset = 3; | offset = 3; | ||||
} else { | } else { | ||||
exp = key[0]; | exp = key[0]; | ||||
offset = 1; | offset = 1; | ||||
} | } | ||||
Show All 17 Lines | ldns_key_buf2rsa_raw(const unsigned char* key, size_t len) | ||||
(void) BN_bin2bn(key+offset, (int)(len - offset), modulus); | (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); | ||||
rsa = RSA_new(); | rsa = RSA_new(); | ||||
if(!rsa) { | if(!rsa) { | ||||
BN_free(exponent); | BN_free(exponent); | ||||
BN_free(modulus); | BN_free(modulus); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) | #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) | ||||
#ifndef S_SPLINT_S | #ifndef S_SPLINT_S | ||||
rsa->n = modulus; | rsa->n = modulus; | ||||
rsa->e = exponent; | rsa->e = exponent; | ||||
#endif /* splint */ | #endif /* splint */ | ||||
#else /* OPENSSL_VERSION_NUMBER */ | #else /* OPENSSL_VERSION_NUMBER */ | ||||
if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { | if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { | ||||
BN_free(exponent); | BN_free(exponent); | ||||
BN_free(modulus); | BN_free(modulus); | ||||
▲ Show 20 Lines • Show All 427 Lines • ▼ Show 20 Lines | ldns_dnssec_create_nsec3(const ldns_dnssec_name *from, | ||||
on_delegation_point = ldns_dnssec_rrsets_contains_type( | on_delegation_point = ldns_dnssec_rrsets_contains_type( | ||||
from->rrsets, LDNS_RR_TYPE_NS) | from->rrsets, LDNS_RR_TYPE_NS) | ||||
&& !ldns_dnssec_rrsets_contains_type( | && !ldns_dnssec_rrsets_contains_type( | ||||
from->rrsets, LDNS_RR_TYPE_SOA); | from->rrsets, LDNS_RR_TYPE_SOA); | ||||
cur_rrsets = from->rrsets; | cur_rrsets = from->rrsets; | ||||
while (cur_rrsets) { | while (cur_rrsets) { | ||||
/* Do not include non-authoritative rrsets on the delegation point | /* Do not include non-authoritative rrsets on the delegation point | ||||
* in the type bitmap. Potentionally not skipping insecure | * in the type bitmap. Potentially not skipping insecure | ||||
* delegation should have been done earlier, in function | * delegation should have been done earlier, in function | ||||
* ldns_dnssec_zone_create_nsec3s, or even earlier in: | * ldns_dnssec_zone_create_nsec3s, or even earlier in: | ||||
* ldns_dnssec_zone_sign_nsec3_flg . | * ldns_dnssec_zone_sign_nsec3_flg . | ||||
*/ | */ | ||||
if ((on_delegation_point && ( | if ((on_delegation_point && ( | ||||
cur_rrsets->type == LDNS_RR_TYPE_NS | cur_rrsets->type == LDNS_RR_TYPE_NS | ||||
|| cur_rrsets->type == LDNS_RR_TYPE_DS)) | || cur_rrsets->type == LDNS_RR_TYPE_DS)) | ||||
|| (!on_delegation_point && | || (!on_delegation_point && | ||||
▲ Show 20 Lines • Show All 405 Lines • ▼ Show 20 Lines | |||||
ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) | ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) | ||||
{ | { | ||||
uint8_t salt_length; | uint8_t salt_length; | ||||
uint8_t *salt; | uint8_t *salt; | ||||
ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); | ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); | ||||
if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { | if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { | ||||
salt_length = ldns_rdf_data(salt_rdf)[0]; | salt_length = ldns_rdf_data(salt_rdf)[0]; | ||||
if((size_t)salt_length+1 > ldns_rdf_size(salt_rdf)) | |||||
return NULL; | |||||
salt = LDNS_XMALLOC(uint8_t, salt_length); | salt = LDNS_XMALLOC(uint8_t, salt_length); | ||||
if(!salt) return NULL; | if(!salt) return NULL; | ||||
memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); | memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); | ||||
return salt; | return salt; | ||||
} | } | ||||
return NULL; | return NULL; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | ldns_pkt_verify_time(const ldns_pkt *p, ldns_rr_type t, const ldns_rdf *o, | ||||
const ldns_rr_list *k, const ldns_rr_list *s, | const ldns_rr_list *k, const ldns_rr_list *s, | ||||
time_t check_time, ldns_rr_list *good_keys) | time_t check_time, ldns_rr_list *good_keys) | ||||
{ | { | ||||
ldns_rr_list *rrset; | ldns_rr_list *rrset; | ||||
ldns_rr_list *sigs; | ldns_rr_list *sigs; | ||||
ldns_rr_list *sigs_covered; | ldns_rr_list *sigs_covered; | ||||
ldns_rdf *rdf_t; | ldns_rdf *rdf_t; | ||||
ldns_rr_type t_netorder; | ldns_rr_type t_netorder; | ||||
ldns_status status; | |||||
if (!k) { | if (!k) { | ||||
return LDNS_STATUS_ERR; | return LDNS_STATUS_ERR; | ||||
/* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */ | /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */ | ||||
} | } | ||||
if (t == LDNS_RR_TYPE_RRSIG) { | if (t == LDNS_RR_TYPE_RRSIG) { | ||||
/* we don't have RRSIG(RRSIG) (yet? ;-) ) */ | /* we don't have RRSIG(RRSIG) (yet? ;-) ) */ | ||||
Show All 35 Lines | ldns_pkt_verify_time(const ldns_pkt *p, ldns_rr_type t, const ldns_rdf *o, | ||||
rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, | rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, | ||||
LDNS_SECTION_ANY_NOQUESTION); | LDNS_SECTION_ANY_NOQUESTION); | ||||
if (!rrset) { | if (!rrset) { | ||||
if (! s) { | if (! s) { | ||||
ldns_rr_list_deep_free(sigs); | ldns_rr_list_deep_free(sigs); | ||||
} | } | ||||
return LDNS_STATUS_ERR; | return LDNS_STATUS_ERR; | ||||
} | } | ||||
return ldns_verify_time(rrset, sigs, k, check_time, good_keys); | status = ldns_verify_time(rrset, sigs, k, check_time, good_keys); | ||||
ldns_rr_list_deep_free(rrset); | |||||
return status; | |||||
} | } | ||||
ldns_status | ldns_status | ||||
ldns_pkt_verify(const ldns_pkt *p, ldns_rr_type t, const ldns_rdf *o, | ldns_pkt_verify(const ldns_pkt *p, ldns_rr_type t, const ldns_rdf *o, | ||||
const ldns_rr_list *k, const ldns_rr_list *s, ldns_rr_list *good_keys) | const ldns_rr_list *k, const ldns_rr_list *s, ldns_rr_list *good_keys) | ||||
{ | { | ||||
return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys); | return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(num_bytes*2), data); | ||||
return rdf; | return rdf; | ||||
} | } | ||||
ldns_status | ldns_status | ||||
ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, | ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, | ||||
const ldns_rdf *sig_rdf) | const ldns_rdf *sig_rdf) | ||||
{ | { | ||||
/* convert from two BIGNUMs in the rdata buffer, to ASN notation. | /* convert from two BIGNUMs in the rdata buffer, to ASN notation. | ||||
* ASN preable: 30440220 <R 32bytefor256> 0220 <S 32bytefor256> | * ASN preamble: 30440220 <R 32bytefor256> 0220 <S 32bytefor256> | ||||
* the '20' is the length of that field (=bnsize). | * the '20' is the length of that field (=bnsize). | ||||
* the '44' is the total remaining length. | * the '44' is the total remaining length. | ||||
* if negative, start with leading zero. | * if negative, start with leading zero. | ||||
* if starts with 00s, remove them from the number. | * if starts with 00s, remove them from the number. | ||||
*/ | */ | ||||
uint8_t pre[] = {0x30, 0x44, 0x02, 0x20}; | uint8_t pre[] = {0x30, 0x44, 0x02, 0x20}; | ||||
int pre_len = 4; | int pre_len = 4; | ||||
uint8_t mid[] = {0x02, 0x20}; | uint8_t mid[] = {0x02, 0x20}; | ||||
Show All 29 Lines | s_high + bnsize - s_rem; | ||||
ldns_buffer_write_u8(target_buffer, 0); | ldns_buffer_write_u8(target_buffer, 0); | ||||
ldns_buffer_write(target_buffer, d+bnsize+s_rem, bnsize-s_rem); | ldns_buffer_write(target_buffer, d+bnsize+s_rem, bnsize-s_rem); | ||||
} | } | ||||
return ldns_buffer_status(target_buffer); | return ldns_buffer_status(target_buffer); | ||||
} | } | ||||
#endif /* S_SPLINT_S */ | #endif /* S_SPLINT_S */ | ||||
#endif /* USE_ECDSA */ | #endif /* USE_ECDSA */ | ||||
#if defined(USE_ED25519) || defined(USE_ED448) | |||||
/* debug printout routine */ | |||||
static void print_hex(const char* str, uint8_t* d, int len) | |||||
{ | |||||
const char hex[] = "0123456789abcdef"; | |||||
int i; | |||||
printf("%s [len=%d]: ", str, len); | |||||
for(i=0; i<len; i++) { | |||||
int x = (d[i]&0xf0)>>4; | |||||
int y = (d[i]&0x0f); | |||||
printf("%c%c", hex[x], hex[y]); | |||||
} | |||||
printf("\n"); | |||||
} | |||||
#endif | |||||
#ifdef USE_ED25519 | |||||
ldns_rdf * | |||||
ldns_convert_ed25519_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len) | |||||
{ | |||||
unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); | |||||
ldns_rdf* rdf = NULL; | |||||
/* TODO when Openssl supports signing and you can test this */ | |||||
print_hex("sig in ASN", data, sig_len); | |||||
return rdf; | |||||
} | |||||
ldns_status | |||||
ldns_convert_ed25519_rrsig_rdf2asn1(ldns_buffer *target_buffer, | |||||
const ldns_rdf *sig_rdf) | |||||
{ | |||||
/* TODO when Openssl supports signing and you can test this. */ | |||||
/* convert sig_buf into ASN1 into the target_buffer */ | |||||
print_hex("sig raw", ldns_rdf_data(sig_rdf), ldns_rdf_size(sig_rdf)); | |||||
return ldns_buffer_status(target_buffer); | |||||
} | |||||
#endif /* USE_ED25519 */ | |||||
#ifdef USE_ED448 | |||||
ldns_rdf * | |||||
ldns_convert_ed448_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len) | |||||
{ | |||||
unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); | |||||
ldns_rdf* rdf = NULL; | |||||
/* TODO when Openssl supports signing and you can test this */ | |||||
print_hex("sig in ASN", data, sig_len); | |||||
return rdf; | |||||
} | |||||
ldns_status | |||||
ldns_convert_ed448_rrsig_rdf2asn1(ldns_buffer *target_buffer, | |||||
const ldns_rdf *sig_rdf) | |||||
{ | |||||
/* TODO when Openssl supports signing and you can test this. */ | |||||
/* convert sig_buf into ASN1 into the target_buffer */ | |||||
print_hex("sig raw", ldns_rdf_data(sig_rdf), ldns_rdf_size(sig_rdf)); | |||||
return ldns_buffer_status(target_buffer); | |||||
} | |||||
#endif /* USE_ED448 */ | |||||
#endif /* HAVE_SSL */ | #endif /* HAVE_SSL */ |