aboutsummaryrefslogtreecommitdiffstats
path: root/dnssec_sign.c
diff options
context:
space:
mode:
Diffstat (limited to 'dnssec_sign.c')
-rw-r--r--dnssec_sign.c247
1 files changed, 195 insertions, 52 deletions
diff --git a/dnssec_sign.c b/dnssec_sign.c
index 4af882a2845f..22f09816dafe 100644
--- a/dnssec_sign.c
+++ b/dnssec_sign.c
@@ -20,8 +20,8 @@
#endif /* HAVE_SSL */
ldns_rr *
-ldns_create_empty_rrsig(ldns_rr_list *rrset,
- ldns_key *current_key)
+ldns_create_empty_rrsig(const ldns_rr_list *rrset,
+ const ldns_key *current_key)
{
uint32_t orig_ttl;
ldns_rr_class orig_class;
@@ -122,13 +122,20 @@ ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
ldns_rdf *b64rdf = NULL;
switch(ldns_key_algorithm(current_key)) {
+#ifdef USE_DSA
case LDNS_SIGN_DSA:
case LDNS_SIGN_DSA_NSEC3:
b64rdf = ldns_sign_public_evp(
sign_buf,
ldns_key_evp_key(current_key),
- EVP_dss1());
+# ifdef HAVE_EVP_DSS1
+ EVP_dss1()
+# else
+ EVP_sha1()
+# endif
+ );
break;
+#endif /* USE_DSA */
case LDNS_SIGN_RSASHA1:
case LDNS_SIGN_RSASHA1_NSEC3:
b64rdf = ldns_sign_public_evp(
@@ -172,6 +179,22 @@ ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
EVP_sha384());
break;
#endif
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ b64rdf = ldns_sign_public_evp(
+ sign_buf,
+ ldns_key_evp_key(current_key),
+ EVP_sha512());
+ break;
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ b64rdf = ldns_sign_public_evp(
+ sign_buf,
+ ldns_key_evp_key(current_key),
+ EVP_sha512());
+ break;
+#endif
case LDNS_SIGN_RSAMD5:
b64rdf = ldns_sign_public_evp(
sign_buf,
@@ -308,11 +331,13 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
ldns_rdf *
ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
{
+#ifdef USE_DSA
unsigned char *sha1_hash;
ldns_rdf *sigdata_rdf;
ldns_buffer *b64sig;
DSA_SIG *sig;
+ const BIGNUM *R, *S;
uint8_t *data;
size_t pad;
@@ -342,17 +367,23 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
}
data[0] = 1;
- pad = 20 - (size_t) BN_num_bytes(sig->r);
+# ifdef HAVE_DSA_SIG_GET0
+ DSA_SIG_get0(sig, &R, &S);
+# else
+ R = sig->r;
+ S = sig->s;
+# endif
+ pad = 20 - (size_t) BN_num_bytes(R);
if (pad > 0) {
memset(data + 1, 0, pad);
}
- BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
+ BN_bn2bin(R, (unsigned char *) (data + 1) + pad);
- pad = 20 - (size_t) BN_num_bytes(sig->s);
+ pad = 20 - (size_t) BN_num_bytes(S);
if (pad > 0) {
memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
}
- BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
+ BN_bn2bin(S, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
1 + 2 * SHA_DIGEST_LENGTH,
@@ -363,28 +394,40 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
DSA_SIG_free(sig);
return sigdata_rdf;
+#else
+ (void)to_sign; (void)key;
+ return NULL;
+#endif
}
#ifdef USE_ECDSA
#ifndef S_SPLINT_S
+/** returns the number of bytes per signature-component (i.e. bits/8), or 0. */
static int
ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
{
EC_KEY* ec;
const EC_GROUP* g;
- if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
+#ifdef HAVE_EVP_PKEY_BASE_ID
+ if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
+ return 0;
+#else
+ if(EVP_PKEY_type(key->type) != EVP_PKEY_EC)
return 0;
+#endif
ec = EVP_PKEY_get1_EC_KEY(pkey);
g = EC_KEY_get0_group(ec);
if(!g) {
EC_KEY_free(ec);
return 0;
}
- if(EC_GROUP_get_curve_name(g) == NID_secp224r1 ||
- EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 ||
- EC_GROUP_get_curve_name(g) == NID_secp384r1) {
+ if(EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1) {
+ EC_KEY_free(ec);
+ return 32; /* 256/8 */
+ }
+ if(EC_GROUP_get_curve_name(g) == NID_secp384r1) {
EC_KEY_free(ec);
- return 1;
+ return 48; /* 384/8 */
}
/* downref the eckey, the original is still inside the pkey */
EC_KEY_free(ec);
@@ -399,9 +442,9 @@ ldns_sign_public_evp(ldns_buffer *to_sign,
const EVP_MD *digest_type)
{
unsigned int siglen;
- ldns_rdf *sigdata_rdf;
+ ldns_rdf *sigdata_rdf = NULL;
ldns_buffer *b64sig;
- EVP_MD_CTX ctx;
+ EVP_MD_CTX *ctx;
const EVP_MD *md_type;
int r;
@@ -419,45 +462,94 @@ ldns_sign_public_evp(ldns_buffer *to_sign,
return NULL;
}
- EVP_MD_CTX_init(&ctx);
- r = EVP_SignInit(&ctx, md_type);
+#ifdef HAVE_EVP_MD_CTX_NEW
+ ctx = EVP_MD_CTX_new();
+#else
+ ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
+ if(ctx) EVP_MD_CTX_init(ctx);
+#endif
+ if(!ctx) {
+ ldns_buffer_free(b64sig);
+ return NULL;
+ }
+
+ r = EVP_SignInit(ctx, md_type);
if(r == 1) {
- r = EVP_SignUpdate(&ctx, (unsigned char*)
+ r = EVP_SignUpdate(ctx, (unsigned char*)
ldns_buffer_begin(to_sign),
ldns_buffer_position(to_sign));
} else {
ldns_buffer_free(b64sig);
+ EVP_MD_CTX_destroy(ctx);
return NULL;
}
if(r == 1) {
- r = EVP_SignFinal(&ctx, (unsigned char*)
+ r = EVP_SignFinal(ctx, (unsigned char*)
ldns_buffer_begin(b64sig), &siglen, key);
} else {
ldns_buffer_free(b64sig);
+ EVP_MD_CTX_destroy(ctx);
return NULL;
}
if(r != 1) {
ldns_buffer_free(b64sig);
+ EVP_MD_CTX_destroy(ctx);
return NULL;
}
- /* unfortunately, OpenSSL output is differenct from DNS DSA format */
+ /* OpenSSL output is different, convert it */
+ r = 0;
+#ifdef USE_DSA
#ifndef S_SPLINT_S
+ /* unfortunately, OpenSSL output is different from DNS DSA format */
+# ifdef HAVE_EVP_PKEY_BASE_ID
+ if (EVP_PKEY_base_id(key) == EVP_PKEY_DSA) {
+# else
if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
+# endif
+ r = 1;
sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
-#ifdef USE_ECDSA
- } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC &&
- ldns_pkey_is_ecdsa(key)) {
- sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen);
+ }
#endif
- } else {
+#endif
+#if defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448)
+ if(
+# ifdef HAVE_EVP_PKEY_BASE_ID
+ EVP_PKEY_base_id(key)
+# else
+ EVP_PKEY_type(key->type)
+# endif
+ == EVP_PKEY_EC) {
+# ifdef USE_ECDSA
+ if(ldns_pkey_is_ecdsa(key)) {
+ r = 1;
+ sigdata_rdf = ldns_convert_ecdsa_rrsig_asn1len2rdf(
+ b64sig, (long)siglen, ldns_pkey_is_ecdsa(key));
+ }
+# endif /* USE_ECDSA */
+# ifdef USE_ED25519
+ if(EVP_PKEY_id(key) == NID_X25519) {
+ r = 1;
+ sigdata_rdf = ldns_convert_ed25519_rrsig_asn12rdf(
+ b64sig, siglen);
+ }
+# endif /* USE_ED25519 */
+# ifdef USE_ED448
+ if(EVP_PKEY_id(key) == NID_X448) {
+ r = 1;
+ sigdata_rdf = ldns_convert_ed448_rrsig_asn12rdf(
+ b64sig, siglen);
+ }
+# endif /* USE_ED448 */
+ }
+#endif /* PKEY_EC */
+ if(r == 0) {
/* ok output for other types is the same */
sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
ldns_buffer_begin(b64sig));
}
-#endif /* splint */
ldns_buffer_free(b64sig);
- EVP_MD_CTX_cleanup(&ctx);
+ EVP_MD_CTX_destroy(ctx);
return sigdata_rdf;
}
@@ -816,6 +908,10 @@ ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
nsec_ttl = LDNS_DEFAULT_TTL;
}
+ if (ldns_rdf_size(zone->soa->name) > 222) {
+ return LDNS_STATUS_NSEC3_DOMAINNAME_OVERFLOW;
+ }
+
if (zone->hashed_names) {
ldns_traverse_postorder(zone->hashed_names,
ldns_hashed_names_node_free, NULL);
@@ -1019,39 +1115,86 @@ ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
/** If there are KSKs use only them and mark ZSKs unused */
static void
-ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
+ldns_key_list_filter_for_dnskey(ldns_key_list *key_list, int flags)
{
- int saw_ksk = 0;
+ bool algos[256]
+#ifndef S_SPLINT_S
+ = { false }
+#endif
+ ;
+ ldns_signing_algorithm saw_ksk = 0;
+ ldns_key *key;
size_t i;
- for(i=0; i<ldns_key_list_key_count(key_list); i++)
- if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
- saw_ksk = 1;
- break;
- }
- if(!saw_ksk)
+
+ if (!ldns_key_list_key_count(key_list))
+ return;
+
+ for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+ key = ldns_key_list_key(key_list, i);
+ if ((ldns_key_flags(key) & LDNS_KEY_SEP_KEY) && !saw_ksk)
+ saw_ksk = ldns_key_algorithm(key);
+ algos[ldns_key_algorithm(key)] = true;
+ }
+ if (!saw_ksk)
return;
- for(i=0; i<ldns_key_list_key_count(key_list); i++)
- if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
- ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
+ else
+ algos[saw_ksk] = 0;
+
+ for (i =0; i < ldns_key_list_key_count(key_list); i++) {
+ key = ldns_key_list_key(key_list, i);
+ if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
+ /* We have a ZSK.
+ * Still use it if it has a unique algorithm though!
+ */
+ if ((flags & LDNS_SIGN_WITH_ALL_ALGORITHMS) &&
+ algos[ldns_key_algorithm(key)])
+ algos[ldns_key_algorithm(key)] = false;
+ else
+ ldns_key_set_use(key, 0);
+ }
+ }
}
/** If there are no ZSKs use KSK as ZSK */
static void
-ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list)
+ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list, int flags)
{
- int saw_zsk = 0;
+ bool algos[256]
+#ifndef S_SPLINT_S
+ = { false }
+#endif
+ ;
+ ldns_signing_algorithm saw_zsk = 0;
+ ldns_key *key;
size_t i;
- for(i=0; i<ldns_key_list_key_count(key_list); i++)
- if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
- saw_zsk = 1;
- break;
- }
- if(!saw_zsk)
+
+ if (!ldns_key_list_key_count(key_list))
return;
- /* else filter all KSKs */
- for(i=0; i<ldns_key_list_key_count(key_list); i++)
- if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
- ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
+
+ for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+ key = ldns_key_list_key(key_list, i);
+ if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY) && !saw_zsk)
+ saw_zsk = ldns_key_algorithm(key);
+ algos[ldns_key_algorithm(key)] = true;
+ }
+ if (!saw_zsk)
+ return;
+ else
+ algos[saw_zsk] = 0;
+
+ for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+ key = ldns_key_list_key(key_list, i);
+ if((ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
+ /* We have a KSK.
+ * Still use it if it has a unique algorithm though!
+ */
+ if ((flags & LDNS_SIGN_WITH_ALL_ALGORITHMS) &&
+ algos[ldns_key_algorithm(key)])
+ algos[ldns_key_algorithm(key)] = false;
+ else
+ ldns_key_set_use(key, 0);
+ }
+ }
}
ldns_status
@@ -1110,10 +1253,10 @@ ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
arg);
if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
- ldns_key_list_filter_for_dnskey(key_list);
+ ldns_key_list_filter_for_dnskey(key_list, flags);
if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY)
- ldns_key_list_filter_for_non_dnskey(key_list);
+ ldns_key_list_filter_for_non_dnskey(key_list, flags);
/* TODO: just set count to zero? */
rr_list = ldns_rr_list_new();
@@ -1166,7 +1309,7 @@ ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
key_list,
func,
arg);
- ldns_key_list_filter_for_non_dnskey(key_list);
+ ldns_key_list_filter_for_non_dnskey(key_list, flags);
rr_list = ldns_rr_list_new();
ldns_rr_list_push_rr(rr_list, cur_name->nsec);