diff options
Diffstat (limited to 'dnssec_sign.c')
-rw-r--r-- | dnssec_sign.c | 247 |
1 files changed, 195 insertions, 52 deletions
diff --git a/dnssec_sign.c b/dnssec_sign.c index 4af882a2845f9..22f09816dafe2 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); |