dnssec_sign.c revision 246827
1238104Sdes#include <ldns/config.h> 2238104Sdes 3238104Sdes#include <ldns/ldns.h> 4238104Sdes 5238104Sdes#include <ldns/dnssec.h> 6238104Sdes#include <ldns/dnssec_sign.h> 7238104Sdes 8238104Sdes#include <strings.h> 9238104Sdes#include <time.h> 10238104Sdes 11238104Sdes#ifdef HAVE_SSL 12238104Sdes/* this entire file is rather useless when you don't have 13238104Sdes * crypto... 14238104Sdes */ 15238104Sdes#include <openssl/ssl.h> 16238104Sdes#include <openssl/evp.h> 17238104Sdes#include <openssl/rand.h> 18238104Sdes#include <openssl/err.h> 19238104Sdes#include <openssl/md5.h> 20238104Sdes#endif /* HAVE_SSL */ 21238104Sdes 22238104Sdesldns_rr * 23238104Sdesldns_create_empty_rrsig(ldns_rr_list *rrset, 24238104Sdes ldns_key *current_key) 25238104Sdes{ 26238104Sdes uint32_t orig_ttl; 27238104Sdes ldns_rr_class orig_class; 28238104Sdes time_t now; 29238104Sdes ldns_rr *current_sig; 30238104Sdes uint8_t label_count; 31238104Sdes ldns_rdf *signame; 32238104Sdes 33238104Sdes label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset, 34238104Sdes 0))); 35238104Sdes /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */ 36238104Sdes if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) 37238104Sdes label_count --; 38238104Sdes 39238104Sdes current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG); 40238104Sdes 41238104Sdes /* set the type on the new signature */ 42238104Sdes orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)); 43238104Sdes orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0)); 44238104Sdes 45238104Sdes ldns_rr_set_ttl(current_sig, orig_ttl); 46238104Sdes ldns_rr_set_class(current_sig, orig_class); 47238104Sdes ldns_rr_set_owner(current_sig, 48238104Sdes ldns_rdf_clone( 49238104Sdes ldns_rr_owner( 50238104Sdes ldns_rr_list_rr(rrset, 51238104Sdes 0)))); 52238104Sdes 53238104Sdes /* fill in what we know of the signature */ 54238104Sdes 55238104Sdes /* set the orig_ttl */ 56238104Sdes (void)ldns_rr_rrsig_set_origttl( 57238104Sdes current_sig, 58238104Sdes ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 59238104Sdes orig_ttl)); 60238104Sdes /* the signers name */ 61238104Sdes signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key)); 62238104Sdes ldns_dname2canonical(signame); 63238104Sdes (void)ldns_rr_rrsig_set_signame( 64238104Sdes current_sig, 65238104Sdes signame); 66238104Sdes /* label count - get it from the first rr in the rr_list */ 67238104Sdes (void)ldns_rr_rrsig_set_labels( 68238104Sdes current_sig, 69238104Sdes ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 70238104Sdes label_count)); 71238104Sdes /* inception, expiration */ 72238104Sdes now = time(NULL); 73238104Sdes if (ldns_key_inception(current_key) != 0) { 74238104Sdes (void)ldns_rr_rrsig_set_inception( 75238104Sdes current_sig, 76238104Sdes ldns_native2rdf_int32( 77238104Sdes LDNS_RDF_TYPE_TIME, 78238104Sdes ldns_key_inception(current_key))); 79238104Sdes } else { 80238104Sdes (void)ldns_rr_rrsig_set_inception( 81238104Sdes current_sig, 82238104Sdes ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now)); 83238104Sdes } 84238104Sdes if (ldns_key_expiration(current_key) != 0) { 85238104Sdes (void)ldns_rr_rrsig_set_expiration( 86238104Sdes current_sig, 87238104Sdes ldns_native2rdf_int32( 88238104Sdes LDNS_RDF_TYPE_TIME, 89238104Sdes ldns_key_expiration(current_key))); 90238104Sdes } else { 91238104Sdes (void)ldns_rr_rrsig_set_expiration( 92238104Sdes current_sig, 93238104Sdes ldns_native2rdf_int32( 94238104Sdes LDNS_RDF_TYPE_TIME, 95238104Sdes now + LDNS_DEFAULT_EXP_TIME)); 96238104Sdes } 97238104Sdes 98238104Sdes (void)ldns_rr_rrsig_set_keytag( 99238104Sdes current_sig, 100238104Sdes ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 101238104Sdes ldns_key_keytag(current_key))); 102238104Sdes 103238104Sdes (void)ldns_rr_rrsig_set_algorithm( 104238104Sdes current_sig, 105238104Sdes ldns_native2rdf_int8( 106238104Sdes LDNS_RDF_TYPE_ALG, 107238104Sdes ldns_key_algorithm(current_key))); 108238104Sdes 109238104Sdes (void)ldns_rr_rrsig_set_typecovered( 110238104Sdes current_sig, 111238104Sdes ldns_native2rdf_int16( 112238104Sdes LDNS_RDF_TYPE_TYPE, 113238104Sdes ldns_rr_get_type(ldns_rr_list_rr(rrset, 114238104Sdes 0)))); 115238104Sdes return current_sig; 116238104Sdes} 117238104Sdes 118238104Sdes#ifdef HAVE_SSL 119238104Sdesldns_rdf * 120238104Sdesldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key) 121238104Sdes{ 122238104Sdes ldns_rdf *b64rdf = NULL; 123238104Sdes 124238104Sdes switch(ldns_key_algorithm(current_key)) { 125238104Sdes case LDNS_SIGN_DSA: 126238104Sdes case LDNS_SIGN_DSA_NSEC3: 127238104Sdes b64rdf = ldns_sign_public_evp( 128238104Sdes sign_buf, 129238104Sdes ldns_key_evp_key(current_key), 130238104Sdes EVP_dss1()); 131238104Sdes break; 132238104Sdes case LDNS_SIGN_RSASHA1: 133238104Sdes case LDNS_SIGN_RSASHA1_NSEC3: 134238104Sdes b64rdf = ldns_sign_public_evp( 135238104Sdes sign_buf, 136238104Sdes ldns_key_evp_key(current_key), 137238104Sdes EVP_sha1()); 138238104Sdes break; 139238104Sdes#ifdef USE_SHA2 140238104Sdes case LDNS_SIGN_RSASHA256: 141238104Sdes b64rdf = ldns_sign_public_evp( 142238104Sdes sign_buf, 143238104Sdes ldns_key_evp_key(current_key), 144238104Sdes EVP_sha256()); 145238104Sdes break; 146238104Sdes case LDNS_SIGN_RSASHA512: 147238104Sdes b64rdf = ldns_sign_public_evp( 148238104Sdes sign_buf, 149238104Sdes ldns_key_evp_key(current_key), 150238104Sdes EVP_sha512()); 151238104Sdes break; 152238104Sdes#endif /* USE_SHA2 */ 153238104Sdes#ifdef USE_GOST 154238104Sdes case LDNS_SIGN_ECC_GOST: 155238104Sdes b64rdf = ldns_sign_public_evp( 156238104Sdes sign_buf, 157238104Sdes ldns_key_evp_key(current_key), 158238104Sdes EVP_get_digestbyname("md_gost94")); 159238104Sdes break; 160238104Sdes#endif /* USE_GOST */ 161238104Sdes#ifdef USE_ECDSA 162238104Sdes case LDNS_SIGN_ECDSAP256SHA256: 163238104Sdes b64rdf = ldns_sign_public_evp( 164238104Sdes sign_buf, 165238104Sdes ldns_key_evp_key(current_key), 166238104Sdes EVP_sha256()); 167238104Sdes break; 168238104Sdes case LDNS_SIGN_ECDSAP384SHA384: 169238104Sdes b64rdf = ldns_sign_public_evp( 170238104Sdes sign_buf, 171238104Sdes ldns_key_evp_key(current_key), 172238104Sdes EVP_sha384()); 173238104Sdes break; 174238104Sdes#endif 175238104Sdes case LDNS_SIGN_RSAMD5: 176238104Sdes b64rdf = ldns_sign_public_evp( 177238104Sdes sign_buf, 178238104Sdes ldns_key_evp_key(current_key), 179238104Sdes EVP_md5()); 180238104Sdes break; 181238104Sdes default: 182238104Sdes /* do _you_ know this alg? */ 183238104Sdes printf("unknown algorithm, "); 184238104Sdes printf("is the one used available on this system?\n"); 185238104Sdes break; 186238104Sdes } 187238104Sdes 188238104Sdes return b64rdf; 189238104Sdes} 190238104Sdes 191238104Sdes/** 192238104Sdes * use this function to sign with a public/private key alg 193238104Sdes * return the created signatures 194238104Sdes */ 195238104Sdesldns_rr_list * 196238104Sdesldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) 197238104Sdes{ 198238104Sdes ldns_rr_list *signatures; 199238104Sdes ldns_rr_list *rrset_clone; 200238104Sdes ldns_rr *current_sig; 201238104Sdes ldns_rdf *b64rdf; 202238104Sdes ldns_key *current_key; 203238104Sdes size_t key_count; 204238104Sdes uint16_t i; 205238104Sdes ldns_buffer *sign_buf; 206238104Sdes ldns_rdf *new_owner; 207238104Sdes 208238104Sdes if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) { 209238104Sdes return NULL; 210238104Sdes } 211238104Sdes 212238104Sdes new_owner = NULL; 213238104Sdes 214238104Sdes signatures = ldns_rr_list_new(); 215238104Sdes 216238104Sdes /* prepare a signature and add all the know data 217238104Sdes * prepare the rrset. Sign this together. */ 218238104Sdes rrset_clone = ldns_rr_list_clone(rrset); 219238104Sdes if (!rrset_clone) { 220238104Sdes return NULL; 221238104Sdes } 222238104Sdes 223238104Sdes /* make it canonical */ 224238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { 225238104Sdes ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), 226238104Sdes ldns_rr_ttl(ldns_rr_list_rr(rrset, 0))); 227238104Sdes ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); 228238104Sdes } 229238104Sdes /* sort */ 230238104Sdes ldns_rr_list_sort(rrset_clone); 231238104Sdes 232238104Sdes for (key_count = 0; 233238104Sdes key_count < ldns_key_list_key_count(keys); 234238104Sdes key_count++) { 235238104Sdes if (!ldns_key_use(ldns_key_list_key(keys, key_count))) { 236238104Sdes continue; 237238104Sdes } 238238104Sdes sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 239238104Sdes if (!sign_buf) { 240238104Sdes ldns_rr_list_free(rrset_clone); 241238104Sdes ldns_rr_list_free(signatures); 242238104Sdes ldns_rdf_free(new_owner); 243238104Sdes return NULL; 244238104Sdes } 245238104Sdes b64rdf = NULL; 246238104Sdes 247238104Sdes current_key = ldns_key_list_key(keys, key_count); 248238104Sdes /* sign all RRs with keys that have ZSKbit, !SEPbit. 249238104Sdes sign DNSKEY RRs with keys that have ZSKbit&SEPbit */ 250238104Sdes if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) { 251238104Sdes current_sig = ldns_create_empty_rrsig(rrset_clone, 252238104Sdes current_key); 253238104Sdes 254238104Sdes /* right now, we have: a key, a semi-sig and an rrset. For 255238104Sdes * which we can create the sig and base64 encode that and 256238104Sdes * add that to the signature */ 257238104Sdes 258238104Sdes if (ldns_rrsig2buffer_wire(sign_buf, current_sig) 259238104Sdes != LDNS_STATUS_OK) { 260238104Sdes ldns_buffer_free(sign_buf); 261238104Sdes /* ERROR */ 262238104Sdes ldns_rr_list_deep_free(rrset_clone); 263238104Sdes return NULL; 264238104Sdes } 265238104Sdes 266238104Sdes /* add the rrset in sign_buf */ 267238104Sdes if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone) 268238104Sdes != LDNS_STATUS_OK) { 269238104Sdes ldns_buffer_free(sign_buf); 270238104Sdes ldns_rr_list_deep_free(rrset_clone); 271238104Sdes return NULL; 272238104Sdes } 273238104Sdes 274238104Sdes b64rdf = ldns_sign_public_buffer(sign_buf, current_key); 275238104Sdes 276238104Sdes if (!b64rdf) { 277238104Sdes /* signing went wrong */ 278238104Sdes ldns_rr_list_deep_free(rrset_clone); 279238104Sdes return NULL; 280238104Sdes } 281238104Sdes 282238104Sdes ldns_rr_rrsig_set_sig(current_sig, b64rdf); 283238104Sdes 284238104Sdes /* push the signature to the signatures list */ 285238104Sdes ldns_rr_list_push_rr(signatures, current_sig); 286238104Sdes } 287238104Sdes ldns_buffer_free(sign_buf); /* restart for the next key */ 288238104Sdes } 289238104Sdes ldns_rr_list_deep_free(rrset_clone); 290238104Sdes 291238104Sdes return signatures; 292238104Sdes} 293238104Sdes 294238104Sdes/** 295238104Sdes * Sign data with DSA 296238104Sdes * 297238104Sdes * \param[in] to_sign The ldns_buffer containing raw data that is 298238104Sdes * to be signed 299238104Sdes * \param[in] key The DSA key structure to sign with 300238104Sdes * \return ldns_rdf for the RRSIG ldns_rr 301238104Sdes */ 302238104Sdesldns_rdf * 303238104Sdesldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) 304238104Sdes{ 305238104Sdes unsigned char *sha1_hash; 306238104Sdes ldns_rdf *sigdata_rdf; 307238104Sdes ldns_buffer *b64sig; 308238104Sdes 309238104Sdes DSA_SIG *sig; 310238104Sdes uint8_t *data; 311238104Sdes size_t pad; 312238104Sdes 313238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 314238104Sdes if (!b64sig) { 315238104Sdes return NULL; 316238104Sdes } 317238104Sdes 318238104Sdes sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), 319238104Sdes ldns_buffer_position(to_sign), NULL); 320238104Sdes if (!sha1_hash) { 321238104Sdes ldns_buffer_free(b64sig); 322238104Sdes return NULL; 323238104Sdes } 324238104Sdes 325238104Sdes sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key); 326238104Sdes if(!sig) { 327238104Sdes ldns_buffer_free(b64sig); 328238104Sdes return NULL; 329238104Sdes } 330238104Sdes 331238104Sdes data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH); 332238104Sdes if(!data) { 333238104Sdes ldns_buffer_free(b64sig); 334238104Sdes DSA_SIG_free(sig); 335238104Sdes return NULL; 336238104Sdes } 337238104Sdes 338238104Sdes data[0] = 1; 339238104Sdes pad = 20 - (size_t) BN_num_bytes(sig->r); 340238104Sdes if (pad > 0) { 341238104Sdes memset(data + 1, 0, pad); 342238104Sdes } 343238104Sdes BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad); 344238104Sdes 345238104Sdes pad = 20 - (size_t) BN_num_bytes(sig->s); 346238104Sdes if (pad > 0) { 347238104Sdes memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad); 348238104Sdes } 349238104Sdes BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad)); 350238104Sdes 351238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, 352238104Sdes 1 + 2 * SHA_DIGEST_LENGTH, 353238104Sdes data); 354238104Sdes 355238104Sdes ldns_buffer_free(b64sig); 356238104Sdes LDNS_FREE(data); 357238104Sdes DSA_SIG_free(sig); 358238104Sdes 359238104Sdes return sigdata_rdf; 360238104Sdes} 361238104Sdes 362238104Sdes#ifdef USE_ECDSA 363238104Sdes#ifndef S_SPLINT_S 364238104Sdesstatic int 365238104Sdesldns_pkey_is_ecdsa(EVP_PKEY* pkey) 366238104Sdes{ 367238104Sdes EC_KEY* ec; 368238104Sdes const EC_GROUP* g; 369238104Sdes if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) 370238104Sdes return 0; 371238104Sdes ec = EVP_PKEY_get1_EC_KEY(pkey); 372238104Sdes g = EC_KEY_get0_group(ec); 373238104Sdes if(!g) { 374238104Sdes EC_KEY_free(ec); 375238104Sdes return 0; 376238104Sdes } 377238104Sdes if(EC_GROUP_get_curve_name(g) == NID_secp224r1 || 378238104Sdes EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 || 379238104Sdes EC_GROUP_get_curve_name(g) == NID_secp384r1) { 380238104Sdes EC_KEY_free(ec); 381238104Sdes return 1; 382238104Sdes } 383238104Sdes /* downref the eckey, the original is still inside the pkey */ 384238104Sdes EC_KEY_free(ec); 385238104Sdes return 0; 386238104Sdes} 387238104Sdes#endif /* splint */ 388238104Sdes#endif /* USE_ECDSA */ 389238104Sdes 390238104Sdesldns_rdf * 391238104Sdesldns_sign_public_evp(ldns_buffer *to_sign, 392238104Sdes EVP_PKEY *key, 393238104Sdes const EVP_MD *digest_type) 394238104Sdes{ 395238104Sdes unsigned int siglen; 396238104Sdes ldns_rdf *sigdata_rdf; 397238104Sdes ldns_buffer *b64sig; 398238104Sdes EVP_MD_CTX ctx; 399238104Sdes const EVP_MD *md_type; 400238104Sdes int r; 401238104Sdes 402238104Sdes siglen = 0; 403238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 404238104Sdes if (!b64sig) { 405238104Sdes return NULL; 406238104Sdes } 407238104Sdes 408238104Sdes /* initializes a signing context */ 409238104Sdes md_type = digest_type; 410238104Sdes if(!md_type) { 411238104Sdes /* unknown message difest */ 412238104Sdes ldns_buffer_free(b64sig); 413238104Sdes return NULL; 414238104Sdes } 415238104Sdes 416238104Sdes EVP_MD_CTX_init(&ctx); 417238104Sdes r = EVP_SignInit(&ctx, md_type); 418238104Sdes if(r == 1) { 419238104Sdes r = EVP_SignUpdate(&ctx, (unsigned char*) 420238104Sdes ldns_buffer_begin(to_sign), 421238104Sdes ldns_buffer_position(to_sign)); 422238104Sdes } else { 423238104Sdes ldns_buffer_free(b64sig); 424238104Sdes return NULL; 425238104Sdes } 426238104Sdes if(r == 1) { 427238104Sdes r = EVP_SignFinal(&ctx, (unsigned char*) 428238104Sdes ldns_buffer_begin(b64sig), &siglen, key); 429238104Sdes } else { 430238104Sdes ldns_buffer_free(b64sig); 431238104Sdes return NULL; 432238104Sdes } 433238104Sdes if(r != 1) { 434238104Sdes ldns_buffer_free(b64sig); 435238104Sdes return NULL; 436238104Sdes } 437238104Sdes 438238104Sdes /* unfortunately, OpenSSL output is differenct from DNS DSA format */ 439238104Sdes#ifndef S_SPLINT_S 440238104Sdes if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { 441238104Sdes sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen); 442238104Sdes#ifdef USE_ECDSA 443238104Sdes } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC && 444238104Sdes ldns_pkey_is_ecdsa(key)) { 445238104Sdes sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen); 446238104Sdes#endif 447238104Sdes } else { 448238104Sdes /* ok output for other types is the same */ 449238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 450238104Sdes ldns_buffer_begin(b64sig)); 451238104Sdes } 452238104Sdes#endif /* splint */ 453238104Sdes ldns_buffer_free(b64sig); 454238104Sdes EVP_MD_CTX_cleanup(&ctx); 455238104Sdes return sigdata_rdf; 456238104Sdes} 457238104Sdes 458238104Sdesldns_rdf * 459238104Sdesldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) 460238104Sdes{ 461238104Sdes unsigned char *sha1_hash; 462238104Sdes unsigned int siglen; 463238104Sdes ldns_rdf *sigdata_rdf; 464238104Sdes ldns_buffer *b64sig; 465238104Sdes int result; 466238104Sdes 467238104Sdes siglen = 0; 468238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 469238104Sdes if (!b64sig) { 470238104Sdes return NULL; 471238104Sdes } 472238104Sdes 473238104Sdes sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), 474238104Sdes ldns_buffer_position(to_sign), NULL); 475238104Sdes if (!sha1_hash) { 476238104Sdes ldns_buffer_free(b64sig); 477238104Sdes return NULL; 478238104Sdes } 479238104Sdes 480238104Sdes result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, 481238104Sdes (unsigned char*)ldns_buffer_begin(b64sig), 482238104Sdes &siglen, key); 483238104Sdes if (result != 1) { 484238104Sdes return NULL; 485238104Sdes } 486238104Sdes 487238104Sdes if (result != 1) { 488238104Sdes return NULL; 489238104Sdes } 490238104Sdes 491238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 492238104Sdes ldns_buffer_begin(b64sig)); 493238104Sdes ldns_buffer_free(b64sig); /* can't free this buffer ?? */ 494238104Sdes return sigdata_rdf; 495238104Sdes} 496238104Sdes 497238104Sdesldns_rdf * 498238104Sdesldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) 499238104Sdes{ 500238104Sdes unsigned char *md5_hash; 501238104Sdes unsigned int siglen; 502238104Sdes ldns_rdf *sigdata_rdf; 503238104Sdes ldns_buffer *b64sig; 504238104Sdes 505238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 506238104Sdes if (!b64sig) { 507238104Sdes return NULL; 508238104Sdes } 509238104Sdes 510238104Sdes md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign), 511238104Sdes ldns_buffer_position(to_sign), NULL); 512238104Sdes if (!md5_hash) { 513238104Sdes ldns_buffer_free(b64sig); 514238104Sdes return NULL; 515238104Sdes } 516238104Sdes 517238104Sdes RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH, 518238104Sdes (unsigned char*)ldns_buffer_begin(b64sig), 519238104Sdes &siglen, key); 520238104Sdes 521238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 522238104Sdes ldns_buffer_begin(b64sig)); 523238104Sdes ldns_buffer_free(b64sig); 524238104Sdes return sigdata_rdf; 525238104Sdes} 526238104Sdes#endif /* HAVE_SSL */ 527238104Sdes 528238104Sdes/** 529238104Sdes * Pushes all rrs from the rrsets of type A and AAAA on gluelist. 530238104Sdes */ 531238104Sdesstatic ldns_status 532238104Sdesldns_dnssec_addresses_on_glue_list( 533238104Sdes ldns_dnssec_rrsets *cur_rrset, 534238104Sdes ldns_rr_list *glue_list) 535238104Sdes{ 536238104Sdes ldns_dnssec_rrs *cur_rrs; 537238104Sdes while (cur_rrset) { 538238104Sdes if (cur_rrset->type == LDNS_RR_TYPE_A 539238104Sdes || cur_rrset->type == LDNS_RR_TYPE_AAAA) { 540238104Sdes for (cur_rrs = cur_rrset->rrs; 541238104Sdes cur_rrs; 542238104Sdes cur_rrs = cur_rrs->next) { 543238104Sdes if (cur_rrs->rr) { 544238104Sdes if (!ldns_rr_list_push_rr(glue_list, 545238104Sdes cur_rrs->rr)) { 546238104Sdes return LDNS_STATUS_MEM_ERR; 547238104Sdes /* ldns_rr_list_push_rr() 548238104Sdes * returns false when unable 549238104Sdes * to increase the capacity 550238104Sdes * of the ldsn_rr_list 551238104Sdes */ 552238104Sdes } 553238104Sdes } 554238104Sdes } 555238104Sdes } 556238104Sdes cur_rrset = cur_rrset->next; 557238104Sdes } 558238104Sdes return LDNS_STATUS_OK; 559238104Sdes} 560238104Sdes 561238104Sdes/** 562238104Sdes * Marks the names in the zone that are occluded. Those names will be skipped 563238104Sdes * when walking the tree with the ldns_dnssec_name_node_next_nonglue() 564238104Sdes * function. But watch out! Names that are partially occluded (like glue with 565238104Sdes * the same name as the delegation) will not be marked and should specifically 566238104Sdes * be taken into account seperately. 567238104Sdes * 568238104Sdes * When glue_list is given (not NULL), in the process of marking the names, all 569238104Sdes * glue resource records will be pushed to that list, even glue at delegation names. 570238104Sdes * 571238104Sdes * \param[in] zone the zone in which to mark the names 572238104Sdes * \param[in] glue_list the list to which to push the glue rrs 573238104Sdes * \return LDNS_STATUS_OK on success, an error code otherwise 574238104Sdes */ 575238104Sdesldns_status 576238104Sdesldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, 577238104Sdes ldns_rr_list *glue_list) 578238104Sdes{ 579238104Sdes ldns_rbnode_t *node; 580238104Sdes ldns_dnssec_name *name; 581238104Sdes ldns_rdf *owner; 582238104Sdes ldns_rdf *cut = NULL; /* keeps track of zone cuts */ 583238104Sdes /* When the cut is caused by a delegation, below_delegation will be 1. 584238104Sdes * When caused by a DNAME, below_delegation will be 0. 585238104Sdes */ 586238104Sdes int below_delegation = -1; /* init suppresses comiler warning */ 587238104Sdes ldns_status s; 588238104Sdes 589238104Sdes if (!zone || !zone->names) { 590238104Sdes return LDNS_STATUS_NULL; 591238104Sdes } 592238104Sdes for (node = ldns_rbtree_first(zone->names); 593238104Sdes node != LDNS_RBTREE_NULL; 594238104Sdes node = ldns_rbtree_next(node)) { 595238104Sdes name = (ldns_dnssec_name *) node->data; 596238104Sdes owner = ldns_dnssec_name_name(name); 597238104Sdes 598238104Sdes if (cut) { 599238104Sdes /* The previous node was a zone cut, or a subdomain 600238104Sdes * below a zone cut. Is this node (still) a subdomain 601238104Sdes * below the cut? Then the name is occluded. Unless 602238104Sdes * the name contains a SOA, after which we are 603238104Sdes * authoritative again. 604238104Sdes * 605238104Sdes * FIXME! If there are labels in between the SOA and 606238104Sdes * the cut, going from the authoritative space (below 607238104Sdes * the SOA) up into occluded space again, will not be 608238104Sdes * detected with the contruct below! 609238104Sdes */ 610238104Sdes if (ldns_dname_is_subdomain(owner, cut) && 611238104Sdes !ldns_dnssec_rrsets_contains_type( 612238104Sdes name->rrsets, LDNS_RR_TYPE_SOA)) { 613238104Sdes 614238104Sdes if (below_delegation && glue_list) { 615238104Sdes s = ldns_dnssec_addresses_on_glue_list( 616238104Sdes name->rrsets, glue_list); 617238104Sdes if (s != LDNS_STATUS_OK) { 618238104Sdes return s; 619238104Sdes } 620238104Sdes } 621238104Sdes name->is_glue = true; /* Mark occluded name! */ 622238104Sdes continue; 623238104Sdes } else { 624238104Sdes cut = NULL; 625238104Sdes } 626238104Sdes } 627238104Sdes 628238104Sdes /* The node is not below a zone cut. Is it a zone cut itself? 629238104Sdes * Everything below a SOA is authoritative of course; Except 630238104Sdes * when the name also contains a DNAME :). 631238104Sdes */ 632238104Sdes if (ldns_dnssec_rrsets_contains_type( 633238104Sdes name->rrsets, LDNS_RR_TYPE_NS) 634238104Sdes && !ldns_dnssec_rrsets_contains_type( 635238104Sdes name->rrsets, LDNS_RR_TYPE_SOA)) { 636238104Sdes cut = owner; 637238104Sdes below_delegation = 1; 638238104Sdes if (glue_list) { /* record glue on the zone cut */ 639238104Sdes s = ldns_dnssec_addresses_on_glue_list( 640238104Sdes name->rrsets, glue_list); 641238104Sdes if (s != LDNS_STATUS_OK) { 642238104Sdes return s; 643238104Sdes } 644238104Sdes } 645238104Sdes } else if (ldns_dnssec_rrsets_contains_type( 646238104Sdes name->rrsets, LDNS_RR_TYPE_DNAME)) { 647238104Sdes cut = owner; 648238104Sdes below_delegation = 0; 649238104Sdes } 650238104Sdes } 651238104Sdes return LDNS_STATUS_OK; 652238104Sdes} 653238104Sdes 654238104Sdes/** 655238104Sdes * Marks the names in the zone that are occluded. Those names will be skipped 656238104Sdes * when walking the tree with the ldns_dnssec_name_node_next_nonglue() 657238104Sdes * function. But watch out! Names that are partially occluded (like glue with 658238104Sdes * the same name as the delegation) will not be marked and should specifically 659238104Sdes * be taken into account seperately. 660238104Sdes * 661238104Sdes * \param[in] zone the zone in which to mark the names 662238104Sdes * \return LDNS_STATUS_OK on success, an error code otherwise 663238104Sdes */ 664238104Sdesldns_status 665238104Sdesldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone) 666238104Sdes{ 667238104Sdes return ldns_dnssec_zone_mark_and_get_glue(zone, NULL); 668238104Sdes} 669238104Sdes 670238104Sdesldns_rbnode_t * 671238104Sdesldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node) 672238104Sdes{ 673238104Sdes ldns_rbnode_t *next_node = NULL; 674238104Sdes ldns_dnssec_name *next_name = NULL; 675238104Sdes bool done = false; 676238104Sdes 677238104Sdes if (node == LDNS_RBTREE_NULL) { 678238104Sdes return NULL; 679238104Sdes } 680238104Sdes next_node = node; 681238104Sdes while (!done) { 682238104Sdes if (next_node == LDNS_RBTREE_NULL) { 683238104Sdes return NULL; 684238104Sdes } else { 685238104Sdes next_name = (ldns_dnssec_name *)next_node->data; 686238104Sdes if (!next_name->is_glue) { 687238104Sdes done = true; 688238104Sdes } else { 689238104Sdes next_node = ldns_rbtree_next(next_node); 690238104Sdes } 691238104Sdes } 692238104Sdes } 693238104Sdes return next_node; 694238104Sdes} 695238104Sdes 696238104Sdesldns_status 697238104Sdesldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, 698238104Sdes ldns_rr_list *new_rrs) 699238104Sdes{ 700238104Sdes 701238104Sdes ldns_rbnode_t *first_node, *cur_node, *next_node; 702238104Sdes ldns_dnssec_name *cur_name, *next_name; 703238104Sdes ldns_rr *nsec_rr; 704238104Sdes uint32_t nsec_ttl; 705238104Sdes ldns_dnssec_rrsets *soa; 706238104Sdes 707238104Sdes /* the TTL of NSEC rrs should be set to the minimum TTL of 708238104Sdes * the zone SOA (RFC4035 Section 2.3) 709238104Sdes */ 710238104Sdes soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); 711238104Sdes 712238104Sdes /* did the caller actually set it? if not, 713238104Sdes * fall back to default ttl 714238104Sdes */ 715238104Sdes if (soa && soa->rrs && soa->rrs->rr 716238104Sdes && (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) { 717238104Sdes nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); 718238104Sdes } else { 719238104Sdes nsec_ttl = LDNS_DEFAULT_TTL; 720238104Sdes } 721238104Sdes 722238104Sdes first_node = ldns_dnssec_name_node_next_nonglue( 723238104Sdes ldns_rbtree_first(zone->names)); 724238104Sdes cur_node = first_node; 725238104Sdes if (cur_node) { 726238104Sdes next_node = ldns_dnssec_name_node_next_nonglue( 727238104Sdes ldns_rbtree_next(cur_node)); 728238104Sdes } else { 729238104Sdes next_node = NULL; 730238104Sdes } 731238104Sdes 732238104Sdes while (cur_node && next_node) { 733238104Sdes cur_name = (ldns_dnssec_name *)cur_node->data; 734238104Sdes next_name = (ldns_dnssec_name *)next_node->data; 735238104Sdes nsec_rr = ldns_dnssec_create_nsec(cur_name, 736238104Sdes next_name, 737238104Sdes LDNS_RR_TYPE_NSEC); 738238104Sdes ldns_rr_set_ttl(nsec_rr, nsec_ttl); 739238104Sdes if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ 740238104Sdes ldns_rr_free(nsec_rr); 741238104Sdes return LDNS_STATUS_ERR; 742238104Sdes } 743238104Sdes ldns_rr_list_push_rr(new_rrs, nsec_rr); 744238104Sdes cur_node = next_node; 745238104Sdes if (cur_node) { 746238104Sdes next_node = ldns_dnssec_name_node_next_nonglue( 747238104Sdes ldns_rbtree_next(cur_node)); 748238104Sdes } 749238104Sdes } 750238104Sdes 751238104Sdes if (cur_node && !next_node) { 752238104Sdes cur_name = (ldns_dnssec_name *)cur_node->data; 753238104Sdes next_name = (ldns_dnssec_name *)first_node->data; 754238104Sdes nsec_rr = ldns_dnssec_create_nsec(cur_name, 755238104Sdes next_name, 756238104Sdes LDNS_RR_TYPE_NSEC); 757238104Sdes ldns_rr_set_ttl(nsec_rr, nsec_ttl); 758238104Sdes if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ 759238104Sdes ldns_rr_free(nsec_rr); 760238104Sdes return LDNS_STATUS_ERR; 761238104Sdes } 762238104Sdes ldns_rr_list_push_rr(new_rrs, nsec_rr); 763238104Sdes } else { 764238104Sdes printf("error\n"); 765238104Sdes } 766238104Sdes 767238104Sdes return LDNS_STATUS_OK; 768238104Sdes} 769238104Sdes 770238104Sdes#ifdef HAVE_SSL 771238104Sdes/* in dnssec_zone.c */ 772238104Sdesextern int ldns_dname_compare_v(const void *a, const void *b); 773238104Sdes 774246827Sdesstatic ldns_status 775238104Sdesldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, 776238104Sdes ldns_rr_list *new_rrs, 777238104Sdes uint8_t algorithm, 778238104Sdes uint8_t flags, 779238104Sdes uint16_t iterations, 780238104Sdes uint8_t salt_length, 781238104Sdes uint8_t *salt, 782238104Sdes ldns_rbtree_t **map) 783238104Sdes{ 784238104Sdes ldns_rbnode_t *first_name_node; 785238104Sdes ldns_rbnode_t *current_name_node; 786238104Sdes ldns_dnssec_name *current_name; 787238104Sdes ldns_status result = LDNS_STATUS_OK; 788238104Sdes ldns_rr *nsec_rr; 789238104Sdes ldns_rr_list *nsec3_list; 790238104Sdes uint32_t nsec_ttl; 791238104Sdes ldns_dnssec_rrsets *soa; 792238104Sdes ldns_rbnode_t *hashmap_node; 793238104Sdes 794238104Sdes if (!zone || !new_rrs || !zone->names) { 795238104Sdes return LDNS_STATUS_ERR; 796238104Sdes } 797238104Sdes 798238104Sdes /* the TTL of NSEC rrs should be set to the minimum TTL of 799238104Sdes * the zone SOA (RFC4035 Section 2.3) 800238104Sdes */ 801238104Sdes soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); 802238104Sdes 803238104Sdes /* did the caller actually set it? if not, 804238104Sdes * fall back to default ttl 805238104Sdes */ 806238104Sdes if (soa && soa->rrs && soa->rrs->rr 807238104Sdes && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) { 808238104Sdes nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); 809238104Sdes } else { 810238104Sdes nsec_ttl = LDNS_DEFAULT_TTL; 811238104Sdes } 812238104Sdes 813238104Sdes if (map) { 814238104Sdes if ((*map = ldns_rbtree_create(ldns_dname_compare_v)) 815238104Sdes == NULL) { 816238104Sdes map = NULL; 817238104Sdes }; 818238104Sdes } 819238104Sdes nsec3_list = ldns_rr_list_new(); 820238104Sdes 821238104Sdes first_name_node = ldns_dnssec_name_node_next_nonglue( 822238104Sdes ldns_rbtree_first(zone->names)); 823238104Sdes 824238104Sdes current_name_node = first_name_node; 825238104Sdes 826238104Sdes while (current_name_node && 827238104Sdes current_name_node != LDNS_RBTREE_NULL) { 828238104Sdes current_name = (ldns_dnssec_name *) current_name_node->data; 829238104Sdes nsec_rr = ldns_dnssec_create_nsec3(current_name, 830238104Sdes NULL, 831238104Sdes zone->soa->name, 832238104Sdes algorithm, 833238104Sdes flags, 834238104Sdes iterations, 835238104Sdes salt_length, 836238104Sdes salt); 837238104Sdes /* by default, our nsec based generator adds rrsigs 838238104Sdes * remove the bitmap for empty nonterminals */ 839238104Sdes if (!current_name->rrsets) { 840238104Sdes ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr)); 841238104Sdes } 842238104Sdes ldns_rr_set_ttl(nsec_rr, nsec_ttl); 843238104Sdes result = ldns_dnssec_name_add_rr(current_name, nsec_rr); 844238104Sdes ldns_rr_list_push_rr(new_rrs, nsec_rr); 845238104Sdes ldns_rr_list_push_rr(nsec3_list, nsec_rr); 846238104Sdes if (map) { 847238104Sdes hashmap_node = LDNS_MALLOC(ldns_rbnode_t); 848238104Sdes if (hashmap_node && ldns_rr_owner(nsec_rr)) { 849238104Sdes hashmap_node->key = ldns_dname_label( 850238104Sdes ldns_rr_owner(nsec_rr), 0); 851238104Sdes if (hashmap_node->key) { 852238104Sdes hashmap_node->data = current_name->name; 853238104Sdes (void) ldns_rbtree_insert( 854238104Sdes *map, hashmap_node); 855238104Sdes } 856238104Sdes } 857238104Sdes } 858238104Sdes current_name_node = ldns_dnssec_name_node_next_nonglue( 859238104Sdes ldns_rbtree_next(current_name_node)); 860238104Sdes } 861238104Sdes if (result != LDNS_STATUS_OK) { 862238104Sdes return result; 863238104Sdes } 864238104Sdes 865238104Sdes ldns_rr_list_sort_nsec3(nsec3_list); 866238104Sdes result = ldns_dnssec_chain_nsec3_list(nsec3_list); 867238104Sdes if (result != LDNS_STATUS_OK) { 868238104Sdes return result; 869238104Sdes } 870238104Sdes 871238104Sdes ldns_rr_list_free(nsec3_list); 872238104Sdes return result; 873238104Sdes} 874238104Sdes 875238104Sdesldns_status 876238104Sdesldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, 877238104Sdes ldns_rr_list *new_rrs, 878238104Sdes uint8_t algorithm, 879238104Sdes uint8_t flags, 880238104Sdes uint16_t iterations, 881238104Sdes uint8_t salt_length, 882238104Sdes uint8_t *salt) 883238104Sdes{ 884238104Sdes return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm, 885238104Sdes flags, iterations, salt_length, salt, NULL); 886238104Sdes 887238104Sdes} 888238104Sdes#endif /* HAVE_SSL */ 889238104Sdes 890238104Sdesldns_dnssec_rrs * 891238104Sdesldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures 892238104Sdes , ATTR_UNUSED(ldns_key_list *key_list) 893238104Sdes , int (*func)(ldns_rr *, void *) 894238104Sdes , void *arg 895238104Sdes ) 896238104Sdes{ 897238104Sdes ldns_dnssec_rrs *base_rrs = signatures; 898238104Sdes ldns_dnssec_rrs *cur_rr = base_rrs; 899238104Sdes ldns_dnssec_rrs *prev_rr = NULL; 900238104Sdes ldns_dnssec_rrs *next_rr; 901238104Sdes 902238104Sdes uint16_t keytag; 903238104Sdes size_t i; 904238104Sdes 905238104Sdes if (!cur_rr) { 906238104Sdes switch(func(NULL, arg)) { 907238104Sdes case LDNS_SIGNATURE_LEAVE_ADD_NEW: 908238104Sdes case LDNS_SIGNATURE_REMOVE_ADD_NEW: 909238104Sdes break; 910238104Sdes case LDNS_SIGNATURE_LEAVE_NO_ADD: 911238104Sdes case LDNS_SIGNATURE_REMOVE_NO_ADD: 912238104Sdes ldns_key_list_set_use(key_list, false); 913238104Sdes break; 914238104Sdes default: 915238104Sdes fprintf(stderr, "[XX] unknown return value from callback\n"); 916238104Sdes break; 917238104Sdes } 918238104Sdes return NULL; 919238104Sdes } 920238104Sdes (void)func(cur_rr->rr, arg); 921238104Sdes 922238104Sdes while (cur_rr) { 923238104Sdes next_rr = cur_rr->next; 924238104Sdes 925238104Sdes switch (func(cur_rr->rr, arg)) { 926238104Sdes case LDNS_SIGNATURE_LEAVE_ADD_NEW: 927238104Sdes prev_rr = cur_rr; 928238104Sdes break; 929238104Sdes case LDNS_SIGNATURE_LEAVE_NO_ADD: 930238104Sdes keytag = ldns_rdf2native_int16( 931238104Sdes ldns_rr_rrsig_keytag(cur_rr->rr)); 932238104Sdes for (i = 0; i < ldns_key_list_key_count(key_list); i++) { 933238104Sdes if (ldns_key_keytag(ldns_key_list_key(key_list, i)) == 934238104Sdes keytag) { 935238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 936238104Sdes false); 937238104Sdes } 938238104Sdes } 939238104Sdes prev_rr = cur_rr; 940238104Sdes break; 941238104Sdes case LDNS_SIGNATURE_REMOVE_NO_ADD: 942238104Sdes keytag = ldns_rdf2native_int16( 943238104Sdes ldns_rr_rrsig_keytag(cur_rr->rr)); 944238104Sdes for (i = 0; i < ldns_key_list_key_count(key_list); i++) { 945238104Sdes if (ldns_key_keytag(ldns_key_list_key(key_list, i)) 946238104Sdes == keytag) { 947238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 948238104Sdes false); 949238104Sdes } 950238104Sdes } 951238104Sdes if (prev_rr) { 952238104Sdes prev_rr->next = next_rr; 953238104Sdes } else { 954238104Sdes base_rrs = next_rr; 955238104Sdes } 956238104Sdes LDNS_FREE(cur_rr); 957238104Sdes break; 958238104Sdes case LDNS_SIGNATURE_REMOVE_ADD_NEW: 959238104Sdes if (prev_rr) { 960238104Sdes prev_rr->next = next_rr; 961238104Sdes } else { 962238104Sdes base_rrs = next_rr; 963238104Sdes } 964238104Sdes LDNS_FREE(cur_rr); 965238104Sdes break; 966238104Sdes default: 967238104Sdes fprintf(stderr, "[XX] unknown return value from callback\n"); 968238104Sdes break; 969238104Sdes } 970238104Sdes cur_rr = next_rr; 971238104Sdes } 972238104Sdes 973238104Sdes return base_rrs; 974238104Sdes} 975238104Sdes 976238104Sdes#ifdef HAVE_SSL 977238104Sdesldns_status 978238104Sdesldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, 979238104Sdes ldns_rr_list *new_rrs, 980238104Sdes ldns_key_list *key_list, 981238104Sdes int (*func)(ldns_rr *, void*), 982238104Sdes void *arg) 983238104Sdes{ 984238104Sdes return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, 985238104Sdes func, arg, 0); 986238104Sdes} 987238104Sdes 988238104Sdes/** If there are KSKs use only them and mark ZSKs unused */ 989238104Sdesstatic void 990238104Sdesldns_key_list_filter_for_dnskey(ldns_key_list *key_list) 991238104Sdes{ 992238104Sdes int saw_ksk = 0; 993238104Sdes size_t i; 994238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 995238104Sdes if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) { 996238104Sdes saw_ksk = 1; 997238104Sdes break; 998238104Sdes } 999238104Sdes if(!saw_ksk) 1000238104Sdes return; 1001238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1002238104Sdes if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) 1003238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 0); 1004238104Sdes} 1005238104Sdes 1006238104Sdes/** If there are no ZSKs use KSK as ZSK */ 1007238104Sdesstatic void 1008238104Sdesldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list) 1009238104Sdes{ 1010238104Sdes int saw_zsk = 0; 1011238104Sdes size_t i; 1012238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1013238104Sdes if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) { 1014238104Sdes saw_zsk = 1; 1015238104Sdes break; 1016238104Sdes } 1017238104Sdes if(!saw_zsk) 1018238104Sdes return; 1019238104Sdes /* else filter all KSKs */ 1020238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1021238104Sdes if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) 1022238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 0); 1023238104Sdes} 1024238104Sdes 1025238104Sdesldns_status 1026238104Sdesldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) 1027238104Sdes , ATTR_UNUSED(ldns_rr_list *new_rrs) 1028238104Sdes , ATTR_UNUSED(ldns_key_list *key_list) 1029238104Sdes , int (*func)(ldns_rr *, void*) 1030238104Sdes , void *arg 1031238104Sdes , int flags 1032238104Sdes ) 1033238104Sdes{ 1034238104Sdes ldns_status result = LDNS_STATUS_OK; 1035238104Sdes 1036238104Sdes ldns_rbnode_t *cur_node; 1037238104Sdes ldns_rr_list *rr_list; 1038238104Sdes 1039238104Sdes ldns_dnssec_name *cur_name; 1040238104Sdes ldns_dnssec_rrsets *cur_rrset; 1041238104Sdes ldns_dnssec_rrs *cur_rr; 1042238104Sdes 1043238104Sdes ldns_rr_list *siglist; 1044238104Sdes 1045238104Sdes size_t i; 1046238104Sdes 1047238104Sdes int on_delegation_point = 0; /* handle partially occluded names */ 1048238104Sdes 1049238104Sdes ldns_rr_list *pubkey_list = ldns_rr_list_new(); 1050238104Sdes for (i = 0; i<ldns_key_list_key_count(key_list); i++) { 1051238104Sdes ldns_rr_list_push_rr( pubkey_list 1052238104Sdes , ldns_key2rr(ldns_key_list_key( 1053238104Sdes key_list, i)) 1054238104Sdes ); 1055238104Sdes } 1056238104Sdes /* TODO: callback to see is list should be signed */ 1057238104Sdes /* TODO: remove 'old' signatures from signature list */ 1058238104Sdes cur_node = ldns_rbtree_first(zone->names); 1059238104Sdes while (cur_node != LDNS_RBTREE_NULL) { 1060238104Sdes cur_name = (ldns_dnssec_name *) cur_node->data; 1061238104Sdes 1062238104Sdes if (!cur_name->is_glue) { 1063238104Sdes on_delegation_point = ldns_dnssec_rrsets_contains_type( 1064238104Sdes cur_name->rrsets, LDNS_RR_TYPE_NS) 1065238104Sdes && !ldns_dnssec_rrsets_contains_type( 1066238104Sdes cur_name->rrsets, LDNS_RR_TYPE_SOA); 1067238104Sdes cur_rrset = cur_name->rrsets; 1068238104Sdes while (cur_rrset) { 1069238104Sdes /* reset keys to use */ 1070238104Sdes ldns_key_list_set_use(key_list, true); 1071238104Sdes 1072238104Sdes /* walk through old sigs, remove the old, 1073238104Sdes and mark which keys (not) to use) */ 1074238104Sdes cur_rrset->signatures = 1075238104Sdes ldns_dnssec_remove_signatures(cur_rrset->signatures, 1076238104Sdes key_list, 1077238104Sdes func, 1078238104Sdes arg); 1079238104Sdes if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) && 1080238104Sdes cur_rrset->type == LDNS_RR_TYPE_DNSKEY) 1081238104Sdes ldns_key_list_filter_for_dnskey(key_list); 1082238104Sdes 1083238104Sdes if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY) 1084238104Sdes ldns_key_list_filter_for_non_dnskey(key_list); 1085238104Sdes 1086238104Sdes /* TODO: just set count to zero? */ 1087238104Sdes rr_list = ldns_rr_list_new(); 1088238104Sdes 1089238104Sdes cur_rr = cur_rrset->rrs; 1090238104Sdes while (cur_rr) { 1091238104Sdes ldns_rr_list_push_rr(rr_list, cur_rr->rr); 1092238104Sdes cur_rr = cur_rr->next; 1093238104Sdes } 1094238104Sdes 1095238104Sdes /* only sign non-delegation RRsets */ 1096238104Sdes /* (glue should have been marked earlier, 1097238104Sdes * except on the delegation points itself) */ 1098238104Sdes if (!on_delegation_point || 1099238104Sdes ldns_rr_list_type(rr_list) 1100238104Sdes == LDNS_RR_TYPE_DS || 1101238104Sdes ldns_rr_list_type(rr_list) 1102238104Sdes == LDNS_RR_TYPE_NSEC || 1103238104Sdes ldns_rr_list_type(rr_list) 1104238104Sdes == LDNS_RR_TYPE_NSEC3) { 1105238104Sdes siglist = ldns_sign_public(rr_list, key_list); 1106238104Sdes for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { 1107238104Sdes if (cur_rrset->signatures) { 1108238104Sdes result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures, 1109238104Sdes ldns_rr_list_rr(siglist, 1110238104Sdes i)); 1111238104Sdes } else { 1112238104Sdes cur_rrset->signatures = ldns_dnssec_rrs_new(); 1113238104Sdes cur_rrset->signatures->rr = 1114238104Sdes ldns_rr_list_rr(siglist, i); 1115238104Sdes ldns_rr_list_push_rr(new_rrs, 1116238104Sdes ldns_rr_list_rr(siglist, 1117238104Sdes i)); 1118238104Sdes } 1119238104Sdes } 1120238104Sdes ldns_rr_list_free(siglist); 1121238104Sdes } 1122238104Sdes 1123238104Sdes ldns_rr_list_free(rr_list); 1124238104Sdes 1125238104Sdes cur_rrset = cur_rrset->next; 1126238104Sdes } 1127238104Sdes 1128238104Sdes /* sign the nsec */ 1129238104Sdes ldns_key_list_set_use(key_list, true); 1130238104Sdes cur_name->nsec_signatures = 1131238104Sdes ldns_dnssec_remove_signatures(cur_name->nsec_signatures, 1132238104Sdes key_list, 1133238104Sdes func, 1134238104Sdes arg); 1135238104Sdes ldns_key_list_filter_for_non_dnskey(key_list); 1136238104Sdes 1137238104Sdes rr_list = ldns_rr_list_new(); 1138238104Sdes ldns_rr_list_push_rr(rr_list, cur_name->nsec); 1139238104Sdes siglist = ldns_sign_public(rr_list, key_list); 1140238104Sdes 1141238104Sdes for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { 1142238104Sdes if (cur_name->nsec_signatures) { 1143238104Sdes result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, 1144238104Sdes ldns_rr_list_rr(siglist, i)); 1145238104Sdes } else { 1146238104Sdes cur_name->nsec_signatures = ldns_dnssec_rrs_new(); 1147238104Sdes cur_name->nsec_signatures->rr = 1148238104Sdes ldns_rr_list_rr(siglist, i); 1149238104Sdes ldns_rr_list_push_rr(new_rrs, 1150238104Sdes ldns_rr_list_rr(siglist, i)); 1151238104Sdes } 1152238104Sdes } 1153238104Sdes 1154238104Sdes ldns_rr_list_free(siglist); 1155238104Sdes ldns_rr_list_free(rr_list); 1156238104Sdes } 1157238104Sdes cur_node = ldns_rbtree_next(cur_node); 1158238104Sdes } 1159238104Sdes 1160238104Sdes ldns_rr_list_deep_free(pubkey_list); 1161238104Sdes return result; 1162238104Sdes} 1163238104Sdes 1164238104Sdesldns_status 1165238104Sdesldns_dnssec_zone_sign(ldns_dnssec_zone *zone, 1166238104Sdes ldns_rr_list *new_rrs, 1167238104Sdes ldns_key_list *key_list, 1168238104Sdes int (*func)(ldns_rr *, void *), 1169238104Sdes void *arg) 1170238104Sdes{ 1171238104Sdes return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0); 1172238104Sdes} 1173238104Sdes 1174238104Sdesldns_status 1175238104Sdesldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, 1176238104Sdes ldns_rr_list *new_rrs, 1177238104Sdes ldns_key_list *key_list, 1178238104Sdes int (*func)(ldns_rr *, void *), 1179238104Sdes void *arg, 1180238104Sdes int flags) 1181238104Sdes{ 1182238104Sdes ldns_status result = LDNS_STATUS_OK; 1183238104Sdes 1184238104Sdes if (!zone || !new_rrs || !key_list) { 1185238104Sdes return LDNS_STATUS_ERR; 1186238104Sdes } 1187238104Sdes 1188238104Sdes /* zone is already sorted */ 1189238104Sdes result = ldns_dnssec_zone_mark_glue(zone); 1190238104Sdes if (result != LDNS_STATUS_OK) { 1191238104Sdes return result; 1192238104Sdes } 1193238104Sdes 1194238104Sdes /* check whether we need to add nsecs */ 1195238104Sdes if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { 1196238104Sdes result = ldns_dnssec_zone_create_nsecs(zone, new_rrs); 1197238104Sdes if (result != LDNS_STATUS_OK) { 1198238104Sdes return result; 1199238104Sdes } 1200238104Sdes } 1201238104Sdes 1202238104Sdes result = ldns_dnssec_zone_create_rrsigs_flg(zone, 1203238104Sdes new_rrs, 1204238104Sdes key_list, 1205238104Sdes func, 1206238104Sdes arg, 1207238104Sdes flags); 1208238104Sdes 1209238104Sdes return result; 1210238104Sdes} 1211238104Sdes 1212238104Sdesldns_status 1213238104Sdesldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, 1214238104Sdes ldns_rr_list *new_rrs, 1215238104Sdes ldns_key_list *key_list, 1216238104Sdes int (*func)(ldns_rr *, void *), 1217238104Sdes void *arg, 1218238104Sdes uint8_t algorithm, 1219238104Sdes uint8_t flags, 1220238104Sdes uint16_t iterations, 1221238104Sdes uint8_t salt_length, 1222238104Sdes uint8_t *salt) 1223238104Sdes{ 1224238104Sdes return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, 1225238104Sdes func, arg, algorithm, flags, iterations, salt_length, salt, 0, 1226238104Sdes NULL); 1227238104Sdes} 1228238104Sdes 1229238104Sdesldns_status 1230238104Sdesldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, 1231238104Sdes ldns_rr_list *new_rrs, 1232238104Sdes ldns_key_list *key_list, 1233238104Sdes int (*func)(ldns_rr *, void *), 1234238104Sdes void *arg, 1235238104Sdes uint8_t algorithm, 1236238104Sdes uint8_t flags, 1237238104Sdes uint16_t iterations, 1238238104Sdes uint8_t salt_length, 1239238104Sdes uint8_t *salt, 1240238104Sdes int signflags, 1241238104Sdes ldns_rbtree_t **map) 1242238104Sdes{ 1243238104Sdes ldns_rr *nsec3, *nsec3param; 1244238104Sdes ldns_status result = LDNS_STATUS_OK; 1245238104Sdes 1246238104Sdes /* zone is already sorted */ 1247238104Sdes result = ldns_dnssec_zone_mark_glue(zone); 1248238104Sdes if (result != LDNS_STATUS_OK) { 1249238104Sdes return result; 1250238104Sdes } 1251238104Sdes 1252238104Sdes /* TODO if there are already nsec3s presents and their 1253238104Sdes * parameters are the same as these, we don't have to recreate 1254238104Sdes */ 1255238104Sdes if (zone->names) { 1256238104Sdes /* add empty nonterminals */ 1257238104Sdes result = ldns_dnssec_zone_add_empty_nonterminals(zone); 1258238104Sdes if (result != LDNS_STATUS_OK) { 1259238104Sdes return result; 1260238104Sdes } 1261238104Sdes 1262238104Sdes nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec; 1263238104Sdes if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) { 1264238104Sdes /* no need to recreate */ 1265238104Sdes } else { 1266238104Sdes if (!ldns_dnssec_zone_find_rrset(zone, 1267238104Sdes zone->soa->name, 1268238104Sdes LDNS_RR_TYPE_NSEC3PARAM)) { 1269238104Sdes /* create and add the nsec3param rr */ 1270238104Sdes nsec3param = 1271238104Sdes ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM); 1272238104Sdes ldns_rr_set_owner(nsec3param, 1273238104Sdes ldns_rdf_clone(zone->soa->name)); 1274238104Sdes ldns_nsec3_add_param_rdfs(nsec3param, 1275238104Sdes algorithm, 1276238104Sdes flags, 1277238104Sdes iterations, 1278238104Sdes salt_length, 1279238104Sdes salt); 1280238104Sdes /* always set bit 7 of the flags to zero, according to 1281238104Sdes * rfc5155 section 11. The bits are counted from right to left, 1282238104Sdes * so bit 7 in rfc5155 is bit 0 in ldns */ 1283238104Sdes ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0); 1284238104Sdes result = ldns_dnssec_zone_add_rr(zone, nsec3param); 1285238104Sdes if (result != LDNS_STATUS_OK) { 1286238104Sdes return result; 1287238104Sdes } 1288238104Sdes ldns_rr_list_push_rr(new_rrs, nsec3param); 1289238104Sdes } 1290238104Sdes result = ldns_dnssec_zone_create_nsec3s_mkmap(zone, 1291238104Sdes new_rrs, 1292238104Sdes algorithm, 1293238104Sdes flags, 1294238104Sdes iterations, 1295238104Sdes salt_length, 1296238104Sdes salt, 1297238104Sdes map); 1298238104Sdes if (result != LDNS_STATUS_OK) { 1299238104Sdes return result; 1300238104Sdes } 1301238104Sdes } 1302238104Sdes 1303238104Sdes result = ldns_dnssec_zone_create_rrsigs_flg(zone, 1304238104Sdes new_rrs, 1305238104Sdes key_list, 1306238104Sdes func, 1307238104Sdes arg, 1308238104Sdes signflags); 1309238104Sdes } 1310238104Sdes 1311238104Sdes return result; 1312238104Sdes} 1313238104Sdes 1314238104Sdesldns_status 1315238104Sdesldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, 1316238104Sdes ldns_rr_list *new_rrs, 1317238104Sdes ldns_key_list *key_list, 1318238104Sdes int (*func)(ldns_rr *, void *), 1319238104Sdes void *arg, 1320238104Sdes uint8_t algorithm, 1321238104Sdes uint8_t flags, 1322238104Sdes uint16_t iterations, 1323238104Sdes uint8_t salt_length, 1324238104Sdes uint8_t *salt, 1325238104Sdes int signflags) 1326238104Sdes{ 1327238104Sdes return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, 1328238104Sdes func, arg, algorithm, flags, iterations, salt_length, salt, 1329238104Sdes signflags, NULL); 1330238104Sdes} 1331238104Sdes 1332238104Sdesldns_zone * 1333238104Sdesldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) 1334238104Sdes{ 1335238104Sdes ldns_dnssec_zone *dnssec_zone; 1336238104Sdes ldns_zone *signed_zone; 1337238104Sdes ldns_rr_list *new_rrs; 1338238104Sdes size_t i; 1339238104Sdes 1340238104Sdes signed_zone = ldns_zone_new(); 1341238104Sdes dnssec_zone = ldns_dnssec_zone_new(); 1342238104Sdes 1343238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); 1344238104Sdes ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); 1345238104Sdes 1346238104Sdes for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 1347238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, 1348238104Sdes ldns_rr_list_rr(ldns_zone_rrs(zone), 1349238104Sdes i)); 1350238104Sdes ldns_zone_push_rr(signed_zone, 1351238104Sdes ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), 1352238104Sdes i))); 1353238104Sdes } 1354238104Sdes 1355238104Sdes new_rrs = ldns_rr_list_new(); 1356238104Sdes (void) ldns_dnssec_zone_sign(dnssec_zone, 1357238104Sdes new_rrs, 1358238104Sdes key_list, 1359238104Sdes ldns_dnssec_default_replace_signatures, 1360238104Sdes NULL); 1361238104Sdes 1362238104Sdes for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { 1363238104Sdes ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), 1364238104Sdes ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); 1365238104Sdes } 1366238104Sdes 1367238104Sdes ldns_rr_list_deep_free(new_rrs); 1368238104Sdes ldns_dnssec_zone_free(dnssec_zone); 1369238104Sdes 1370238104Sdes return signed_zone; 1371238104Sdes} 1372238104Sdes 1373238104Sdesldns_zone * 1374238104Sdesldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt) 1375238104Sdes{ 1376238104Sdes ldns_dnssec_zone *dnssec_zone; 1377238104Sdes ldns_zone *signed_zone; 1378238104Sdes ldns_rr_list *new_rrs; 1379238104Sdes size_t i; 1380238104Sdes 1381238104Sdes signed_zone = ldns_zone_new(); 1382238104Sdes dnssec_zone = ldns_dnssec_zone_new(); 1383238104Sdes 1384238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); 1385238104Sdes ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); 1386238104Sdes 1387238104Sdes for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 1388238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, 1389238104Sdes ldns_rr_list_rr(ldns_zone_rrs(zone), 1390238104Sdes i)); 1391238104Sdes ldns_zone_push_rr(signed_zone, 1392238104Sdes ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), 1393238104Sdes i))); 1394238104Sdes } 1395238104Sdes 1396238104Sdes new_rrs = ldns_rr_list_new(); 1397238104Sdes (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone, 1398238104Sdes new_rrs, 1399238104Sdes key_list, 1400238104Sdes ldns_dnssec_default_replace_signatures, 1401238104Sdes NULL, 1402238104Sdes algorithm, 1403238104Sdes flags, 1404238104Sdes iterations, 1405238104Sdes salt_length, 1406238104Sdes salt); 1407238104Sdes 1408238104Sdes for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { 1409238104Sdes ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), 1410238104Sdes ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); 1411238104Sdes } 1412238104Sdes 1413238104Sdes ldns_rr_list_deep_free(new_rrs); 1414238104Sdes ldns_dnssec_zone_free(dnssec_zone); 1415238104Sdes 1416238104Sdes return signed_zone; 1417238104Sdes} 1418238104Sdes#endif /* HAVE_SSL */ 1419238104Sdes 1420238104Sdes 1421