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); 263246854Sdes ldns_rr_free(current_sig); 264246854Sdes ldns_rr_list_deep_free(signatures); 265238104Sdes return NULL; 266238104Sdes } 267238104Sdes 268238104Sdes /* add the rrset in sign_buf */ 269238104Sdes if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone) 270238104Sdes != LDNS_STATUS_OK) { 271238104Sdes ldns_buffer_free(sign_buf); 272238104Sdes ldns_rr_list_deep_free(rrset_clone); 273246854Sdes ldns_rr_free(current_sig); 274246854Sdes ldns_rr_list_deep_free(signatures); 275238104Sdes return NULL; 276238104Sdes } 277238104Sdes 278238104Sdes b64rdf = ldns_sign_public_buffer(sign_buf, current_key); 279238104Sdes 280238104Sdes if (!b64rdf) { 281238104Sdes /* signing went wrong */ 282238104Sdes ldns_rr_list_deep_free(rrset_clone); 283246854Sdes ldns_rr_free(current_sig); 284246854Sdes ldns_rr_list_deep_free(signatures); 285238104Sdes return NULL; 286238104Sdes } 287238104Sdes 288238104Sdes ldns_rr_rrsig_set_sig(current_sig, b64rdf); 289238104Sdes 290238104Sdes /* push the signature to the signatures list */ 291238104Sdes ldns_rr_list_push_rr(signatures, current_sig); 292238104Sdes } 293238104Sdes ldns_buffer_free(sign_buf); /* restart for the next key */ 294238104Sdes } 295238104Sdes ldns_rr_list_deep_free(rrset_clone); 296238104Sdes 297238104Sdes return signatures; 298238104Sdes} 299238104Sdes 300238104Sdes/** 301238104Sdes * Sign data with DSA 302238104Sdes * 303238104Sdes * \param[in] to_sign The ldns_buffer containing raw data that is 304238104Sdes * to be signed 305238104Sdes * \param[in] key The DSA key structure to sign with 306238104Sdes * \return ldns_rdf for the RRSIG ldns_rr 307238104Sdes */ 308238104Sdesldns_rdf * 309238104Sdesldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) 310238104Sdes{ 311238104Sdes unsigned char *sha1_hash; 312238104Sdes ldns_rdf *sigdata_rdf; 313238104Sdes ldns_buffer *b64sig; 314238104Sdes 315238104Sdes DSA_SIG *sig; 316238104Sdes uint8_t *data; 317238104Sdes size_t pad; 318238104Sdes 319238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 320238104Sdes if (!b64sig) { 321238104Sdes return NULL; 322238104Sdes } 323238104Sdes 324238104Sdes sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), 325238104Sdes ldns_buffer_position(to_sign), NULL); 326238104Sdes if (!sha1_hash) { 327238104Sdes ldns_buffer_free(b64sig); 328238104Sdes return NULL; 329238104Sdes } 330238104Sdes 331238104Sdes sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key); 332238104Sdes if(!sig) { 333238104Sdes ldns_buffer_free(b64sig); 334238104Sdes return NULL; 335238104Sdes } 336238104Sdes 337238104Sdes data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH); 338238104Sdes if(!data) { 339238104Sdes ldns_buffer_free(b64sig); 340238104Sdes DSA_SIG_free(sig); 341238104Sdes return NULL; 342238104Sdes } 343238104Sdes 344238104Sdes data[0] = 1; 345238104Sdes pad = 20 - (size_t) BN_num_bytes(sig->r); 346238104Sdes if (pad > 0) { 347238104Sdes memset(data + 1, 0, pad); 348238104Sdes } 349238104Sdes BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad); 350238104Sdes 351238104Sdes pad = 20 - (size_t) BN_num_bytes(sig->s); 352238104Sdes if (pad > 0) { 353238104Sdes memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad); 354238104Sdes } 355238104Sdes BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad)); 356238104Sdes 357238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, 358238104Sdes 1 + 2 * SHA_DIGEST_LENGTH, 359238104Sdes data); 360238104Sdes 361238104Sdes ldns_buffer_free(b64sig); 362238104Sdes LDNS_FREE(data); 363238104Sdes DSA_SIG_free(sig); 364238104Sdes 365238104Sdes return sigdata_rdf; 366238104Sdes} 367238104Sdes 368238104Sdes#ifdef USE_ECDSA 369238104Sdes#ifndef S_SPLINT_S 370238104Sdesstatic int 371238104Sdesldns_pkey_is_ecdsa(EVP_PKEY* pkey) 372238104Sdes{ 373238104Sdes EC_KEY* ec; 374238104Sdes const EC_GROUP* g; 375238104Sdes if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) 376238104Sdes return 0; 377238104Sdes ec = EVP_PKEY_get1_EC_KEY(pkey); 378238104Sdes g = EC_KEY_get0_group(ec); 379238104Sdes if(!g) { 380238104Sdes EC_KEY_free(ec); 381238104Sdes return 0; 382238104Sdes } 383238104Sdes if(EC_GROUP_get_curve_name(g) == NID_secp224r1 || 384238104Sdes EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 || 385238104Sdes EC_GROUP_get_curve_name(g) == NID_secp384r1) { 386238104Sdes EC_KEY_free(ec); 387238104Sdes return 1; 388238104Sdes } 389238104Sdes /* downref the eckey, the original is still inside the pkey */ 390238104Sdes EC_KEY_free(ec); 391238104Sdes return 0; 392238104Sdes} 393238104Sdes#endif /* splint */ 394238104Sdes#endif /* USE_ECDSA */ 395238104Sdes 396238104Sdesldns_rdf * 397238104Sdesldns_sign_public_evp(ldns_buffer *to_sign, 398238104Sdes EVP_PKEY *key, 399238104Sdes const EVP_MD *digest_type) 400238104Sdes{ 401238104Sdes unsigned int siglen; 402238104Sdes ldns_rdf *sigdata_rdf; 403238104Sdes ldns_buffer *b64sig; 404238104Sdes EVP_MD_CTX ctx; 405238104Sdes const EVP_MD *md_type; 406238104Sdes int r; 407238104Sdes 408238104Sdes siglen = 0; 409238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 410238104Sdes if (!b64sig) { 411238104Sdes return NULL; 412238104Sdes } 413238104Sdes 414238104Sdes /* initializes a signing context */ 415238104Sdes md_type = digest_type; 416238104Sdes if(!md_type) { 417238104Sdes /* unknown message difest */ 418238104Sdes ldns_buffer_free(b64sig); 419238104Sdes return NULL; 420238104Sdes } 421238104Sdes 422238104Sdes EVP_MD_CTX_init(&ctx); 423238104Sdes r = EVP_SignInit(&ctx, md_type); 424238104Sdes if(r == 1) { 425238104Sdes r = EVP_SignUpdate(&ctx, (unsigned char*) 426238104Sdes ldns_buffer_begin(to_sign), 427238104Sdes ldns_buffer_position(to_sign)); 428238104Sdes } else { 429238104Sdes ldns_buffer_free(b64sig); 430238104Sdes return NULL; 431238104Sdes } 432238104Sdes if(r == 1) { 433238104Sdes r = EVP_SignFinal(&ctx, (unsigned char*) 434238104Sdes ldns_buffer_begin(b64sig), &siglen, key); 435238104Sdes } else { 436238104Sdes ldns_buffer_free(b64sig); 437238104Sdes return NULL; 438238104Sdes } 439238104Sdes if(r != 1) { 440238104Sdes ldns_buffer_free(b64sig); 441238104Sdes return NULL; 442238104Sdes } 443238104Sdes 444238104Sdes /* unfortunately, OpenSSL output is differenct from DNS DSA format */ 445238104Sdes#ifndef S_SPLINT_S 446238104Sdes if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { 447238104Sdes sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen); 448238104Sdes#ifdef USE_ECDSA 449238104Sdes } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC && 450238104Sdes ldns_pkey_is_ecdsa(key)) { 451238104Sdes sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen); 452238104Sdes#endif 453238104Sdes } else { 454238104Sdes /* ok output for other types is the same */ 455238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 456238104Sdes ldns_buffer_begin(b64sig)); 457238104Sdes } 458238104Sdes#endif /* splint */ 459238104Sdes ldns_buffer_free(b64sig); 460238104Sdes EVP_MD_CTX_cleanup(&ctx); 461238104Sdes return sigdata_rdf; 462238104Sdes} 463238104Sdes 464238104Sdesldns_rdf * 465238104Sdesldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) 466238104Sdes{ 467238104Sdes unsigned char *sha1_hash; 468238104Sdes unsigned int siglen; 469238104Sdes ldns_rdf *sigdata_rdf; 470238104Sdes ldns_buffer *b64sig; 471238104Sdes int result; 472238104Sdes 473238104Sdes siglen = 0; 474238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 475238104Sdes if (!b64sig) { 476238104Sdes return NULL; 477238104Sdes } 478238104Sdes 479238104Sdes sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), 480238104Sdes ldns_buffer_position(to_sign), NULL); 481238104Sdes if (!sha1_hash) { 482238104Sdes ldns_buffer_free(b64sig); 483238104Sdes return NULL; 484238104Sdes } 485238104Sdes 486238104Sdes result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, 487238104Sdes (unsigned char*)ldns_buffer_begin(b64sig), 488238104Sdes &siglen, key); 489238104Sdes if (result != 1) { 490246854Sdes ldns_buffer_free(b64sig); 491238104Sdes return NULL; 492238104Sdes } 493238104Sdes 494238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 495238104Sdes ldns_buffer_begin(b64sig)); 496238104Sdes ldns_buffer_free(b64sig); /* can't free this buffer ?? */ 497238104Sdes return sigdata_rdf; 498238104Sdes} 499238104Sdes 500238104Sdesldns_rdf * 501238104Sdesldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) 502238104Sdes{ 503238104Sdes unsigned char *md5_hash; 504238104Sdes unsigned int siglen; 505238104Sdes ldns_rdf *sigdata_rdf; 506238104Sdes ldns_buffer *b64sig; 507238104Sdes 508238104Sdes b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); 509238104Sdes if (!b64sig) { 510238104Sdes return NULL; 511238104Sdes } 512238104Sdes 513238104Sdes md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign), 514238104Sdes ldns_buffer_position(to_sign), NULL); 515238104Sdes if (!md5_hash) { 516238104Sdes ldns_buffer_free(b64sig); 517238104Sdes return NULL; 518238104Sdes } 519238104Sdes 520238104Sdes RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH, 521238104Sdes (unsigned char*)ldns_buffer_begin(b64sig), 522238104Sdes &siglen, key); 523238104Sdes 524238104Sdes sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 525238104Sdes ldns_buffer_begin(b64sig)); 526238104Sdes ldns_buffer_free(b64sig); 527238104Sdes return sigdata_rdf; 528238104Sdes} 529238104Sdes#endif /* HAVE_SSL */ 530238104Sdes 531238104Sdes/** 532238104Sdes * Pushes all rrs from the rrsets of type A and AAAA on gluelist. 533238104Sdes */ 534238104Sdesstatic ldns_status 535238104Sdesldns_dnssec_addresses_on_glue_list( 536238104Sdes ldns_dnssec_rrsets *cur_rrset, 537238104Sdes ldns_rr_list *glue_list) 538238104Sdes{ 539238104Sdes ldns_dnssec_rrs *cur_rrs; 540238104Sdes while (cur_rrset) { 541238104Sdes if (cur_rrset->type == LDNS_RR_TYPE_A 542238104Sdes || cur_rrset->type == LDNS_RR_TYPE_AAAA) { 543238104Sdes for (cur_rrs = cur_rrset->rrs; 544238104Sdes cur_rrs; 545238104Sdes cur_rrs = cur_rrs->next) { 546238104Sdes if (cur_rrs->rr) { 547238104Sdes if (!ldns_rr_list_push_rr(glue_list, 548238104Sdes cur_rrs->rr)) { 549238104Sdes return LDNS_STATUS_MEM_ERR; 550238104Sdes /* ldns_rr_list_push_rr() 551238104Sdes * returns false when unable 552238104Sdes * to increase the capacity 553238104Sdes * of the ldsn_rr_list 554238104Sdes */ 555238104Sdes } 556238104Sdes } 557238104Sdes } 558238104Sdes } 559238104Sdes cur_rrset = cur_rrset->next; 560238104Sdes } 561238104Sdes return LDNS_STATUS_OK; 562238104Sdes} 563238104Sdes 564238104Sdes/** 565238104Sdes * Marks the names in the zone that are occluded. Those names will be skipped 566238104Sdes * when walking the tree with the ldns_dnssec_name_node_next_nonglue() 567238104Sdes * function. But watch out! Names that are partially occluded (like glue with 568238104Sdes * the same name as the delegation) will not be marked and should specifically 569269257Sdes * be taken into account separately. 570238104Sdes * 571238104Sdes * When glue_list is given (not NULL), in the process of marking the names, all 572238104Sdes * glue resource records will be pushed to that list, even glue at delegation names. 573238104Sdes * 574238104Sdes * \param[in] zone the zone in which to mark the names 575238104Sdes * \param[in] glue_list the list to which to push the glue rrs 576238104Sdes * \return LDNS_STATUS_OK on success, an error code otherwise 577238104Sdes */ 578238104Sdesldns_status 579238104Sdesldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, 580238104Sdes ldns_rr_list *glue_list) 581238104Sdes{ 582238104Sdes ldns_rbnode_t *node; 583238104Sdes ldns_dnssec_name *name; 584238104Sdes ldns_rdf *owner; 585238104Sdes ldns_rdf *cut = NULL; /* keeps track of zone cuts */ 586238104Sdes /* When the cut is caused by a delegation, below_delegation will be 1. 587238104Sdes * When caused by a DNAME, below_delegation will be 0. 588238104Sdes */ 589238104Sdes int below_delegation = -1; /* init suppresses comiler warning */ 590238104Sdes ldns_status s; 591238104Sdes 592238104Sdes if (!zone || !zone->names) { 593238104Sdes return LDNS_STATUS_NULL; 594238104Sdes } 595238104Sdes for (node = ldns_rbtree_first(zone->names); 596238104Sdes node != LDNS_RBTREE_NULL; 597238104Sdes node = ldns_rbtree_next(node)) { 598238104Sdes name = (ldns_dnssec_name *) node->data; 599238104Sdes owner = ldns_dnssec_name_name(name); 600238104Sdes 601238104Sdes if (cut) { 602238104Sdes /* The previous node was a zone cut, or a subdomain 603238104Sdes * below a zone cut. Is this node (still) a subdomain 604238104Sdes * below the cut? Then the name is occluded. Unless 605238104Sdes * the name contains a SOA, after which we are 606238104Sdes * authoritative again. 607238104Sdes * 608238104Sdes * FIXME! If there are labels in between the SOA and 609238104Sdes * the cut, going from the authoritative space (below 610238104Sdes * the SOA) up into occluded space again, will not be 611238104Sdes * detected with the contruct below! 612238104Sdes */ 613238104Sdes if (ldns_dname_is_subdomain(owner, cut) && 614238104Sdes !ldns_dnssec_rrsets_contains_type( 615238104Sdes name->rrsets, LDNS_RR_TYPE_SOA)) { 616238104Sdes 617238104Sdes if (below_delegation && glue_list) { 618238104Sdes s = ldns_dnssec_addresses_on_glue_list( 619238104Sdes name->rrsets, glue_list); 620238104Sdes if (s != LDNS_STATUS_OK) { 621238104Sdes return s; 622238104Sdes } 623238104Sdes } 624238104Sdes name->is_glue = true; /* Mark occluded name! */ 625238104Sdes continue; 626238104Sdes } else { 627238104Sdes cut = NULL; 628238104Sdes } 629238104Sdes } 630238104Sdes 631238104Sdes /* The node is not below a zone cut. Is it a zone cut itself? 632238104Sdes * Everything below a SOA is authoritative of course; Except 633238104Sdes * when the name also contains a DNAME :). 634238104Sdes */ 635238104Sdes if (ldns_dnssec_rrsets_contains_type( 636238104Sdes name->rrsets, LDNS_RR_TYPE_NS) 637238104Sdes && !ldns_dnssec_rrsets_contains_type( 638238104Sdes name->rrsets, LDNS_RR_TYPE_SOA)) { 639238104Sdes cut = owner; 640238104Sdes below_delegation = 1; 641238104Sdes if (glue_list) { /* record glue on the zone cut */ 642238104Sdes s = ldns_dnssec_addresses_on_glue_list( 643238104Sdes name->rrsets, glue_list); 644238104Sdes if (s != LDNS_STATUS_OK) { 645238104Sdes return s; 646238104Sdes } 647238104Sdes } 648238104Sdes } else if (ldns_dnssec_rrsets_contains_type( 649238104Sdes name->rrsets, LDNS_RR_TYPE_DNAME)) { 650238104Sdes cut = owner; 651238104Sdes below_delegation = 0; 652238104Sdes } 653238104Sdes } 654238104Sdes return LDNS_STATUS_OK; 655238104Sdes} 656238104Sdes 657238104Sdes/** 658238104Sdes * Marks the names in the zone that are occluded. Those names will be skipped 659238104Sdes * when walking the tree with the ldns_dnssec_name_node_next_nonglue() 660238104Sdes * function. But watch out! Names that are partially occluded (like glue with 661238104Sdes * the same name as the delegation) will not be marked and should specifically 662269257Sdes * be taken into account separately. 663238104Sdes * 664238104Sdes * \param[in] zone the zone in which to mark the names 665238104Sdes * \return LDNS_STATUS_OK on success, an error code otherwise 666238104Sdes */ 667238104Sdesldns_status 668238104Sdesldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone) 669238104Sdes{ 670238104Sdes return ldns_dnssec_zone_mark_and_get_glue(zone, NULL); 671238104Sdes} 672238104Sdes 673238104Sdesldns_rbnode_t * 674238104Sdesldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node) 675238104Sdes{ 676238104Sdes ldns_rbnode_t *next_node = NULL; 677238104Sdes ldns_dnssec_name *next_name = NULL; 678238104Sdes bool done = false; 679238104Sdes 680238104Sdes if (node == LDNS_RBTREE_NULL) { 681238104Sdes return NULL; 682238104Sdes } 683238104Sdes next_node = node; 684238104Sdes while (!done) { 685238104Sdes if (next_node == LDNS_RBTREE_NULL) { 686238104Sdes return NULL; 687238104Sdes } else { 688238104Sdes next_name = (ldns_dnssec_name *)next_node->data; 689238104Sdes if (!next_name->is_glue) { 690238104Sdes done = true; 691238104Sdes } else { 692238104Sdes next_node = ldns_rbtree_next(next_node); 693238104Sdes } 694238104Sdes } 695238104Sdes } 696238104Sdes return next_node; 697238104Sdes} 698238104Sdes 699238104Sdesldns_status 700238104Sdesldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, 701238104Sdes ldns_rr_list *new_rrs) 702238104Sdes{ 703238104Sdes 704238104Sdes ldns_rbnode_t *first_node, *cur_node, *next_node; 705238104Sdes ldns_dnssec_name *cur_name, *next_name; 706238104Sdes ldns_rr *nsec_rr; 707238104Sdes uint32_t nsec_ttl; 708238104Sdes ldns_dnssec_rrsets *soa; 709238104Sdes 710238104Sdes /* the TTL of NSEC rrs should be set to the minimum TTL of 711238104Sdes * the zone SOA (RFC4035 Section 2.3) 712238104Sdes */ 713238104Sdes soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); 714238104Sdes 715238104Sdes /* did the caller actually set it? if not, 716238104Sdes * fall back to default ttl 717238104Sdes */ 718238104Sdes if (soa && soa->rrs && soa->rrs->rr 719238104Sdes && (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) { 720238104Sdes nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); 721238104Sdes } else { 722238104Sdes nsec_ttl = LDNS_DEFAULT_TTL; 723238104Sdes } 724238104Sdes 725238104Sdes first_node = ldns_dnssec_name_node_next_nonglue( 726238104Sdes ldns_rbtree_first(zone->names)); 727238104Sdes cur_node = first_node; 728238104Sdes if (cur_node) { 729238104Sdes next_node = ldns_dnssec_name_node_next_nonglue( 730238104Sdes ldns_rbtree_next(cur_node)); 731238104Sdes } else { 732238104Sdes next_node = NULL; 733238104Sdes } 734238104Sdes 735238104Sdes while (cur_node && next_node) { 736238104Sdes cur_name = (ldns_dnssec_name *)cur_node->data; 737238104Sdes next_name = (ldns_dnssec_name *)next_node->data; 738238104Sdes nsec_rr = ldns_dnssec_create_nsec(cur_name, 739238104Sdes next_name, 740238104Sdes LDNS_RR_TYPE_NSEC); 741238104Sdes ldns_rr_set_ttl(nsec_rr, nsec_ttl); 742238104Sdes if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ 743238104Sdes ldns_rr_free(nsec_rr); 744238104Sdes return LDNS_STATUS_ERR; 745238104Sdes } 746238104Sdes ldns_rr_list_push_rr(new_rrs, nsec_rr); 747238104Sdes cur_node = next_node; 748238104Sdes if (cur_node) { 749238104Sdes next_node = ldns_dnssec_name_node_next_nonglue( 750238104Sdes ldns_rbtree_next(cur_node)); 751238104Sdes } 752238104Sdes } 753238104Sdes 754238104Sdes if (cur_node && !next_node) { 755238104Sdes cur_name = (ldns_dnssec_name *)cur_node->data; 756238104Sdes next_name = (ldns_dnssec_name *)first_node->data; 757238104Sdes nsec_rr = ldns_dnssec_create_nsec(cur_name, 758238104Sdes next_name, 759238104Sdes LDNS_RR_TYPE_NSEC); 760238104Sdes ldns_rr_set_ttl(nsec_rr, nsec_ttl); 761238104Sdes if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ 762238104Sdes ldns_rr_free(nsec_rr); 763238104Sdes return LDNS_STATUS_ERR; 764238104Sdes } 765238104Sdes ldns_rr_list_push_rr(new_rrs, nsec_rr); 766238104Sdes } else { 767238104Sdes printf("error\n"); 768238104Sdes } 769238104Sdes 770238104Sdes return LDNS_STATUS_OK; 771238104Sdes} 772238104Sdes 773238104Sdes#ifdef HAVE_SSL 774269257Sdesstatic void 775269257Sdesldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) { 776269257Sdes (void) arg; 777269257Sdes LDNS_FREE(node); 778269257Sdes} 779269257Sdes 780246827Sdesstatic ldns_status 781238104Sdesldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, 782238104Sdes ldns_rr_list *new_rrs, 783238104Sdes uint8_t algorithm, 784238104Sdes uint8_t flags, 785238104Sdes uint16_t iterations, 786238104Sdes uint8_t salt_length, 787238104Sdes uint8_t *salt, 788238104Sdes ldns_rbtree_t **map) 789238104Sdes{ 790238104Sdes ldns_rbnode_t *first_name_node; 791238104Sdes ldns_rbnode_t *current_name_node; 792238104Sdes ldns_dnssec_name *current_name; 793238104Sdes ldns_status result = LDNS_STATUS_OK; 794238104Sdes ldns_rr *nsec_rr; 795238104Sdes ldns_rr_list *nsec3_list; 796238104Sdes uint32_t nsec_ttl; 797238104Sdes ldns_dnssec_rrsets *soa; 798238104Sdes ldns_rbnode_t *hashmap_node; 799238104Sdes 800238104Sdes if (!zone || !new_rrs || !zone->names) { 801238104Sdes return LDNS_STATUS_ERR; 802238104Sdes } 803238104Sdes 804238104Sdes /* the TTL of NSEC rrs should be set to the minimum TTL of 805238104Sdes * the zone SOA (RFC4035 Section 2.3) 806238104Sdes */ 807238104Sdes soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); 808238104Sdes 809238104Sdes /* did the caller actually set it? if not, 810238104Sdes * fall back to default ttl 811238104Sdes */ 812238104Sdes if (soa && soa->rrs && soa->rrs->rr 813238104Sdes && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) { 814238104Sdes nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); 815238104Sdes } else { 816238104Sdes nsec_ttl = LDNS_DEFAULT_TTL; 817238104Sdes } 818238104Sdes 819269257Sdes if (zone->hashed_names) { 820269257Sdes ldns_traverse_postorder(zone->hashed_names, 821269257Sdes ldns_hashed_names_node_free, NULL); 822269257Sdes LDNS_FREE(zone->hashed_names); 823238104Sdes } 824269257Sdes zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v); 825269257Sdes if (zone->hashed_names && map) { 826269257Sdes *map = zone->hashed_names; 827269257Sdes } 828238104Sdes 829238104Sdes first_name_node = ldns_dnssec_name_node_next_nonglue( 830238104Sdes ldns_rbtree_first(zone->names)); 831238104Sdes 832238104Sdes current_name_node = first_name_node; 833238104Sdes 834269257Sdes while (current_name_node && current_name_node != LDNS_RBTREE_NULL && 835269257Sdes result == LDNS_STATUS_OK) { 836269257Sdes 837238104Sdes current_name = (ldns_dnssec_name *) current_name_node->data; 838238104Sdes nsec_rr = ldns_dnssec_create_nsec3(current_name, 839238104Sdes NULL, 840238104Sdes zone->soa->name, 841238104Sdes algorithm, 842238104Sdes flags, 843238104Sdes iterations, 844238104Sdes salt_length, 845238104Sdes salt); 846238104Sdes /* by default, our nsec based generator adds rrsigs 847238104Sdes * remove the bitmap for empty nonterminals */ 848238104Sdes if (!current_name->rrsets) { 849238104Sdes ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr)); 850238104Sdes } 851238104Sdes ldns_rr_set_ttl(nsec_rr, nsec_ttl); 852238104Sdes result = ldns_dnssec_name_add_rr(current_name, nsec_rr); 853238104Sdes ldns_rr_list_push_rr(new_rrs, nsec_rr); 854269257Sdes if (ldns_rr_owner(nsec_rr)) { 855238104Sdes hashmap_node = LDNS_MALLOC(ldns_rbnode_t); 856269257Sdes if (hashmap_node == NULL) { 857269257Sdes return LDNS_STATUS_MEM_ERR; 858238104Sdes } 859269257Sdes current_name->hashed_name = 860269257Sdes ldns_dname_label(ldns_rr_owner(nsec_rr), 0); 861269257Sdes 862269257Sdes if (current_name->hashed_name == NULL) { 863269257Sdes LDNS_FREE(hashmap_node); 864269257Sdes return LDNS_STATUS_MEM_ERR; 865269257Sdes } 866269257Sdes hashmap_node->key = current_name->hashed_name; 867269257Sdes hashmap_node->data = current_name; 868269257Sdes 869269257Sdes if (! ldns_rbtree_insert(zone->hashed_names 870269257Sdes , hashmap_node)) { 871269257Sdes LDNS_FREE(hashmap_node); 872269257Sdes } 873238104Sdes } 874238104Sdes current_name_node = ldns_dnssec_name_node_next_nonglue( 875238104Sdes ldns_rbtree_next(current_name_node)); 876238104Sdes } 877238104Sdes if (result != LDNS_STATUS_OK) { 878238104Sdes return result; 879238104Sdes } 880238104Sdes 881269257Sdes /* Make sorted list of nsec3s (via zone->hashed_names) 882269257Sdes */ 883269257Sdes nsec3_list = ldns_rr_list_new(); 884269257Sdes if (nsec3_list == NULL) { 885269257Sdes return LDNS_STATUS_MEM_ERR; 886269257Sdes } 887269257Sdes for ( hashmap_node = ldns_rbtree_first(zone->hashed_names) 888269257Sdes ; hashmap_node != LDNS_RBTREE_NULL 889269257Sdes ; hashmap_node = ldns_rbtree_next(hashmap_node) 890269257Sdes ) { 891269257Sdes current_name = (ldns_dnssec_name *) hashmap_node->data; 892269257Sdes nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec; 893269257Sdes if (nsec_rr) { 894269257Sdes ldns_rr_list_push_rr(nsec3_list, nsec_rr); 895269257Sdes } 896269257Sdes } 897238104Sdes result = ldns_dnssec_chain_nsec3_list(nsec3_list); 898246854Sdes ldns_rr_list_free(nsec3_list); 899238104Sdes 900238104Sdes return result; 901238104Sdes} 902238104Sdes 903238104Sdesldns_status 904238104Sdesldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, 905238104Sdes ldns_rr_list *new_rrs, 906238104Sdes uint8_t algorithm, 907238104Sdes uint8_t flags, 908238104Sdes uint16_t iterations, 909238104Sdes uint8_t salt_length, 910238104Sdes uint8_t *salt) 911238104Sdes{ 912238104Sdes return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm, 913238104Sdes flags, iterations, salt_length, salt, NULL); 914238104Sdes 915238104Sdes} 916238104Sdes#endif /* HAVE_SSL */ 917238104Sdes 918238104Sdesldns_dnssec_rrs * 919238104Sdesldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures 920238104Sdes , ATTR_UNUSED(ldns_key_list *key_list) 921238104Sdes , int (*func)(ldns_rr *, void *) 922238104Sdes , void *arg 923238104Sdes ) 924238104Sdes{ 925238104Sdes ldns_dnssec_rrs *base_rrs = signatures; 926238104Sdes ldns_dnssec_rrs *cur_rr = base_rrs; 927238104Sdes ldns_dnssec_rrs *prev_rr = NULL; 928238104Sdes ldns_dnssec_rrs *next_rr; 929238104Sdes 930238104Sdes uint16_t keytag; 931238104Sdes size_t i; 932238104Sdes 933238104Sdes if (!cur_rr) { 934238104Sdes switch(func(NULL, arg)) { 935238104Sdes case LDNS_SIGNATURE_LEAVE_ADD_NEW: 936238104Sdes case LDNS_SIGNATURE_REMOVE_ADD_NEW: 937238104Sdes break; 938238104Sdes case LDNS_SIGNATURE_LEAVE_NO_ADD: 939238104Sdes case LDNS_SIGNATURE_REMOVE_NO_ADD: 940238104Sdes ldns_key_list_set_use(key_list, false); 941238104Sdes break; 942238104Sdes default: 943269257Sdes#ifdef STDERR_MSGS 944238104Sdes fprintf(stderr, "[XX] unknown return value from callback\n"); 945269257Sdes#endif 946238104Sdes break; 947238104Sdes } 948238104Sdes return NULL; 949238104Sdes } 950238104Sdes (void)func(cur_rr->rr, arg); 951238104Sdes 952238104Sdes while (cur_rr) { 953238104Sdes next_rr = cur_rr->next; 954238104Sdes 955238104Sdes switch (func(cur_rr->rr, arg)) { 956238104Sdes case LDNS_SIGNATURE_LEAVE_ADD_NEW: 957238104Sdes prev_rr = cur_rr; 958238104Sdes break; 959238104Sdes case LDNS_SIGNATURE_LEAVE_NO_ADD: 960238104Sdes keytag = ldns_rdf2native_int16( 961238104Sdes ldns_rr_rrsig_keytag(cur_rr->rr)); 962238104Sdes for (i = 0; i < ldns_key_list_key_count(key_list); i++) { 963238104Sdes if (ldns_key_keytag(ldns_key_list_key(key_list, i)) == 964238104Sdes keytag) { 965238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 966238104Sdes false); 967238104Sdes } 968238104Sdes } 969238104Sdes prev_rr = cur_rr; 970238104Sdes break; 971238104Sdes case LDNS_SIGNATURE_REMOVE_NO_ADD: 972238104Sdes keytag = ldns_rdf2native_int16( 973238104Sdes ldns_rr_rrsig_keytag(cur_rr->rr)); 974238104Sdes for (i = 0; i < ldns_key_list_key_count(key_list); i++) { 975238104Sdes if (ldns_key_keytag(ldns_key_list_key(key_list, i)) 976238104Sdes == keytag) { 977238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 978238104Sdes false); 979238104Sdes } 980238104Sdes } 981238104Sdes if (prev_rr) { 982238104Sdes prev_rr->next = next_rr; 983238104Sdes } else { 984238104Sdes base_rrs = next_rr; 985238104Sdes } 986238104Sdes LDNS_FREE(cur_rr); 987238104Sdes break; 988238104Sdes case LDNS_SIGNATURE_REMOVE_ADD_NEW: 989238104Sdes if (prev_rr) { 990238104Sdes prev_rr->next = next_rr; 991238104Sdes } else { 992238104Sdes base_rrs = next_rr; 993238104Sdes } 994238104Sdes LDNS_FREE(cur_rr); 995238104Sdes break; 996238104Sdes default: 997269257Sdes#ifdef STDERR_MSGS 998238104Sdes fprintf(stderr, "[XX] unknown return value from callback\n"); 999269257Sdes#endif 1000238104Sdes break; 1001238104Sdes } 1002238104Sdes cur_rr = next_rr; 1003238104Sdes } 1004238104Sdes 1005238104Sdes return base_rrs; 1006238104Sdes} 1007238104Sdes 1008238104Sdes#ifdef HAVE_SSL 1009238104Sdesldns_status 1010238104Sdesldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, 1011238104Sdes ldns_rr_list *new_rrs, 1012238104Sdes ldns_key_list *key_list, 1013238104Sdes int (*func)(ldns_rr *, void*), 1014238104Sdes void *arg) 1015238104Sdes{ 1016238104Sdes return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, 1017238104Sdes func, arg, 0); 1018238104Sdes} 1019238104Sdes 1020238104Sdes/** If there are KSKs use only them and mark ZSKs unused */ 1021238104Sdesstatic void 1022238104Sdesldns_key_list_filter_for_dnskey(ldns_key_list *key_list) 1023238104Sdes{ 1024238104Sdes int saw_ksk = 0; 1025238104Sdes size_t i; 1026238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1027238104Sdes if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) { 1028238104Sdes saw_ksk = 1; 1029238104Sdes break; 1030238104Sdes } 1031238104Sdes if(!saw_ksk) 1032238104Sdes return; 1033238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1034238104Sdes if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) 1035238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 0); 1036238104Sdes} 1037238104Sdes 1038238104Sdes/** If there are no ZSKs use KSK as ZSK */ 1039238104Sdesstatic void 1040238104Sdesldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list) 1041238104Sdes{ 1042238104Sdes int saw_zsk = 0; 1043238104Sdes size_t i; 1044238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1045238104Sdes if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) { 1046238104Sdes saw_zsk = 1; 1047238104Sdes break; 1048238104Sdes } 1049238104Sdes if(!saw_zsk) 1050238104Sdes return; 1051238104Sdes /* else filter all KSKs */ 1052238104Sdes for(i=0; i<ldns_key_list_key_count(key_list); i++) 1053238104Sdes if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) 1054238104Sdes ldns_key_set_use(ldns_key_list_key(key_list, i), 0); 1055238104Sdes} 1056238104Sdes 1057238104Sdesldns_status 1058246854Sdesldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone 1059246854Sdes , ldns_rr_list *new_rrs 1060246854Sdes , ldns_key_list *key_list 1061238104Sdes , int (*func)(ldns_rr *, void*) 1062238104Sdes , void *arg 1063238104Sdes , int flags 1064238104Sdes ) 1065238104Sdes{ 1066238104Sdes ldns_status result = LDNS_STATUS_OK; 1067238104Sdes 1068238104Sdes ldns_rbnode_t *cur_node; 1069238104Sdes ldns_rr_list *rr_list; 1070238104Sdes 1071238104Sdes ldns_dnssec_name *cur_name; 1072238104Sdes ldns_dnssec_rrsets *cur_rrset; 1073238104Sdes ldns_dnssec_rrs *cur_rr; 1074238104Sdes 1075238104Sdes ldns_rr_list *siglist; 1076238104Sdes 1077238104Sdes size_t i; 1078238104Sdes 1079238104Sdes int on_delegation_point = 0; /* handle partially occluded names */ 1080238104Sdes 1081238104Sdes ldns_rr_list *pubkey_list = ldns_rr_list_new(); 1082238104Sdes for (i = 0; i<ldns_key_list_key_count(key_list); i++) { 1083238104Sdes ldns_rr_list_push_rr( pubkey_list 1084238104Sdes , ldns_key2rr(ldns_key_list_key( 1085238104Sdes key_list, i)) 1086238104Sdes ); 1087238104Sdes } 1088238104Sdes /* TODO: callback to see is list should be signed */ 1089238104Sdes /* TODO: remove 'old' signatures from signature list */ 1090238104Sdes cur_node = ldns_rbtree_first(zone->names); 1091238104Sdes while (cur_node != LDNS_RBTREE_NULL) { 1092238104Sdes cur_name = (ldns_dnssec_name *) cur_node->data; 1093238104Sdes 1094238104Sdes if (!cur_name->is_glue) { 1095238104Sdes on_delegation_point = ldns_dnssec_rrsets_contains_type( 1096238104Sdes cur_name->rrsets, LDNS_RR_TYPE_NS) 1097238104Sdes && !ldns_dnssec_rrsets_contains_type( 1098238104Sdes cur_name->rrsets, LDNS_RR_TYPE_SOA); 1099238104Sdes cur_rrset = cur_name->rrsets; 1100238104Sdes while (cur_rrset) { 1101238104Sdes /* reset keys to use */ 1102238104Sdes ldns_key_list_set_use(key_list, true); 1103238104Sdes 1104238104Sdes /* walk through old sigs, remove the old, 1105238104Sdes and mark which keys (not) to use) */ 1106238104Sdes cur_rrset->signatures = 1107238104Sdes ldns_dnssec_remove_signatures(cur_rrset->signatures, 1108238104Sdes key_list, 1109238104Sdes func, 1110238104Sdes arg); 1111238104Sdes if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) && 1112238104Sdes cur_rrset->type == LDNS_RR_TYPE_DNSKEY) 1113238104Sdes ldns_key_list_filter_for_dnskey(key_list); 1114238104Sdes 1115238104Sdes if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY) 1116238104Sdes ldns_key_list_filter_for_non_dnskey(key_list); 1117238104Sdes 1118238104Sdes /* TODO: just set count to zero? */ 1119238104Sdes rr_list = ldns_rr_list_new(); 1120238104Sdes 1121238104Sdes cur_rr = cur_rrset->rrs; 1122238104Sdes while (cur_rr) { 1123238104Sdes ldns_rr_list_push_rr(rr_list, cur_rr->rr); 1124238104Sdes cur_rr = cur_rr->next; 1125238104Sdes } 1126238104Sdes 1127238104Sdes /* only sign non-delegation RRsets */ 1128238104Sdes /* (glue should have been marked earlier, 1129238104Sdes * except on the delegation points itself) */ 1130238104Sdes if (!on_delegation_point || 1131238104Sdes ldns_rr_list_type(rr_list) 1132238104Sdes == LDNS_RR_TYPE_DS || 1133238104Sdes ldns_rr_list_type(rr_list) 1134238104Sdes == LDNS_RR_TYPE_NSEC || 1135238104Sdes ldns_rr_list_type(rr_list) 1136238104Sdes == LDNS_RR_TYPE_NSEC3) { 1137238104Sdes siglist = ldns_sign_public(rr_list, key_list); 1138238104Sdes for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { 1139238104Sdes if (cur_rrset->signatures) { 1140238104Sdes result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures, 1141238104Sdes ldns_rr_list_rr(siglist, 1142238104Sdes i)); 1143238104Sdes } else { 1144238104Sdes cur_rrset->signatures = ldns_dnssec_rrs_new(); 1145238104Sdes cur_rrset->signatures->rr = 1146238104Sdes ldns_rr_list_rr(siglist, i); 1147246854Sdes } 1148246854Sdes if (new_rrs) { 1149238104Sdes ldns_rr_list_push_rr(new_rrs, 1150246854Sdes ldns_rr_list_rr(siglist, 1151246854Sdes i)); 1152238104Sdes } 1153238104Sdes } 1154238104Sdes ldns_rr_list_free(siglist); 1155238104Sdes } 1156238104Sdes 1157238104Sdes ldns_rr_list_free(rr_list); 1158238104Sdes 1159238104Sdes cur_rrset = cur_rrset->next; 1160238104Sdes } 1161238104Sdes 1162238104Sdes /* sign the nsec */ 1163238104Sdes ldns_key_list_set_use(key_list, true); 1164238104Sdes cur_name->nsec_signatures = 1165238104Sdes ldns_dnssec_remove_signatures(cur_name->nsec_signatures, 1166238104Sdes key_list, 1167238104Sdes func, 1168238104Sdes arg); 1169238104Sdes ldns_key_list_filter_for_non_dnskey(key_list); 1170238104Sdes 1171238104Sdes rr_list = ldns_rr_list_new(); 1172238104Sdes ldns_rr_list_push_rr(rr_list, cur_name->nsec); 1173238104Sdes siglist = ldns_sign_public(rr_list, key_list); 1174238104Sdes 1175238104Sdes for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { 1176238104Sdes if (cur_name->nsec_signatures) { 1177238104Sdes result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, 1178238104Sdes ldns_rr_list_rr(siglist, i)); 1179238104Sdes } else { 1180238104Sdes cur_name->nsec_signatures = ldns_dnssec_rrs_new(); 1181238104Sdes cur_name->nsec_signatures->rr = 1182238104Sdes ldns_rr_list_rr(siglist, i); 1183246854Sdes } 1184246854Sdes if (new_rrs) { 1185238104Sdes ldns_rr_list_push_rr(new_rrs, 1186246854Sdes ldns_rr_list_rr(siglist, i)); 1187238104Sdes } 1188238104Sdes } 1189238104Sdes 1190238104Sdes ldns_rr_list_free(siglist); 1191238104Sdes ldns_rr_list_free(rr_list); 1192238104Sdes } 1193238104Sdes cur_node = ldns_rbtree_next(cur_node); 1194238104Sdes } 1195238104Sdes 1196238104Sdes ldns_rr_list_deep_free(pubkey_list); 1197238104Sdes return result; 1198238104Sdes} 1199238104Sdes 1200238104Sdesldns_status 1201238104Sdesldns_dnssec_zone_sign(ldns_dnssec_zone *zone, 1202238104Sdes ldns_rr_list *new_rrs, 1203238104Sdes ldns_key_list *key_list, 1204238104Sdes int (*func)(ldns_rr *, void *), 1205238104Sdes void *arg) 1206238104Sdes{ 1207238104Sdes return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0); 1208238104Sdes} 1209238104Sdes 1210238104Sdesldns_status 1211238104Sdesldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, 1212238104Sdes ldns_rr_list *new_rrs, 1213238104Sdes ldns_key_list *key_list, 1214238104Sdes int (*func)(ldns_rr *, void *), 1215238104Sdes void *arg, 1216238104Sdes int flags) 1217238104Sdes{ 1218238104Sdes ldns_status result = LDNS_STATUS_OK; 1219238104Sdes 1220238104Sdes if (!zone || !new_rrs || !key_list) { 1221238104Sdes return LDNS_STATUS_ERR; 1222238104Sdes } 1223238104Sdes 1224238104Sdes /* zone is already sorted */ 1225238104Sdes result = ldns_dnssec_zone_mark_glue(zone); 1226238104Sdes if (result != LDNS_STATUS_OK) { 1227238104Sdes return result; 1228238104Sdes } 1229238104Sdes 1230238104Sdes /* check whether we need to add nsecs */ 1231238104Sdes if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { 1232238104Sdes result = ldns_dnssec_zone_create_nsecs(zone, new_rrs); 1233238104Sdes if (result != LDNS_STATUS_OK) { 1234238104Sdes return result; 1235238104Sdes } 1236238104Sdes } 1237238104Sdes 1238238104Sdes result = ldns_dnssec_zone_create_rrsigs_flg(zone, 1239238104Sdes new_rrs, 1240238104Sdes key_list, 1241238104Sdes func, 1242238104Sdes arg, 1243238104Sdes flags); 1244238104Sdes 1245238104Sdes return result; 1246238104Sdes} 1247238104Sdes 1248238104Sdesldns_status 1249238104Sdesldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, 1250238104Sdes ldns_rr_list *new_rrs, 1251238104Sdes ldns_key_list *key_list, 1252238104Sdes int (*func)(ldns_rr *, void *), 1253238104Sdes void *arg, 1254238104Sdes uint8_t algorithm, 1255238104Sdes uint8_t flags, 1256238104Sdes uint16_t iterations, 1257238104Sdes uint8_t salt_length, 1258238104Sdes uint8_t *salt) 1259238104Sdes{ 1260238104Sdes return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, 1261238104Sdes func, arg, algorithm, flags, iterations, salt_length, salt, 0, 1262238104Sdes NULL); 1263238104Sdes} 1264238104Sdes 1265238104Sdesldns_status 1266238104Sdesldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, 1267238104Sdes ldns_rr_list *new_rrs, 1268238104Sdes ldns_key_list *key_list, 1269238104Sdes int (*func)(ldns_rr *, void *), 1270238104Sdes void *arg, 1271238104Sdes uint8_t algorithm, 1272238104Sdes uint8_t flags, 1273238104Sdes uint16_t iterations, 1274238104Sdes uint8_t salt_length, 1275238104Sdes uint8_t *salt, 1276238104Sdes int signflags, 1277238104Sdes ldns_rbtree_t **map) 1278238104Sdes{ 1279238104Sdes ldns_rr *nsec3, *nsec3param; 1280238104Sdes ldns_status result = LDNS_STATUS_OK; 1281238104Sdes 1282238104Sdes /* zone is already sorted */ 1283238104Sdes result = ldns_dnssec_zone_mark_glue(zone); 1284238104Sdes if (result != LDNS_STATUS_OK) { 1285238104Sdes return result; 1286238104Sdes } 1287238104Sdes 1288238104Sdes /* TODO if there are already nsec3s presents and their 1289238104Sdes * parameters are the same as these, we don't have to recreate 1290238104Sdes */ 1291238104Sdes if (zone->names) { 1292238104Sdes /* add empty nonterminals */ 1293238104Sdes result = ldns_dnssec_zone_add_empty_nonterminals(zone); 1294238104Sdes if (result != LDNS_STATUS_OK) { 1295238104Sdes return result; 1296238104Sdes } 1297238104Sdes 1298238104Sdes nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec; 1299238104Sdes if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) { 1300238104Sdes /* no need to recreate */ 1301238104Sdes } else { 1302238104Sdes if (!ldns_dnssec_zone_find_rrset(zone, 1303238104Sdes zone->soa->name, 1304238104Sdes LDNS_RR_TYPE_NSEC3PARAM)) { 1305238104Sdes /* create and add the nsec3param rr */ 1306238104Sdes nsec3param = 1307238104Sdes ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM); 1308238104Sdes ldns_rr_set_owner(nsec3param, 1309238104Sdes ldns_rdf_clone(zone->soa->name)); 1310238104Sdes ldns_nsec3_add_param_rdfs(nsec3param, 1311238104Sdes algorithm, 1312238104Sdes flags, 1313238104Sdes iterations, 1314238104Sdes salt_length, 1315238104Sdes salt); 1316238104Sdes /* always set bit 7 of the flags to zero, according to 1317238104Sdes * rfc5155 section 11. The bits are counted from right to left, 1318238104Sdes * so bit 7 in rfc5155 is bit 0 in ldns */ 1319238104Sdes ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0); 1320238104Sdes result = ldns_dnssec_zone_add_rr(zone, nsec3param); 1321238104Sdes if (result != LDNS_STATUS_OK) { 1322238104Sdes return result; 1323238104Sdes } 1324238104Sdes ldns_rr_list_push_rr(new_rrs, nsec3param); 1325238104Sdes } 1326238104Sdes result = ldns_dnssec_zone_create_nsec3s_mkmap(zone, 1327238104Sdes new_rrs, 1328238104Sdes algorithm, 1329238104Sdes flags, 1330238104Sdes iterations, 1331238104Sdes salt_length, 1332238104Sdes salt, 1333238104Sdes map); 1334238104Sdes if (result != LDNS_STATUS_OK) { 1335238104Sdes return result; 1336238104Sdes } 1337238104Sdes } 1338238104Sdes 1339238104Sdes result = ldns_dnssec_zone_create_rrsigs_flg(zone, 1340238104Sdes new_rrs, 1341238104Sdes key_list, 1342238104Sdes func, 1343238104Sdes arg, 1344238104Sdes signflags); 1345238104Sdes } 1346238104Sdes 1347238104Sdes return result; 1348238104Sdes} 1349238104Sdes 1350238104Sdesldns_status 1351238104Sdesldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, 1352238104Sdes ldns_rr_list *new_rrs, 1353238104Sdes ldns_key_list *key_list, 1354238104Sdes int (*func)(ldns_rr *, void *), 1355238104Sdes void *arg, 1356238104Sdes uint8_t algorithm, 1357238104Sdes uint8_t flags, 1358238104Sdes uint16_t iterations, 1359238104Sdes uint8_t salt_length, 1360238104Sdes uint8_t *salt, 1361238104Sdes int signflags) 1362238104Sdes{ 1363238104Sdes return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, 1364238104Sdes func, arg, algorithm, flags, iterations, salt_length, salt, 1365238104Sdes signflags, NULL); 1366238104Sdes} 1367238104Sdes 1368238104Sdesldns_zone * 1369238104Sdesldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) 1370238104Sdes{ 1371238104Sdes ldns_dnssec_zone *dnssec_zone; 1372238104Sdes ldns_zone *signed_zone; 1373238104Sdes ldns_rr_list *new_rrs; 1374238104Sdes size_t i; 1375238104Sdes 1376238104Sdes signed_zone = ldns_zone_new(); 1377238104Sdes dnssec_zone = ldns_dnssec_zone_new(); 1378238104Sdes 1379238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); 1380238104Sdes ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); 1381238104Sdes 1382238104Sdes for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 1383238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, 1384238104Sdes ldns_rr_list_rr(ldns_zone_rrs(zone), 1385238104Sdes i)); 1386238104Sdes ldns_zone_push_rr(signed_zone, 1387238104Sdes ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), 1388238104Sdes i))); 1389238104Sdes } 1390238104Sdes 1391238104Sdes new_rrs = ldns_rr_list_new(); 1392238104Sdes (void) ldns_dnssec_zone_sign(dnssec_zone, 1393238104Sdes new_rrs, 1394238104Sdes key_list, 1395238104Sdes ldns_dnssec_default_replace_signatures, 1396238104Sdes NULL); 1397238104Sdes 1398238104Sdes for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { 1399238104Sdes ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), 1400238104Sdes ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); 1401238104Sdes } 1402238104Sdes 1403238104Sdes ldns_rr_list_deep_free(new_rrs); 1404238104Sdes ldns_dnssec_zone_free(dnssec_zone); 1405238104Sdes 1406238104Sdes return signed_zone; 1407238104Sdes} 1408238104Sdes 1409238104Sdesldns_zone * 1410238104Sdesldns_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) 1411238104Sdes{ 1412238104Sdes ldns_dnssec_zone *dnssec_zone; 1413238104Sdes ldns_zone *signed_zone; 1414238104Sdes ldns_rr_list *new_rrs; 1415238104Sdes size_t i; 1416238104Sdes 1417238104Sdes signed_zone = ldns_zone_new(); 1418238104Sdes dnssec_zone = ldns_dnssec_zone_new(); 1419238104Sdes 1420238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); 1421238104Sdes ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); 1422238104Sdes 1423238104Sdes for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 1424238104Sdes (void) ldns_dnssec_zone_add_rr(dnssec_zone, 1425238104Sdes ldns_rr_list_rr(ldns_zone_rrs(zone), 1426238104Sdes i)); 1427238104Sdes ldns_zone_push_rr(signed_zone, 1428238104Sdes ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), 1429238104Sdes i))); 1430238104Sdes } 1431238104Sdes 1432238104Sdes new_rrs = ldns_rr_list_new(); 1433238104Sdes (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone, 1434238104Sdes new_rrs, 1435238104Sdes key_list, 1436238104Sdes ldns_dnssec_default_replace_signatures, 1437238104Sdes NULL, 1438238104Sdes algorithm, 1439238104Sdes flags, 1440238104Sdes iterations, 1441238104Sdes salt_length, 1442238104Sdes salt); 1443238104Sdes 1444238104Sdes for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { 1445238104Sdes ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), 1446238104Sdes ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); 1447238104Sdes } 1448238104Sdes 1449238104Sdes ldns_rr_list_deep_free(new_rrs); 1450238104Sdes ldns_dnssec_zone_free(dnssec_zone); 1451238104Sdes 1452238104Sdes return signed_zone; 1453238104Sdes} 1454238104Sdes#endif /* HAVE_SSL */ 1455238104Sdes 1456238104Sdes 1457