xref: /freebsd/contrib/ldns/dnssec_sign.c (revision 2787e39aaaaffd1fb07657ffaa2e3561858b3c73)
17b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
27b5038d7SDag-Erling Smørgrav 
37b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
47b5038d7SDag-Erling Smørgrav 
57b5038d7SDag-Erling Smørgrav #include <ldns/dnssec.h>
67b5038d7SDag-Erling Smørgrav #include <ldns/dnssec_sign.h>
77b5038d7SDag-Erling Smørgrav 
87b5038d7SDag-Erling Smørgrav #include <strings.h>
97b5038d7SDag-Erling Smørgrav #include <time.h>
107b5038d7SDag-Erling Smørgrav 
117b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
127b5038d7SDag-Erling Smørgrav /* this entire file is rather useless when you don't have
137b5038d7SDag-Erling Smørgrav  * crypto...
147b5038d7SDag-Erling Smørgrav  */
157b5038d7SDag-Erling Smørgrav #include <openssl/ssl.h>
167b5038d7SDag-Erling Smørgrav #include <openssl/evp.h>
177b5038d7SDag-Erling Smørgrav #include <openssl/rand.h>
187b5038d7SDag-Erling Smørgrav #include <openssl/err.h>
197b5038d7SDag-Erling Smørgrav #include <openssl/md5.h>
207b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
217b5038d7SDag-Erling Smørgrav 
227b5038d7SDag-Erling Smørgrav ldns_rr *
237b5038d7SDag-Erling Smørgrav ldns_create_empty_rrsig(ldns_rr_list *rrset,
247b5038d7SDag-Erling Smørgrav                         ldns_key *current_key)
257b5038d7SDag-Erling Smørgrav {
267b5038d7SDag-Erling Smørgrav 	uint32_t orig_ttl;
277b5038d7SDag-Erling Smørgrav 	ldns_rr_class orig_class;
287b5038d7SDag-Erling Smørgrav 	time_t now;
297b5038d7SDag-Erling Smørgrav 	ldns_rr *current_sig;
307b5038d7SDag-Erling Smørgrav 	uint8_t label_count;
317b5038d7SDag-Erling Smørgrav 	ldns_rdf *signame;
327b5038d7SDag-Erling Smørgrav 
337b5038d7SDag-Erling Smørgrav 	label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
347b5038d7SDag-Erling Smørgrav 	                                                   0)));
357b5038d7SDag-Erling Smørgrav         /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */
367b5038d7SDag-Erling Smørgrav         if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))))
377b5038d7SDag-Erling Smørgrav                 label_count --;
387b5038d7SDag-Erling Smørgrav 
397b5038d7SDag-Erling Smørgrav 	current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
407b5038d7SDag-Erling Smørgrav 
417b5038d7SDag-Erling Smørgrav 	/* set the type on the new signature */
427b5038d7SDag-Erling Smørgrav 	orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
437b5038d7SDag-Erling Smørgrav 	orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
447b5038d7SDag-Erling Smørgrav 
457b5038d7SDag-Erling Smørgrav 	ldns_rr_set_ttl(current_sig, orig_ttl);
467b5038d7SDag-Erling Smørgrav 	ldns_rr_set_class(current_sig, orig_class);
477b5038d7SDag-Erling Smørgrav 	ldns_rr_set_owner(current_sig,
487b5038d7SDag-Erling Smørgrav 			  ldns_rdf_clone(
497b5038d7SDag-Erling Smørgrav 			       ldns_rr_owner(
507b5038d7SDag-Erling Smørgrav 				    ldns_rr_list_rr(rrset,
517b5038d7SDag-Erling Smørgrav 						    0))));
527b5038d7SDag-Erling Smørgrav 
537b5038d7SDag-Erling Smørgrav 	/* fill in what we know of the signature */
547b5038d7SDag-Erling Smørgrav 
557b5038d7SDag-Erling Smørgrav 	/* set the orig_ttl */
567b5038d7SDag-Erling Smørgrav 	(void)ldns_rr_rrsig_set_origttl(
577b5038d7SDag-Erling Smørgrav 		   current_sig,
587b5038d7SDag-Erling Smørgrav 		   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
597b5038d7SDag-Erling Smørgrav 					 orig_ttl));
607b5038d7SDag-Erling Smørgrav 	/* the signers name */
617b5038d7SDag-Erling Smørgrav 	signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
627b5038d7SDag-Erling Smørgrav 	ldns_dname2canonical(signame);
637b5038d7SDag-Erling Smørgrav 	(void)ldns_rr_rrsig_set_signame(
647b5038d7SDag-Erling Smørgrav 			current_sig,
657b5038d7SDag-Erling Smørgrav 			signame);
667b5038d7SDag-Erling Smørgrav 	/* label count - get it from the first rr in the rr_list */
677b5038d7SDag-Erling Smørgrav 	(void)ldns_rr_rrsig_set_labels(
687b5038d7SDag-Erling Smørgrav 			current_sig,
697b5038d7SDag-Erling Smørgrav 			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
707b5038d7SDag-Erling Smørgrav 			                     label_count));
717b5038d7SDag-Erling Smørgrav 	/* inception, expiration */
727b5038d7SDag-Erling Smørgrav 	now = time(NULL);
737b5038d7SDag-Erling Smørgrav 	if (ldns_key_inception(current_key) != 0) {
747b5038d7SDag-Erling Smørgrav 		(void)ldns_rr_rrsig_set_inception(
757b5038d7SDag-Erling Smørgrav 				current_sig,
767b5038d7SDag-Erling Smørgrav 				ldns_native2rdf_int32(
777b5038d7SDag-Erling Smørgrav 				    LDNS_RDF_TYPE_TIME,
787b5038d7SDag-Erling Smørgrav 				    ldns_key_inception(current_key)));
797b5038d7SDag-Erling Smørgrav 	} else {
807b5038d7SDag-Erling Smørgrav 		(void)ldns_rr_rrsig_set_inception(
817b5038d7SDag-Erling Smørgrav 				current_sig,
827b5038d7SDag-Erling Smørgrav 				ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
837b5038d7SDag-Erling Smørgrav 	}
847b5038d7SDag-Erling Smørgrav 	if (ldns_key_expiration(current_key) != 0) {
857b5038d7SDag-Erling Smørgrav 		(void)ldns_rr_rrsig_set_expiration(
867b5038d7SDag-Erling Smørgrav 				current_sig,
877b5038d7SDag-Erling Smørgrav 				ldns_native2rdf_int32(
887b5038d7SDag-Erling Smørgrav 				    LDNS_RDF_TYPE_TIME,
897b5038d7SDag-Erling Smørgrav 				    ldns_key_expiration(current_key)));
907b5038d7SDag-Erling Smørgrav 	} else {
917b5038d7SDag-Erling Smørgrav 		(void)ldns_rr_rrsig_set_expiration(
927b5038d7SDag-Erling Smørgrav 			     current_sig,
937b5038d7SDag-Erling Smørgrav 				ldns_native2rdf_int32(
947b5038d7SDag-Erling Smørgrav 				    LDNS_RDF_TYPE_TIME,
957b5038d7SDag-Erling Smørgrav 				    now + LDNS_DEFAULT_EXP_TIME));
967b5038d7SDag-Erling Smørgrav 	}
977b5038d7SDag-Erling Smørgrav 
987b5038d7SDag-Erling Smørgrav 	(void)ldns_rr_rrsig_set_keytag(
997b5038d7SDag-Erling Smørgrav 		   current_sig,
1007b5038d7SDag-Erling Smørgrav 		   ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
1017b5038d7SDag-Erling Smørgrav 		                         ldns_key_keytag(current_key)));
1027b5038d7SDag-Erling Smørgrav 
1037b5038d7SDag-Erling Smørgrav 	(void)ldns_rr_rrsig_set_algorithm(
1047b5038d7SDag-Erling Smørgrav 			current_sig,
1057b5038d7SDag-Erling Smørgrav 			ldns_native2rdf_int8(
1067b5038d7SDag-Erling Smørgrav 			    LDNS_RDF_TYPE_ALG,
1077b5038d7SDag-Erling Smørgrav 			    ldns_key_algorithm(current_key)));
1087b5038d7SDag-Erling Smørgrav 
1097b5038d7SDag-Erling Smørgrav 	(void)ldns_rr_rrsig_set_typecovered(
1107b5038d7SDag-Erling Smørgrav 			current_sig,
1117b5038d7SDag-Erling Smørgrav 			ldns_native2rdf_int16(
1127b5038d7SDag-Erling Smørgrav 			    LDNS_RDF_TYPE_TYPE,
1137b5038d7SDag-Erling Smørgrav 			    ldns_rr_get_type(ldns_rr_list_rr(rrset,
1147b5038d7SDag-Erling Smørgrav 			                                     0))));
1157b5038d7SDag-Erling Smørgrav 	return current_sig;
1167b5038d7SDag-Erling Smørgrav }
1177b5038d7SDag-Erling Smørgrav 
1187b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
1197b5038d7SDag-Erling Smørgrav ldns_rdf *
1207b5038d7SDag-Erling Smørgrav ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
1217b5038d7SDag-Erling Smørgrav {
1227b5038d7SDag-Erling Smørgrav 	ldns_rdf *b64rdf = NULL;
1237b5038d7SDag-Erling Smørgrav 
1247b5038d7SDag-Erling Smørgrav 	switch(ldns_key_algorithm(current_key)) {
1257b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_DSA:
1267b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_DSA_NSEC3:
1277b5038d7SDag-Erling Smørgrav 		b64rdf = ldns_sign_public_evp(
1287b5038d7SDag-Erling Smørgrav 				   sign_buf,
1297b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1307b5038d7SDag-Erling Smørgrav 				   EVP_dss1());
1317b5038d7SDag-Erling Smørgrav 		break;
1327b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_RSASHA1:
1337b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_RSASHA1_NSEC3:
1347b5038d7SDag-Erling Smørgrav 		b64rdf = ldns_sign_public_evp(
1357b5038d7SDag-Erling Smørgrav 				   sign_buf,
1367b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1377b5038d7SDag-Erling Smørgrav 				   EVP_sha1());
1387b5038d7SDag-Erling Smørgrav 		break;
1397b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
1407b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_RSASHA256:
1417b5038d7SDag-Erling Smørgrav 		b64rdf = ldns_sign_public_evp(
1427b5038d7SDag-Erling Smørgrav 				   sign_buf,
1437b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1447b5038d7SDag-Erling Smørgrav 				   EVP_sha256());
1457b5038d7SDag-Erling Smørgrav 		break;
1467b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_RSASHA512:
1477b5038d7SDag-Erling Smørgrav 		b64rdf = ldns_sign_public_evp(
1487b5038d7SDag-Erling Smørgrav 				   sign_buf,
1497b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1507b5038d7SDag-Erling Smørgrav 				   EVP_sha512());
1517b5038d7SDag-Erling Smørgrav 		break;
1527b5038d7SDag-Erling Smørgrav #endif /* USE_SHA2 */
1537b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
1547b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_ECC_GOST:
1557b5038d7SDag-Erling Smørgrav 		b64rdf = ldns_sign_public_evp(
1567b5038d7SDag-Erling Smørgrav 				   sign_buf,
1577b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1587b5038d7SDag-Erling Smørgrav 				   EVP_get_digestbyname("md_gost94"));
1597b5038d7SDag-Erling Smørgrav 		break;
1607b5038d7SDag-Erling Smørgrav #endif /* USE_GOST */
1617b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
1627b5038d7SDag-Erling Smørgrav         case LDNS_SIGN_ECDSAP256SHA256:
1637b5038d7SDag-Erling Smørgrav        		b64rdf = ldns_sign_public_evp(
1647b5038d7SDag-Erling Smørgrav 				   sign_buf,
1657b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1667b5038d7SDag-Erling Smørgrav 				   EVP_sha256());
1677b5038d7SDag-Erling Smørgrav                 break;
1687b5038d7SDag-Erling Smørgrav         case LDNS_SIGN_ECDSAP384SHA384:
1697b5038d7SDag-Erling Smørgrav        		b64rdf = ldns_sign_public_evp(
1707b5038d7SDag-Erling Smørgrav 				   sign_buf,
1717b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1727b5038d7SDag-Erling Smørgrav 				   EVP_sha384());
1737b5038d7SDag-Erling Smørgrav                 break;
1747b5038d7SDag-Erling Smørgrav #endif
1757b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_RSAMD5:
1767b5038d7SDag-Erling Smørgrav 		b64rdf = ldns_sign_public_evp(
1777b5038d7SDag-Erling Smørgrav 				   sign_buf,
1787b5038d7SDag-Erling Smørgrav 				   ldns_key_evp_key(current_key),
1797b5038d7SDag-Erling Smørgrav 				   EVP_md5());
1807b5038d7SDag-Erling Smørgrav 		break;
1817b5038d7SDag-Erling Smørgrav 	default:
1827b5038d7SDag-Erling Smørgrav 		/* do _you_ know this alg? */
1837b5038d7SDag-Erling Smørgrav 		printf("unknown algorithm, ");
1847b5038d7SDag-Erling Smørgrav 		printf("is the one used available on this system?\n");
1857b5038d7SDag-Erling Smørgrav 		break;
1867b5038d7SDag-Erling Smørgrav 	}
1877b5038d7SDag-Erling Smørgrav 
1887b5038d7SDag-Erling Smørgrav 	return b64rdf;
1897b5038d7SDag-Erling Smørgrav }
1907b5038d7SDag-Erling Smørgrav 
1917b5038d7SDag-Erling Smørgrav /**
1927b5038d7SDag-Erling Smørgrav  * use this function to sign with a public/private key alg
1937b5038d7SDag-Erling Smørgrav  * return the created signatures
1947b5038d7SDag-Erling Smørgrav  */
1957b5038d7SDag-Erling Smørgrav ldns_rr_list *
1967b5038d7SDag-Erling Smørgrav ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
1977b5038d7SDag-Erling Smørgrav {
1987b5038d7SDag-Erling Smørgrav 	ldns_rr_list *signatures;
1997b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrset_clone;
2007b5038d7SDag-Erling Smørgrav 	ldns_rr *current_sig;
2017b5038d7SDag-Erling Smørgrav 	ldns_rdf *b64rdf;
2027b5038d7SDag-Erling Smørgrav 	ldns_key *current_key;
2037b5038d7SDag-Erling Smørgrav 	size_t key_count;
2047b5038d7SDag-Erling Smørgrav 	uint16_t i;
2057b5038d7SDag-Erling Smørgrav 	ldns_buffer *sign_buf;
2067b5038d7SDag-Erling Smørgrav 	ldns_rdf *new_owner;
2077b5038d7SDag-Erling Smørgrav 
2087b5038d7SDag-Erling Smørgrav 	if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
2097b5038d7SDag-Erling Smørgrav 		return NULL;
2107b5038d7SDag-Erling Smørgrav 	}
2117b5038d7SDag-Erling Smørgrav 
2127b5038d7SDag-Erling Smørgrav 	new_owner = NULL;
2137b5038d7SDag-Erling Smørgrav 
2147b5038d7SDag-Erling Smørgrav 	signatures = ldns_rr_list_new();
2157b5038d7SDag-Erling Smørgrav 
2167b5038d7SDag-Erling Smørgrav 	/* prepare a signature and add all the know data
2177b5038d7SDag-Erling Smørgrav 	 * prepare the rrset. Sign this together.  */
2187b5038d7SDag-Erling Smørgrav 	rrset_clone = ldns_rr_list_clone(rrset);
2197b5038d7SDag-Erling Smørgrav 	if (!rrset_clone) {
2207b5038d7SDag-Erling Smørgrav 		return NULL;
2217b5038d7SDag-Erling Smørgrav 	}
2227b5038d7SDag-Erling Smørgrav 
2237b5038d7SDag-Erling Smørgrav 	/* make it canonical */
2247b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
2257b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i),
2267b5038d7SDag-Erling Smørgrav 			ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
2277b5038d7SDag-Erling Smørgrav 		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
2287b5038d7SDag-Erling Smørgrav 	}
2297b5038d7SDag-Erling Smørgrav 	/* sort */
2307b5038d7SDag-Erling Smørgrav 	ldns_rr_list_sort(rrset_clone);
2317b5038d7SDag-Erling Smørgrav 
2327b5038d7SDag-Erling Smørgrav 	for (key_count = 0;
2337b5038d7SDag-Erling Smørgrav 		key_count < ldns_key_list_key_count(keys);
2347b5038d7SDag-Erling Smørgrav 		key_count++) {
2357b5038d7SDag-Erling Smørgrav 		if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
2367b5038d7SDag-Erling Smørgrav 			continue;
2377b5038d7SDag-Erling Smørgrav 		}
2387b5038d7SDag-Erling Smørgrav 		sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2397b5038d7SDag-Erling Smørgrav 		if (!sign_buf) {
2407b5038d7SDag-Erling Smørgrav 			ldns_rr_list_free(rrset_clone);
2417b5038d7SDag-Erling Smørgrav 			ldns_rr_list_free(signatures);
2427b5038d7SDag-Erling Smørgrav 			ldns_rdf_free(new_owner);
2437b5038d7SDag-Erling Smørgrav 			return NULL;
2447b5038d7SDag-Erling Smørgrav 		}
2457b5038d7SDag-Erling Smørgrav 		b64rdf = NULL;
2467b5038d7SDag-Erling Smørgrav 
2477b5038d7SDag-Erling Smørgrav 		current_key = ldns_key_list_key(keys, key_count);
2487b5038d7SDag-Erling Smørgrav 		/* sign all RRs with keys that have ZSKbit, !SEPbit.
2497b5038d7SDag-Erling Smørgrav 		   sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
2507b5038d7SDag-Erling Smørgrav 		if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) {
2517b5038d7SDag-Erling Smørgrav 			current_sig = ldns_create_empty_rrsig(rrset_clone,
2527b5038d7SDag-Erling Smørgrav 			                                      current_key);
2537b5038d7SDag-Erling Smørgrav 
2547b5038d7SDag-Erling Smørgrav 			/* right now, we have: a key, a semi-sig and an rrset. For
2557b5038d7SDag-Erling Smørgrav 			 * which we can create the sig and base64 encode that and
2567b5038d7SDag-Erling Smørgrav 			 * add that to the signature */
2577b5038d7SDag-Erling Smørgrav 
2587b5038d7SDag-Erling Smørgrav 			if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
2597b5038d7SDag-Erling Smørgrav 			    != LDNS_STATUS_OK) {
2607b5038d7SDag-Erling Smørgrav 				ldns_buffer_free(sign_buf);
2617b5038d7SDag-Erling Smørgrav 				/* ERROR */
2627b5038d7SDag-Erling Smørgrav 				ldns_rr_list_deep_free(rrset_clone);
263*2787e39aSDag-Erling Smørgrav 				ldns_rr_free(current_sig);
264*2787e39aSDag-Erling Smørgrav 				ldns_rr_list_deep_free(signatures);
2657b5038d7SDag-Erling Smørgrav 				return NULL;
2667b5038d7SDag-Erling Smørgrav 			}
2677b5038d7SDag-Erling Smørgrav 
2687b5038d7SDag-Erling Smørgrav 			/* add the rrset in sign_buf */
2697b5038d7SDag-Erling Smørgrav 			if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
2707b5038d7SDag-Erling Smørgrav 			    != LDNS_STATUS_OK) {
2717b5038d7SDag-Erling Smørgrav 				ldns_buffer_free(sign_buf);
2727b5038d7SDag-Erling Smørgrav 				ldns_rr_list_deep_free(rrset_clone);
273*2787e39aSDag-Erling Smørgrav 				ldns_rr_free(current_sig);
274*2787e39aSDag-Erling Smørgrav 				ldns_rr_list_deep_free(signatures);
2757b5038d7SDag-Erling Smørgrav 				return NULL;
2767b5038d7SDag-Erling Smørgrav 			}
2777b5038d7SDag-Erling Smørgrav 
2787b5038d7SDag-Erling Smørgrav 			b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
2797b5038d7SDag-Erling Smørgrav 
2807b5038d7SDag-Erling Smørgrav 			if (!b64rdf) {
2817b5038d7SDag-Erling Smørgrav 				/* signing went wrong */
2827b5038d7SDag-Erling Smørgrav 				ldns_rr_list_deep_free(rrset_clone);
283*2787e39aSDag-Erling Smørgrav 				ldns_rr_free(current_sig);
284*2787e39aSDag-Erling Smørgrav 				ldns_rr_list_deep_free(signatures);
2857b5038d7SDag-Erling Smørgrav 				return NULL;
2867b5038d7SDag-Erling Smørgrav 			}
2877b5038d7SDag-Erling Smørgrav 
2887b5038d7SDag-Erling Smørgrav 			ldns_rr_rrsig_set_sig(current_sig, b64rdf);
2897b5038d7SDag-Erling Smørgrav 
2907b5038d7SDag-Erling Smørgrav 			/* push the signature to the signatures list */
2917b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(signatures, current_sig);
2927b5038d7SDag-Erling Smørgrav 		}
2937b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(sign_buf); /* restart for the next key */
2947b5038d7SDag-Erling Smørgrav 	}
2957b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrset_clone);
2967b5038d7SDag-Erling Smørgrav 
2977b5038d7SDag-Erling Smørgrav 	return signatures;
2987b5038d7SDag-Erling Smørgrav }
2997b5038d7SDag-Erling Smørgrav 
3007b5038d7SDag-Erling Smørgrav /**
3017b5038d7SDag-Erling Smørgrav  * Sign data with DSA
3027b5038d7SDag-Erling Smørgrav  *
3037b5038d7SDag-Erling Smørgrav  * \param[in] to_sign The ldns_buffer containing raw data that is
3047b5038d7SDag-Erling Smørgrav  *                    to be signed
3057b5038d7SDag-Erling Smørgrav  * \param[in] key The DSA key structure to sign with
3067b5038d7SDag-Erling Smørgrav  * \return ldns_rdf for the RRSIG ldns_rr
3077b5038d7SDag-Erling Smørgrav  */
3087b5038d7SDag-Erling Smørgrav ldns_rdf *
3097b5038d7SDag-Erling Smørgrav ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
3107b5038d7SDag-Erling Smørgrav {
3117b5038d7SDag-Erling Smørgrav 	unsigned char *sha1_hash;
3127b5038d7SDag-Erling Smørgrav 	ldns_rdf *sigdata_rdf;
3137b5038d7SDag-Erling Smørgrav 	ldns_buffer *b64sig;
3147b5038d7SDag-Erling Smørgrav 
3157b5038d7SDag-Erling Smørgrav 	DSA_SIG *sig;
3167b5038d7SDag-Erling Smørgrav 	uint8_t *data;
3177b5038d7SDag-Erling Smørgrav 	size_t pad;
3187b5038d7SDag-Erling Smørgrav 
3197b5038d7SDag-Erling Smørgrav 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3207b5038d7SDag-Erling Smørgrav 	if (!b64sig) {
3217b5038d7SDag-Erling Smørgrav 		return NULL;
3227b5038d7SDag-Erling Smørgrav 	}
3237b5038d7SDag-Erling Smørgrav 
3247b5038d7SDag-Erling Smørgrav 	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
3257b5038d7SDag-Erling Smørgrav 				  ldns_buffer_position(to_sign), NULL);
3267b5038d7SDag-Erling Smørgrav 	if (!sha1_hash) {
3277b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
3287b5038d7SDag-Erling Smørgrav 		return NULL;
3297b5038d7SDag-Erling Smørgrav 	}
3307b5038d7SDag-Erling Smørgrav 
3317b5038d7SDag-Erling Smørgrav 	sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
3327b5038d7SDag-Erling Smørgrav         if(!sig) {
3337b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
3347b5038d7SDag-Erling Smørgrav 		return NULL;
3357b5038d7SDag-Erling Smørgrav         }
3367b5038d7SDag-Erling Smørgrav 
3377b5038d7SDag-Erling Smørgrav 	data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
3387b5038d7SDag-Erling Smørgrav         if(!data) {
3397b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
3407b5038d7SDag-Erling Smørgrav                 DSA_SIG_free(sig);
3417b5038d7SDag-Erling Smørgrav 		return NULL;
3427b5038d7SDag-Erling Smørgrav         }
3437b5038d7SDag-Erling Smørgrav 
3447b5038d7SDag-Erling Smørgrav 	data[0] = 1;
3457b5038d7SDag-Erling Smørgrav 	pad = 20 - (size_t) BN_num_bytes(sig->r);
3467b5038d7SDag-Erling Smørgrav 	if (pad > 0) {
3477b5038d7SDag-Erling Smørgrav 		memset(data + 1, 0, pad);
3487b5038d7SDag-Erling Smørgrav 	}
3497b5038d7SDag-Erling Smørgrav 	BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
3507b5038d7SDag-Erling Smørgrav 
3517b5038d7SDag-Erling Smørgrav 	pad = 20 - (size_t) BN_num_bytes(sig->s);
3527b5038d7SDag-Erling Smørgrav 	if (pad > 0) {
3537b5038d7SDag-Erling Smørgrav 		memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
3547b5038d7SDag-Erling Smørgrav 	}
3557b5038d7SDag-Erling Smørgrav 	BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
3567b5038d7SDag-Erling Smørgrav 
3577b5038d7SDag-Erling Smørgrav 	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
3587b5038d7SDag-Erling Smørgrav 								 1 + 2 * SHA_DIGEST_LENGTH,
3597b5038d7SDag-Erling Smørgrav 								 data);
3607b5038d7SDag-Erling Smørgrav 
3617b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(b64sig);
3627b5038d7SDag-Erling Smørgrav 	LDNS_FREE(data);
3637b5038d7SDag-Erling Smørgrav         DSA_SIG_free(sig);
3647b5038d7SDag-Erling Smørgrav 
3657b5038d7SDag-Erling Smørgrav 	return sigdata_rdf;
3667b5038d7SDag-Erling Smørgrav }
3677b5038d7SDag-Erling Smørgrav 
3687b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
3697b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
3707b5038d7SDag-Erling Smørgrav static int
3717b5038d7SDag-Erling Smørgrav ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
3727b5038d7SDag-Erling Smørgrav {
3737b5038d7SDag-Erling Smørgrav         EC_KEY* ec;
3747b5038d7SDag-Erling Smørgrav         const EC_GROUP* g;
3757b5038d7SDag-Erling Smørgrav         if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
3767b5038d7SDag-Erling Smørgrav                 return 0;
3777b5038d7SDag-Erling Smørgrav         ec = EVP_PKEY_get1_EC_KEY(pkey);
3787b5038d7SDag-Erling Smørgrav         g = EC_KEY_get0_group(ec);
3797b5038d7SDag-Erling Smørgrav         if(!g) {
3807b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
3817b5038d7SDag-Erling Smørgrav                 return 0;
3827b5038d7SDag-Erling Smørgrav         }
3837b5038d7SDag-Erling Smørgrav         if(EC_GROUP_get_curve_name(g) == NID_secp224r1 ||
3847b5038d7SDag-Erling Smørgrav                 EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 ||
3857b5038d7SDag-Erling Smørgrav                 EC_GROUP_get_curve_name(g) == NID_secp384r1) {
3867b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
3877b5038d7SDag-Erling Smørgrav                 return 1;
3887b5038d7SDag-Erling Smørgrav         }
3897b5038d7SDag-Erling Smørgrav         /* downref the eckey, the original is still inside the pkey */
3907b5038d7SDag-Erling Smørgrav         EC_KEY_free(ec);
3917b5038d7SDag-Erling Smørgrav         return 0;
3927b5038d7SDag-Erling Smørgrav }
3937b5038d7SDag-Erling Smørgrav #endif /* splint */
3947b5038d7SDag-Erling Smørgrav #endif /* USE_ECDSA */
3957b5038d7SDag-Erling Smørgrav 
3967b5038d7SDag-Erling Smørgrav ldns_rdf *
3977b5038d7SDag-Erling Smørgrav ldns_sign_public_evp(ldns_buffer *to_sign,
3987b5038d7SDag-Erling Smørgrav 				 EVP_PKEY *key,
3997b5038d7SDag-Erling Smørgrav 				 const EVP_MD *digest_type)
4007b5038d7SDag-Erling Smørgrav {
4017b5038d7SDag-Erling Smørgrav 	unsigned int siglen;
4027b5038d7SDag-Erling Smørgrav 	ldns_rdf *sigdata_rdf;
4037b5038d7SDag-Erling Smørgrav 	ldns_buffer *b64sig;
4047b5038d7SDag-Erling Smørgrav 	EVP_MD_CTX ctx;
4057b5038d7SDag-Erling Smørgrav 	const EVP_MD *md_type;
4067b5038d7SDag-Erling Smørgrav 	int r;
4077b5038d7SDag-Erling Smørgrav 
4087b5038d7SDag-Erling Smørgrav 	siglen = 0;
4097b5038d7SDag-Erling Smørgrav 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
4107b5038d7SDag-Erling Smørgrav 	if (!b64sig) {
4117b5038d7SDag-Erling Smørgrav 		return NULL;
4127b5038d7SDag-Erling Smørgrav 	}
4137b5038d7SDag-Erling Smørgrav 
4147b5038d7SDag-Erling Smørgrav 	/* initializes a signing context */
4157b5038d7SDag-Erling Smørgrav 	md_type = digest_type;
4167b5038d7SDag-Erling Smørgrav 	if(!md_type) {
4177b5038d7SDag-Erling Smørgrav 		/* unknown message difest */
4187b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
4197b5038d7SDag-Erling Smørgrav 		return NULL;
4207b5038d7SDag-Erling Smørgrav 	}
4217b5038d7SDag-Erling Smørgrav 
4227b5038d7SDag-Erling Smørgrav 	EVP_MD_CTX_init(&ctx);
4237b5038d7SDag-Erling Smørgrav 	r = EVP_SignInit(&ctx, md_type);
4247b5038d7SDag-Erling Smørgrav 	if(r == 1) {
4257b5038d7SDag-Erling Smørgrav 		r = EVP_SignUpdate(&ctx, (unsigned char*)
4267b5038d7SDag-Erling Smørgrav 					    ldns_buffer_begin(to_sign),
4277b5038d7SDag-Erling Smørgrav 					    ldns_buffer_position(to_sign));
4287b5038d7SDag-Erling Smørgrav 	} else {
4297b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
4307b5038d7SDag-Erling Smørgrav 		return NULL;
4317b5038d7SDag-Erling Smørgrav 	}
4327b5038d7SDag-Erling Smørgrav 	if(r == 1) {
4337b5038d7SDag-Erling Smørgrav 		r = EVP_SignFinal(&ctx, (unsigned char*)
4347b5038d7SDag-Erling Smørgrav 					   ldns_buffer_begin(b64sig), &siglen, key);
4357b5038d7SDag-Erling Smørgrav 	} else {
4367b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
4377b5038d7SDag-Erling Smørgrav 		return NULL;
4387b5038d7SDag-Erling Smørgrav 	}
4397b5038d7SDag-Erling Smørgrav 	if(r != 1) {
4407b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
4417b5038d7SDag-Erling Smørgrav 		return NULL;
4427b5038d7SDag-Erling Smørgrav 	}
4437b5038d7SDag-Erling Smørgrav 
4447b5038d7SDag-Erling Smørgrav 	/* unfortunately, OpenSSL output is differenct from DNS DSA format */
4457b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
4467b5038d7SDag-Erling Smørgrav 	if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
4477b5038d7SDag-Erling Smørgrav 		sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
4487b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
4497b5038d7SDag-Erling Smørgrav         } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC &&
4507b5038d7SDag-Erling Smørgrav                 ldns_pkey_is_ecdsa(key)) {
4517b5038d7SDag-Erling Smørgrav                 sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen);
4527b5038d7SDag-Erling Smørgrav #endif
4537b5038d7SDag-Erling Smørgrav 	} else {
4547b5038d7SDag-Erling Smørgrav 		/* ok output for other types is the same */
4557b5038d7SDag-Erling Smørgrav 		sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
4567b5038d7SDag-Erling Smørgrav 									 ldns_buffer_begin(b64sig));
4577b5038d7SDag-Erling Smørgrav 	}
4587b5038d7SDag-Erling Smørgrav #endif /* splint */
4597b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(b64sig);
4607b5038d7SDag-Erling Smørgrav 	EVP_MD_CTX_cleanup(&ctx);
4617b5038d7SDag-Erling Smørgrav 	return sigdata_rdf;
4627b5038d7SDag-Erling Smørgrav }
4637b5038d7SDag-Erling Smørgrav 
4647b5038d7SDag-Erling Smørgrav ldns_rdf *
4657b5038d7SDag-Erling Smørgrav ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
4667b5038d7SDag-Erling Smørgrav {
4677b5038d7SDag-Erling Smørgrav 	unsigned char *sha1_hash;
4687b5038d7SDag-Erling Smørgrav 	unsigned int siglen;
4697b5038d7SDag-Erling Smørgrav 	ldns_rdf *sigdata_rdf;
4707b5038d7SDag-Erling Smørgrav 	ldns_buffer *b64sig;
4717b5038d7SDag-Erling Smørgrav 	int result;
4727b5038d7SDag-Erling Smørgrav 
4737b5038d7SDag-Erling Smørgrav 	siglen = 0;
4747b5038d7SDag-Erling Smørgrav 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
4757b5038d7SDag-Erling Smørgrav 	if (!b64sig) {
4767b5038d7SDag-Erling Smørgrav 		return NULL;
4777b5038d7SDag-Erling Smørgrav 	}
4787b5038d7SDag-Erling Smørgrav 
4797b5038d7SDag-Erling Smørgrav 	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
4807b5038d7SDag-Erling Smørgrav 				  ldns_buffer_position(to_sign), NULL);
4817b5038d7SDag-Erling Smørgrav 	if (!sha1_hash) {
4827b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
4837b5038d7SDag-Erling Smørgrav 		return NULL;
4847b5038d7SDag-Erling Smørgrav 	}
4857b5038d7SDag-Erling Smørgrav 
4867b5038d7SDag-Erling Smørgrav 	result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
4877b5038d7SDag-Erling Smørgrav 				   (unsigned char*)ldns_buffer_begin(b64sig),
4887b5038d7SDag-Erling Smørgrav 				   &siglen, key);
4897b5038d7SDag-Erling Smørgrav 	if (result != 1) {
490*2787e39aSDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
4917b5038d7SDag-Erling Smørgrav 		return NULL;
4927b5038d7SDag-Erling Smørgrav 	}
4937b5038d7SDag-Erling Smørgrav 
4947b5038d7SDag-Erling Smørgrav 	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
4957b5038d7SDag-Erling Smørgrav 								 ldns_buffer_begin(b64sig));
4967b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(b64sig); /* can't free this buffer ?? */
4977b5038d7SDag-Erling Smørgrav 	return sigdata_rdf;
4987b5038d7SDag-Erling Smørgrav }
4997b5038d7SDag-Erling Smørgrav 
5007b5038d7SDag-Erling Smørgrav ldns_rdf *
5017b5038d7SDag-Erling Smørgrav ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
5027b5038d7SDag-Erling Smørgrav {
5037b5038d7SDag-Erling Smørgrav 	unsigned char *md5_hash;
5047b5038d7SDag-Erling Smørgrav 	unsigned int siglen;
5057b5038d7SDag-Erling Smørgrav 	ldns_rdf *sigdata_rdf;
5067b5038d7SDag-Erling Smørgrav 	ldns_buffer *b64sig;
5077b5038d7SDag-Erling Smørgrav 
5087b5038d7SDag-Erling Smørgrav 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
5097b5038d7SDag-Erling Smørgrav 	if (!b64sig) {
5107b5038d7SDag-Erling Smørgrav 		return NULL;
5117b5038d7SDag-Erling Smørgrav 	}
5127b5038d7SDag-Erling Smørgrav 
5137b5038d7SDag-Erling Smørgrav 	md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
5147b5038d7SDag-Erling Smørgrav 				ldns_buffer_position(to_sign), NULL);
5157b5038d7SDag-Erling Smørgrav 	if (!md5_hash) {
5167b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(b64sig);
5177b5038d7SDag-Erling Smørgrav 		return NULL;
5187b5038d7SDag-Erling Smørgrav 	}
5197b5038d7SDag-Erling Smørgrav 
5207b5038d7SDag-Erling Smørgrav 	RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
5217b5038d7SDag-Erling Smørgrav 		    (unsigned char*)ldns_buffer_begin(b64sig),
5227b5038d7SDag-Erling Smørgrav 		    &siglen, key);
5237b5038d7SDag-Erling Smørgrav 
5247b5038d7SDag-Erling Smørgrav 	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
5257b5038d7SDag-Erling Smørgrav 								 ldns_buffer_begin(b64sig));
5267b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(b64sig);
5277b5038d7SDag-Erling Smørgrav 	return sigdata_rdf;
5287b5038d7SDag-Erling Smørgrav }
5297b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
5307b5038d7SDag-Erling Smørgrav 
5317b5038d7SDag-Erling Smørgrav /**
5327b5038d7SDag-Erling Smørgrav  * Pushes all rrs from the rrsets of type A and AAAA on gluelist.
5337b5038d7SDag-Erling Smørgrav  */
5347b5038d7SDag-Erling Smørgrav static ldns_status
5357b5038d7SDag-Erling Smørgrav ldns_dnssec_addresses_on_glue_list(
5367b5038d7SDag-Erling Smørgrav 		ldns_dnssec_rrsets *cur_rrset,
5377b5038d7SDag-Erling Smørgrav 		ldns_rr_list *glue_list)
5387b5038d7SDag-Erling Smørgrav {
5397b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *cur_rrs;
5407b5038d7SDag-Erling Smørgrav 	while (cur_rrset) {
5417b5038d7SDag-Erling Smørgrav 		if (cur_rrset->type == LDNS_RR_TYPE_A
5427b5038d7SDag-Erling Smørgrav 				|| cur_rrset->type == LDNS_RR_TYPE_AAAA) {
5437b5038d7SDag-Erling Smørgrav 			for (cur_rrs = cur_rrset->rrs;
5447b5038d7SDag-Erling Smørgrav 					cur_rrs;
5457b5038d7SDag-Erling Smørgrav 					cur_rrs = cur_rrs->next) {
5467b5038d7SDag-Erling Smørgrav 				if (cur_rrs->rr) {
5477b5038d7SDag-Erling Smørgrav 					if (!ldns_rr_list_push_rr(glue_list,
5487b5038d7SDag-Erling Smørgrav 							cur_rrs->rr)) {
5497b5038d7SDag-Erling Smørgrav 						return LDNS_STATUS_MEM_ERR;
5507b5038d7SDag-Erling Smørgrav 						/* ldns_rr_list_push_rr()
5517b5038d7SDag-Erling Smørgrav 						 * returns false when unable
5527b5038d7SDag-Erling Smørgrav 						 * to increase the capacity
5537b5038d7SDag-Erling Smørgrav 						 * of the ldsn_rr_list
5547b5038d7SDag-Erling Smørgrav 						 */
5557b5038d7SDag-Erling Smørgrav 					}
5567b5038d7SDag-Erling Smørgrav 				}
5577b5038d7SDag-Erling Smørgrav 			}
5587b5038d7SDag-Erling Smørgrav 		}
5597b5038d7SDag-Erling Smørgrav 		cur_rrset = cur_rrset->next;
5607b5038d7SDag-Erling Smørgrav 	}
5617b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
5627b5038d7SDag-Erling Smørgrav }
5637b5038d7SDag-Erling Smørgrav 
5647b5038d7SDag-Erling Smørgrav /**
5657b5038d7SDag-Erling Smørgrav  * Marks the names in the zone that are occluded. Those names will be skipped
5667b5038d7SDag-Erling Smørgrav  * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
5677b5038d7SDag-Erling Smørgrav  * function. But watch out! Names that are partially occluded (like glue with
5687b5038d7SDag-Erling Smørgrav  * the same name as the delegation) will not be marked and should specifically
5697b5038d7SDag-Erling Smørgrav  * be taken into account seperately.
5707b5038d7SDag-Erling Smørgrav  *
5717b5038d7SDag-Erling Smørgrav  * When glue_list is given (not NULL), in the process of marking the names, all
5727b5038d7SDag-Erling Smørgrav  * glue resource records will be pushed to that list, even glue at delegation names.
5737b5038d7SDag-Erling Smørgrav  *
5747b5038d7SDag-Erling Smørgrav  * \param[in] zone the zone in which to mark the names
5757b5038d7SDag-Erling Smørgrav  * \param[in] glue_list the list to which to push the glue rrs
5767b5038d7SDag-Erling Smørgrav  * \return LDNS_STATUS_OK on success, an error code otherwise
5777b5038d7SDag-Erling Smørgrav  */
5787b5038d7SDag-Erling Smørgrav ldns_status
5797b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone,
5807b5038d7SDag-Erling Smørgrav 	ldns_rr_list *glue_list)
5817b5038d7SDag-Erling Smørgrav {
5827b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t    *node;
5837b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *name;
5847b5038d7SDag-Erling Smørgrav 	ldns_rdf         *owner;
5857b5038d7SDag-Erling Smørgrav 	ldns_rdf         *cut = NULL; /* keeps track of zone cuts */
5867b5038d7SDag-Erling Smørgrav 	/* When the cut is caused by a delegation, below_delegation will be 1.
5877b5038d7SDag-Erling Smørgrav 	 * When caused by a DNAME, below_delegation will be 0.
5887b5038d7SDag-Erling Smørgrav 	 */
5897b5038d7SDag-Erling Smørgrav 	int below_delegation = -1; /* init suppresses comiler warning */
5907b5038d7SDag-Erling Smørgrav 	ldns_status s;
5917b5038d7SDag-Erling Smørgrav 
5927b5038d7SDag-Erling Smørgrav 	if (!zone || !zone->names) {
5937b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_NULL;
5947b5038d7SDag-Erling Smørgrav 	}
5957b5038d7SDag-Erling Smørgrav 	for (node = ldns_rbtree_first(zone->names);
5967b5038d7SDag-Erling Smørgrav 			node != LDNS_RBTREE_NULL;
5977b5038d7SDag-Erling Smørgrav 			node = ldns_rbtree_next(node)) {
5987b5038d7SDag-Erling Smørgrav 		name = (ldns_dnssec_name *) node->data;
5997b5038d7SDag-Erling Smørgrav 		owner = ldns_dnssec_name_name(name);
6007b5038d7SDag-Erling Smørgrav 
6017b5038d7SDag-Erling Smørgrav 		if (cut) {
6027b5038d7SDag-Erling Smørgrav 			/* The previous node was a zone cut, or a subdomain
6037b5038d7SDag-Erling Smørgrav 			 * below a zone cut. Is this node (still) a subdomain
6047b5038d7SDag-Erling Smørgrav 			 * below the cut? Then the name is occluded. Unless
6057b5038d7SDag-Erling Smørgrav 			 * the name contains a SOA, after which we are
6067b5038d7SDag-Erling Smørgrav 			 * authoritative again.
6077b5038d7SDag-Erling Smørgrav 			 *
6087b5038d7SDag-Erling Smørgrav 			 * FIXME! If there are labels in between the SOA and
6097b5038d7SDag-Erling Smørgrav 			 * the cut, going from the authoritative space (below
6107b5038d7SDag-Erling Smørgrav 			 * the SOA) up into occluded space again, will not be
6117b5038d7SDag-Erling Smørgrav 			 * detected with the contruct below!
6127b5038d7SDag-Erling Smørgrav 			 */
6137b5038d7SDag-Erling Smørgrav 			if (ldns_dname_is_subdomain(owner, cut) &&
6147b5038d7SDag-Erling Smørgrav 					!ldns_dnssec_rrsets_contains_type(
6157b5038d7SDag-Erling Smørgrav 					name->rrsets, LDNS_RR_TYPE_SOA)) {
6167b5038d7SDag-Erling Smørgrav 
6177b5038d7SDag-Erling Smørgrav 				if (below_delegation && glue_list) {
6187b5038d7SDag-Erling Smørgrav 					s = ldns_dnssec_addresses_on_glue_list(
6197b5038d7SDag-Erling Smørgrav 						name->rrsets, glue_list);
6207b5038d7SDag-Erling Smørgrav 					if (s != LDNS_STATUS_OK) {
6217b5038d7SDag-Erling Smørgrav 						return s;
6227b5038d7SDag-Erling Smørgrav 					}
6237b5038d7SDag-Erling Smørgrav 				}
6247b5038d7SDag-Erling Smørgrav 				name->is_glue = true; /* Mark occluded name! */
6257b5038d7SDag-Erling Smørgrav 				continue;
6267b5038d7SDag-Erling Smørgrav 			} else {
6277b5038d7SDag-Erling Smørgrav 				cut = NULL;
6287b5038d7SDag-Erling Smørgrav 			}
6297b5038d7SDag-Erling Smørgrav 		}
6307b5038d7SDag-Erling Smørgrav 
6317b5038d7SDag-Erling Smørgrav 		/* The node is not below a zone cut. Is it a zone cut itself?
6327b5038d7SDag-Erling Smørgrav 		 * Everything below a SOA is authoritative of course; Except
6337b5038d7SDag-Erling Smørgrav 		 * when the name also contains a DNAME :).
6347b5038d7SDag-Erling Smørgrav 		 */
6357b5038d7SDag-Erling Smørgrav 		if (ldns_dnssec_rrsets_contains_type(
6367b5038d7SDag-Erling Smørgrav 				name->rrsets, LDNS_RR_TYPE_NS)
6377b5038d7SDag-Erling Smørgrav 			    && !ldns_dnssec_rrsets_contains_type(
6387b5038d7SDag-Erling Smørgrav 				name->rrsets, LDNS_RR_TYPE_SOA)) {
6397b5038d7SDag-Erling Smørgrav 			cut = owner;
6407b5038d7SDag-Erling Smørgrav 			below_delegation = 1;
6417b5038d7SDag-Erling Smørgrav 			if (glue_list) { /* record glue on the zone cut */
6427b5038d7SDag-Erling Smørgrav 				s = ldns_dnssec_addresses_on_glue_list(
6437b5038d7SDag-Erling Smørgrav 					name->rrsets, glue_list);
6447b5038d7SDag-Erling Smørgrav 				if (s != LDNS_STATUS_OK) {
6457b5038d7SDag-Erling Smørgrav 					return s;
6467b5038d7SDag-Erling Smørgrav 				}
6477b5038d7SDag-Erling Smørgrav 			}
6487b5038d7SDag-Erling Smørgrav 		} else if (ldns_dnssec_rrsets_contains_type(
6497b5038d7SDag-Erling Smørgrav 				name->rrsets, LDNS_RR_TYPE_DNAME)) {
6507b5038d7SDag-Erling Smørgrav 			cut = owner;
6517b5038d7SDag-Erling Smørgrav 			below_delegation = 0;
6527b5038d7SDag-Erling Smørgrav 		}
6537b5038d7SDag-Erling Smørgrav 	}
6547b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
6557b5038d7SDag-Erling Smørgrav }
6567b5038d7SDag-Erling Smørgrav 
6577b5038d7SDag-Erling Smørgrav /**
6587b5038d7SDag-Erling Smørgrav  * Marks the names in the zone that are occluded. Those names will be skipped
6597b5038d7SDag-Erling Smørgrav  * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
6607b5038d7SDag-Erling Smørgrav  * function. But watch out! Names that are partially occluded (like glue with
6617b5038d7SDag-Erling Smørgrav  * the same name as the delegation) will not be marked and should specifically
6627b5038d7SDag-Erling Smørgrav  * be taken into account seperately.
6637b5038d7SDag-Erling Smørgrav  *
6647b5038d7SDag-Erling Smørgrav  * \param[in] zone the zone in which to mark the names
6657b5038d7SDag-Erling Smørgrav  * \return LDNS_STATUS_OK on success, an error code otherwise
6667b5038d7SDag-Erling Smørgrav  */
6677b5038d7SDag-Erling Smørgrav ldns_status
6687b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
6697b5038d7SDag-Erling Smørgrav {
6707b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_mark_and_get_glue(zone, NULL);
6717b5038d7SDag-Erling Smørgrav }
6727b5038d7SDag-Erling Smørgrav 
6737b5038d7SDag-Erling Smørgrav ldns_rbnode_t *
6747b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
6757b5038d7SDag-Erling Smørgrav {
6767b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *next_node = NULL;
6777b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *next_name = NULL;
6787b5038d7SDag-Erling Smørgrav 	bool done = false;
6797b5038d7SDag-Erling Smørgrav 
6807b5038d7SDag-Erling Smørgrav 	if (node == LDNS_RBTREE_NULL) {
6817b5038d7SDag-Erling Smørgrav 		return NULL;
6827b5038d7SDag-Erling Smørgrav 	}
6837b5038d7SDag-Erling Smørgrav 	next_node = node;
6847b5038d7SDag-Erling Smørgrav 	while (!done) {
6857b5038d7SDag-Erling Smørgrav 		if (next_node == LDNS_RBTREE_NULL) {
6867b5038d7SDag-Erling Smørgrav 			return NULL;
6877b5038d7SDag-Erling Smørgrav 		} else {
6887b5038d7SDag-Erling Smørgrav 			next_name = (ldns_dnssec_name *)next_node->data;
6897b5038d7SDag-Erling Smørgrav 			if (!next_name->is_glue) {
6907b5038d7SDag-Erling Smørgrav 				done = true;
6917b5038d7SDag-Erling Smørgrav 			} else {
6927b5038d7SDag-Erling Smørgrav 				next_node = ldns_rbtree_next(next_node);
6937b5038d7SDag-Erling Smørgrav 			}
6947b5038d7SDag-Erling Smørgrav 		}
6957b5038d7SDag-Erling Smørgrav 	}
6967b5038d7SDag-Erling Smørgrav 	return next_node;
6977b5038d7SDag-Erling Smørgrav }
6987b5038d7SDag-Erling Smørgrav 
6997b5038d7SDag-Erling Smørgrav ldns_status
7007b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
7017b5038d7SDag-Erling Smørgrav                               ldns_rr_list *new_rrs)
7027b5038d7SDag-Erling Smørgrav {
7037b5038d7SDag-Erling Smørgrav 
7047b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *first_node, *cur_node, *next_node;
7057b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *cur_name, *next_name;
7067b5038d7SDag-Erling Smørgrav 	ldns_rr *nsec_rr;
7077b5038d7SDag-Erling Smørgrav 	uint32_t nsec_ttl;
7087b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *soa;
7097b5038d7SDag-Erling Smørgrav 
7107b5038d7SDag-Erling Smørgrav 	/* the TTL of NSEC rrs should be set to the minimum TTL of
7117b5038d7SDag-Erling Smørgrav 	 * the zone SOA (RFC4035 Section 2.3)
7127b5038d7SDag-Erling Smørgrav 	 */
7137b5038d7SDag-Erling Smørgrav 	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
7147b5038d7SDag-Erling Smørgrav 
7157b5038d7SDag-Erling Smørgrav 	/* did the caller actually set it? if not,
7167b5038d7SDag-Erling Smørgrav 	 * fall back to default ttl
7177b5038d7SDag-Erling Smørgrav 	 */
7187b5038d7SDag-Erling Smørgrav 	if (soa && soa->rrs && soa->rrs->rr
7197b5038d7SDag-Erling Smørgrav 			&& (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) {
7207b5038d7SDag-Erling Smørgrav 		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
7217b5038d7SDag-Erling Smørgrav 	} else {
7227b5038d7SDag-Erling Smørgrav 		nsec_ttl = LDNS_DEFAULT_TTL;
7237b5038d7SDag-Erling Smørgrav 	}
7247b5038d7SDag-Erling Smørgrav 
7257b5038d7SDag-Erling Smørgrav 	first_node = ldns_dnssec_name_node_next_nonglue(
7267b5038d7SDag-Erling Smørgrav 			       ldns_rbtree_first(zone->names));
7277b5038d7SDag-Erling Smørgrav 	cur_node = first_node;
7287b5038d7SDag-Erling Smørgrav 	if (cur_node) {
7297b5038d7SDag-Erling Smørgrav 		next_node = ldns_dnssec_name_node_next_nonglue(
7307b5038d7SDag-Erling Smørgrav 			           ldns_rbtree_next(cur_node));
7317b5038d7SDag-Erling Smørgrav 	} else {
7327b5038d7SDag-Erling Smørgrav 		next_node = NULL;
7337b5038d7SDag-Erling Smørgrav 	}
7347b5038d7SDag-Erling Smørgrav 
7357b5038d7SDag-Erling Smørgrav 	while (cur_node && next_node) {
7367b5038d7SDag-Erling Smørgrav 		cur_name = (ldns_dnssec_name *)cur_node->data;
7377b5038d7SDag-Erling Smørgrav 		next_name = (ldns_dnssec_name *)next_node->data;
7387b5038d7SDag-Erling Smørgrav 		nsec_rr = ldns_dnssec_create_nsec(cur_name,
7397b5038d7SDag-Erling Smørgrav 		                                  next_name,
7407b5038d7SDag-Erling Smørgrav 		                                  LDNS_RR_TYPE_NSEC);
7417b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
7427b5038d7SDag-Erling Smørgrav 		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
7437b5038d7SDag-Erling Smørgrav 			ldns_rr_free(nsec_rr);
7447b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_ERR;
7457b5038d7SDag-Erling Smørgrav 		}
7467b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(new_rrs, nsec_rr);
7477b5038d7SDag-Erling Smørgrav 		cur_node = next_node;
7487b5038d7SDag-Erling Smørgrav 		if (cur_node) {
7497b5038d7SDag-Erling Smørgrav 			next_node = ldns_dnssec_name_node_next_nonglue(
7507b5038d7SDag-Erling Smørgrav                                ldns_rbtree_next(cur_node));
7517b5038d7SDag-Erling Smørgrav 		}
7527b5038d7SDag-Erling Smørgrav 	}
7537b5038d7SDag-Erling Smørgrav 
7547b5038d7SDag-Erling Smørgrav 	if (cur_node && !next_node) {
7557b5038d7SDag-Erling Smørgrav 		cur_name = (ldns_dnssec_name *)cur_node->data;
7567b5038d7SDag-Erling Smørgrav 		next_name = (ldns_dnssec_name *)first_node->data;
7577b5038d7SDag-Erling Smørgrav 		nsec_rr = ldns_dnssec_create_nsec(cur_name,
7587b5038d7SDag-Erling Smørgrav 		                                  next_name,
7597b5038d7SDag-Erling Smørgrav 		                                  LDNS_RR_TYPE_NSEC);
7607b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
7617b5038d7SDag-Erling Smørgrav 		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
7627b5038d7SDag-Erling Smørgrav 			ldns_rr_free(nsec_rr);
7637b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_ERR;
7647b5038d7SDag-Erling Smørgrav 		}
7657b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(new_rrs, nsec_rr);
7667b5038d7SDag-Erling Smørgrav 	} else {
7677b5038d7SDag-Erling Smørgrav 		printf("error\n");
7687b5038d7SDag-Erling Smørgrav 	}
7697b5038d7SDag-Erling Smørgrav 
7707b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
7717b5038d7SDag-Erling Smørgrav }
7727b5038d7SDag-Erling Smørgrav 
7737b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
7747b5038d7SDag-Erling Smørgrav /* in dnssec_zone.c */
7757b5038d7SDag-Erling Smørgrav extern int ldns_dname_compare_v(const void *a, const void *b);
7767b5038d7SDag-Erling Smørgrav 
7777b5038d7SDag-Erling Smørgrav static ldns_status
7787b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
7797b5038d7SDag-Erling Smørgrav 		ldns_rr_list *new_rrs,
7807b5038d7SDag-Erling Smørgrav 		uint8_t algorithm,
7817b5038d7SDag-Erling Smørgrav 		uint8_t flags,
7827b5038d7SDag-Erling Smørgrav 		uint16_t iterations,
7837b5038d7SDag-Erling Smørgrav 		uint8_t salt_length,
7847b5038d7SDag-Erling Smørgrav 		uint8_t *salt,
7857b5038d7SDag-Erling Smørgrav 		ldns_rbtree_t **map)
7867b5038d7SDag-Erling Smørgrav {
7877b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *first_name_node;
7887b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *current_name_node;
7897b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *current_name;
7907b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
7917b5038d7SDag-Erling Smørgrav 	ldns_rr *nsec_rr;
7927b5038d7SDag-Erling Smørgrav 	ldns_rr_list *nsec3_list;
7937b5038d7SDag-Erling Smørgrav 	uint32_t nsec_ttl;
7947b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *soa;
7957b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *hashmap_node;
7967b5038d7SDag-Erling Smørgrav 
7977b5038d7SDag-Erling Smørgrav 	if (!zone || !new_rrs || !zone->names) {
7987b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
7997b5038d7SDag-Erling Smørgrav 	}
8007b5038d7SDag-Erling Smørgrav 
8017b5038d7SDag-Erling Smørgrav 	/* the TTL of NSEC rrs should be set to the minimum TTL of
8027b5038d7SDag-Erling Smørgrav 	 * the zone SOA (RFC4035 Section 2.3)
8037b5038d7SDag-Erling Smørgrav 	 */
8047b5038d7SDag-Erling Smørgrav 	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
8057b5038d7SDag-Erling Smørgrav 
8067b5038d7SDag-Erling Smørgrav 	/* did the caller actually set it? if not,
8077b5038d7SDag-Erling Smørgrav 	 * fall back to default ttl
8087b5038d7SDag-Erling Smørgrav 	 */
8097b5038d7SDag-Erling Smørgrav 	if (soa && soa->rrs && soa->rrs->rr
8107b5038d7SDag-Erling Smørgrav 			&& ldns_rr_rdf(soa->rrs->rr, 6) != NULL) {
8117b5038d7SDag-Erling Smørgrav 		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
8127b5038d7SDag-Erling Smørgrav 	} else {
8137b5038d7SDag-Erling Smørgrav 		nsec_ttl = LDNS_DEFAULT_TTL;
8147b5038d7SDag-Erling Smørgrav 	}
8157b5038d7SDag-Erling Smørgrav 
8167b5038d7SDag-Erling Smørgrav 	if (map) {
8177b5038d7SDag-Erling Smørgrav 		if ((*map = ldns_rbtree_create(ldns_dname_compare_v))
8187b5038d7SDag-Erling Smørgrav 				== NULL) {
8197b5038d7SDag-Erling Smørgrav 			map = NULL;
8207b5038d7SDag-Erling Smørgrav 		};
8217b5038d7SDag-Erling Smørgrav 	}
8227b5038d7SDag-Erling Smørgrav 	nsec3_list = ldns_rr_list_new();
8237b5038d7SDag-Erling Smørgrav 
8247b5038d7SDag-Erling Smørgrav 	first_name_node = ldns_dnssec_name_node_next_nonglue(
8257b5038d7SDag-Erling Smørgrav 					  ldns_rbtree_first(zone->names));
8267b5038d7SDag-Erling Smørgrav 
8277b5038d7SDag-Erling Smørgrav 	current_name_node = first_name_node;
8287b5038d7SDag-Erling Smørgrav 
8297b5038d7SDag-Erling Smørgrav 	while (current_name_node &&
8307b5038d7SDag-Erling Smørgrav 	       current_name_node != LDNS_RBTREE_NULL) {
8317b5038d7SDag-Erling Smørgrav 		current_name = (ldns_dnssec_name *) current_name_node->data;
8327b5038d7SDag-Erling Smørgrav 		nsec_rr = ldns_dnssec_create_nsec3(current_name,
8337b5038d7SDag-Erling Smørgrav 		                                   NULL,
8347b5038d7SDag-Erling Smørgrav 		                                   zone->soa->name,
8357b5038d7SDag-Erling Smørgrav 		                                   algorithm,
8367b5038d7SDag-Erling Smørgrav 		                                   flags,
8377b5038d7SDag-Erling Smørgrav 		                                   iterations,
8387b5038d7SDag-Erling Smørgrav 		                                   salt_length,
8397b5038d7SDag-Erling Smørgrav 		                                   salt);
8407b5038d7SDag-Erling Smørgrav 		/* by default, our nsec based generator adds rrsigs
8417b5038d7SDag-Erling Smørgrav 		 * remove the bitmap for empty nonterminals */
8427b5038d7SDag-Erling Smørgrav 		if (!current_name->rrsets) {
8437b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
8447b5038d7SDag-Erling Smørgrav 		}
8457b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
8467b5038d7SDag-Erling Smørgrav 		result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
8477b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(new_rrs, nsec_rr);
8487b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(nsec3_list, nsec_rr);
8497b5038d7SDag-Erling Smørgrav 		if (map) {
8507b5038d7SDag-Erling Smørgrav 			hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
8517b5038d7SDag-Erling Smørgrav 			if (hashmap_node && ldns_rr_owner(nsec_rr)) {
8527b5038d7SDag-Erling Smørgrav 				hashmap_node->key = ldns_dname_label(
8537b5038d7SDag-Erling Smørgrav 					ldns_rr_owner(nsec_rr), 0);
8547b5038d7SDag-Erling Smørgrav 				if (hashmap_node->key) {
8557b5038d7SDag-Erling Smørgrav 					hashmap_node->data = current_name->name;
8567b5038d7SDag-Erling Smørgrav 					(void) ldns_rbtree_insert(
8577b5038d7SDag-Erling Smørgrav 							*map, hashmap_node);
8587b5038d7SDag-Erling Smørgrav 				}
8597b5038d7SDag-Erling Smørgrav 			}
8607b5038d7SDag-Erling Smørgrav 		}
8617b5038d7SDag-Erling Smørgrav 		current_name_node = ldns_dnssec_name_node_next_nonglue(
8627b5038d7SDag-Erling Smørgrav 		                   ldns_rbtree_next(current_name_node));
8637b5038d7SDag-Erling Smørgrav 	}
8647b5038d7SDag-Erling Smørgrav 	if (result != LDNS_STATUS_OK) {
865*2787e39aSDag-Erling Smørgrav 		ldns_rr_list_free(nsec3_list);
8667b5038d7SDag-Erling Smørgrav 		return result;
8677b5038d7SDag-Erling Smørgrav 	}
8687b5038d7SDag-Erling Smørgrav 
8697b5038d7SDag-Erling Smørgrav 	ldns_rr_list_sort_nsec3(nsec3_list);
8707b5038d7SDag-Erling Smørgrav 	result = ldns_dnssec_chain_nsec3_list(nsec3_list);
8717b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(nsec3_list);
872*2787e39aSDag-Erling Smørgrav 
8737b5038d7SDag-Erling Smørgrav 	return result;
8747b5038d7SDag-Erling Smørgrav }
8757b5038d7SDag-Erling Smørgrav 
8767b5038d7SDag-Erling Smørgrav ldns_status
8777b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
8787b5038d7SDag-Erling Smørgrav 		ldns_rr_list *new_rrs,
8797b5038d7SDag-Erling Smørgrav 		uint8_t algorithm,
8807b5038d7SDag-Erling Smørgrav 		uint8_t flags,
8817b5038d7SDag-Erling Smørgrav 		uint16_t iterations,
8827b5038d7SDag-Erling Smørgrav 		uint8_t salt_length,
8837b5038d7SDag-Erling Smørgrav 		uint8_t *salt)
8847b5038d7SDag-Erling Smørgrav {
8857b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm,
8867b5038d7SDag-Erling Smørgrav 		       	flags, iterations, salt_length, salt, NULL);
8877b5038d7SDag-Erling Smørgrav 
8887b5038d7SDag-Erling Smørgrav }
8897b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
8907b5038d7SDag-Erling Smørgrav 
8917b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs *
8927b5038d7SDag-Erling Smørgrav ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures
8937b5038d7SDag-Erling Smørgrav 			     , ATTR_UNUSED(ldns_key_list *key_list)
8947b5038d7SDag-Erling Smørgrav 			     , int (*func)(ldns_rr *, void *)
8957b5038d7SDag-Erling Smørgrav 			     , void *arg
8967b5038d7SDag-Erling Smørgrav 			     )
8977b5038d7SDag-Erling Smørgrav {
8987b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *base_rrs = signatures;
8997b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *cur_rr = base_rrs;
9007b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *prev_rr = NULL;
9017b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *next_rr;
9027b5038d7SDag-Erling Smørgrav 
9037b5038d7SDag-Erling Smørgrav 	uint16_t keytag;
9047b5038d7SDag-Erling Smørgrav 	size_t i;
9057b5038d7SDag-Erling Smørgrav 
9067b5038d7SDag-Erling Smørgrav 	if (!cur_rr) {
9077b5038d7SDag-Erling Smørgrav 		switch(func(NULL, arg)) {
9087b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_LEAVE_ADD_NEW:
9097b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
9107b5038d7SDag-Erling Smørgrav 		break;
9117b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_LEAVE_NO_ADD:
9127b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_REMOVE_NO_ADD:
9137b5038d7SDag-Erling Smørgrav 		ldns_key_list_set_use(key_list, false);
9147b5038d7SDag-Erling Smørgrav 		break;
9157b5038d7SDag-Erling Smørgrav 		default:
9167b5038d7SDag-Erling Smørgrav 			fprintf(stderr, "[XX] unknown return value from callback\n");
9177b5038d7SDag-Erling Smørgrav 			break;
9187b5038d7SDag-Erling Smørgrav 		}
9197b5038d7SDag-Erling Smørgrav 		return NULL;
9207b5038d7SDag-Erling Smørgrav 	}
9217b5038d7SDag-Erling Smørgrav 	(void)func(cur_rr->rr, arg);
9227b5038d7SDag-Erling Smørgrav 
9237b5038d7SDag-Erling Smørgrav 	while (cur_rr) {
9247b5038d7SDag-Erling Smørgrav 		next_rr = cur_rr->next;
9257b5038d7SDag-Erling Smørgrav 
9267b5038d7SDag-Erling Smørgrav 		switch (func(cur_rr->rr, arg)) {
9277b5038d7SDag-Erling Smørgrav 		case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
9287b5038d7SDag-Erling Smørgrav 			prev_rr = cur_rr;
9297b5038d7SDag-Erling Smørgrav 			break;
9307b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_LEAVE_NO_ADD:
9317b5038d7SDag-Erling Smørgrav 			keytag = ldns_rdf2native_int16(
9327b5038d7SDag-Erling Smørgrav 					   ldns_rr_rrsig_keytag(cur_rr->rr));
9337b5038d7SDag-Erling Smørgrav 			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
9347b5038d7SDag-Erling Smørgrav 				if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
9357b5038d7SDag-Erling Smørgrav 				    keytag) {
9367b5038d7SDag-Erling Smørgrav 					ldns_key_set_use(ldns_key_list_key(key_list, i),
9377b5038d7SDag-Erling Smørgrav 								  false);
9387b5038d7SDag-Erling Smørgrav 				}
9397b5038d7SDag-Erling Smørgrav 			}
9407b5038d7SDag-Erling Smørgrav 			prev_rr = cur_rr;
9417b5038d7SDag-Erling Smørgrav 			break;
9427b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_REMOVE_NO_ADD:
9437b5038d7SDag-Erling Smørgrav 			keytag = ldns_rdf2native_int16(
9447b5038d7SDag-Erling Smørgrav 					   ldns_rr_rrsig_keytag(cur_rr->rr));
9457b5038d7SDag-Erling Smørgrav 			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
9467b5038d7SDag-Erling Smørgrav 				if (ldns_key_keytag(ldns_key_list_key(key_list, i))
9477b5038d7SDag-Erling Smørgrav 				    == keytag) {
9487b5038d7SDag-Erling Smørgrav 					ldns_key_set_use(ldns_key_list_key(key_list, i),
9497b5038d7SDag-Erling Smørgrav 								  false);
9507b5038d7SDag-Erling Smørgrav 				}
9517b5038d7SDag-Erling Smørgrav 			}
9527b5038d7SDag-Erling Smørgrav 			if (prev_rr) {
9537b5038d7SDag-Erling Smørgrav 				prev_rr->next = next_rr;
9547b5038d7SDag-Erling Smørgrav 			} else {
9557b5038d7SDag-Erling Smørgrav 				base_rrs = next_rr;
9567b5038d7SDag-Erling Smørgrav 			}
9577b5038d7SDag-Erling Smørgrav 			LDNS_FREE(cur_rr);
9587b5038d7SDag-Erling Smørgrav 			break;
9597b5038d7SDag-Erling Smørgrav 		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
9607b5038d7SDag-Erling Smørgrav 			if (prev_rr) {
9617b5038d7SDag-Erling Smørgrav 				prev_rr->next = next_rr;
9627b5038d7SDag-Erling Smørgrav 			} else {
9637b5038d7SDag-Erling Smørgrav 				base_rrs = next_rr;
9647b5038d7SDag-Erling Smørgrav 			}
9657b5038d7SDag-Erling Smørgrav 			LDNS_FREE(cur_rr);
9667b5038d7SDag-Erling Smørgrav 			break;
9677b5038d7SDag-Erling Smørgrav 		default:
9687b5038d7SDag-Erling Smørgrav 			fprintf(stderr, "[XX] unknown return value from callback\n");
9697b5038d7SDag-Erling Smørgrav 			break;
9707b5038d7SDag-Erling Smørgrav 		}
9717b5038d7SDag-Erling Smørgrav 		cur_rr = next_rr;
9727b5038d7SDag-Erling Smørgrav 	}
9737b5038d7SDag-Erling Smørgrav 
9747b5038d7SDag-Erling Smørgrav 	return base_rrs;
9757b5038d7SDag-Erling Smørgrav }
9767b5038d7SDag-Erling Smørgrav 
9777b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
9787b5038d7SDag-Erling Smørgrav ldns_status
9797b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
9807b5038d7SDag-Erling Smørgrav                                ldns_rr_list *new_rrs,
9817b5038d7SDag-Erling Smørgrav                                ldns_key_list *key_list,
9827b5038d7SDag-Erling Smørgrav                                int (*func)(ldns_rr *, void*),
9837b5038d7SDag-Erling Smørgrav                                void *arg)
9847b5038d7SDag-Erling Smørgrav {
9857b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list,
9867b5038d7SDag-Erling Smørgrav 		func, arg, 0);
9877b5038d7SDag-Erling Smørgrav }
9887b5038d7SDag-Erling Smørgrav 
9897b5038d7SDag-Erling Smørgrav /** If there are KSKs use only them and mark ZSKs unused */
9907b5038d7SDag-Erling Smørgrav static void
9917b5038d7SDag-Erling Smørgrav ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
9927b5038d7SDag-Erling Smørgrav {
9937b5038d7SDag-Erling Smørgrav 	int saw_ksk = 0;
9947b5038d7SDag-Erling Smørgrav 	size_t i;
9957b5038d7SDag-Erling Smørgrav 	for(i=0; i<ldns_key_list_key_count(key_list); i++)
9967b5038d7SDag-Erling Smørgrav 		if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
9977b5038d7SDag-Erling Smørgrav 			saw_ksk = 1;
9987b5038d7SDag-Erling Smørgrav 			break;
9997b5038d7SDag-Erling Smørgrav 		}
10007b5038d7SDag-Erling Smørgrav 	if(!saw_ksk)
10017b5038d7SDag-Erling Smørgrav 		return;
10027b5038d7SDag-Erling Smørgrav 	for(i=0; i<ldns_key_list_key_count(key_list); i++)
10037b5038d7SDag-Erling Smørgrav 		if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
10047b5038d7SDag-Erling Smørgrav 			ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
10057b5038d7SDag-Erling Smørgrav }
10067b5038d7SDag-Erling Smørgrav 
10077b5038d7SDag-Erling Smørgrav /** If there are no ZSKs use KSK as ZSK */
10087b5038d7SDag-Erling Smørgrav static void
10097b5038d7SDag-Erling Smørgrav ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list)
10107b5038d7SDag-Erling Smørgrav {
10117b5038d7SDag-Erling Smørgrav 	int saw_zsk = 0;
10127b5038d7SDag-Erling Smørgrav 	size_t i;
10137b5038d7SDag-Erling Smørgrav 	for(i=0; i<ldns_key_list_key_count(key_list); i++)
10147b5038d7SDag-Erling Smørgrav 		if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
10157b5038d7SDag-Erling Smørgrav 			saw_zsk = 1;
10167b5038d7SDag-Erling Smørgrav 			break;
10177b5038d7SDag-Erling Smørgrav 		}
10187b5038d7SDag-Erling Smørgrav 	if(!saw_zsk)
10197b5038d7SDag-Erling Smørgrav 		return;
10207b5038d7SDag-Erling Smørgrav 	/* else filter all KSKs */
10217b5038d7SDag-Erling Smørgrav 	for(i=0; i<ldns_key_list_key_count(key_list); i++)
10227b5038d7SDag-Erling Smørgrav 		if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
10237b5038d7SDag-Erling Smørgrav 			ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
10247b5038d7SDag-Erling Smørgrav }
10257b5038d7SDag-Erling Smørgrav 
10267b5038d7SDag-Erling Smørgrav ldns_status
1027*2787e39aSDag-Erling Smørgrav ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
1028*2787e39aSDag-Erling Smørgrav 				  , ldns_rr_list *new_rrs
1029*2787e39aSDag-Erling Smørgrav 				  , ldns_key_list *key_list
10307b5038d7SDag-Erling Smørgrav 				  , int (*func)(ldns_rr *, void*)
10317b5038d7SDag-Erling Smørgrav 				  , void *arg
10327b5038d7SDag-Erling Smørgrav 				  , int flags
10337b5038d7SDag-Erling Smørgrav 				  )
10347b5038d7SDag-Erling Smørgrav {
10357b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
10367b5038d7SDag-Erling Smørgrav 
10377b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *cur_node;
10387b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rr_list;
10397b5038d7SDag-Erling Smørgrav 
10407b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *cur_name;
10417b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *cur_rrset;
10427b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *cur_rr;
10437b5038d7SDag-Erling Smørgrav 
10447b5038d7SDag-Erling Smørgrav 	ldns_rr_list *siglist;
10457b5038d7SDag-Erling Smørgrav 
10467b5038d7SDag-Erling Smørgrav 	size_t i;
10477b5038d7SDag-Erling Smørgrav 
10487b5038d7SDag-Erling Smørgrav 	int on_delegation_point = 0; /* handle partially occluded names */
10497b5038d7SDag-Erling Smørgrav 
10507b5038d7SDag-Erling Smørgrav 	ldns_rr_list *pubkey_list = ldns_rr_list_new();
10517b5038d7SDag-Erling Smørgrav 	for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
10527b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr( pubkey_list
10537b5038d7SDag-Erling Smørgrav 				    , ldns_key2rr(ldns_key_list_key(
10547b5038d7SDag-Erling Smørgrav 							key_list, i))
10557b5038d7SDag-Erling Smørgrav 				    );
10567b5038d7SDag-Erling Smørgrav 	}
10577b5038d7SDag-Erling Smørgrav 	/* TODO: callback to see is list should be signed */
10587b5038d7SDag-Erling Smørgrav 	/* TODO: remove 'old' signatures from signature list */
10597b5038d7SDag-Erling Smørgrav 	cur_node = ldns_rbtree_first(zone->names);
10607b5038d7SDag-Erling Smørgrav 	while (cur_node != LDNS_RBTREE_NULL) {
10617b5038d7SDag-Erling Smørgrav 		cur_name = (ldns_dnssec_name *) cur_node->data;
10627b5038d7SDag-Erling Smørgrav 
10637b5038d7SDag-Erling Smørgrav 		if (!cur_name->is_glue) {
10647b5038d7SDag-Erling Smørgrav 			on_delegation_point = ldns_dnssec_rrsets_contains_type(
10657b5038d7SDag-Erling Smørgrav 					cur_name->rrsets, LDNS_RR_TYPE_NS)
10667b5038d7SDag-Erling Smørgrav 				&& !ldns_dnssec_rrsets_contains_type(
10677b5038d7SDag-Erling Smørgrav 					cur_name->rrsets, LDNS_RR_TYPE_SOA);
10687b5038d7SDag-Erling Smørgrav 			cur_rrset = cur_name->rrsets;
10697b5038d7SDag-Erling Smørgrav 			while (cur_rrset) {
10707b5038d7SDag-Erling Smørgrav 				/* reset keys to use */
10717b5038d7SDag-Erling Smørgrav 				ldns_key_list_set_use(key_list, true);
10727b5038d7SDag-Erling Smørgrav 
10737b5038d7SDag-Erling Smørgrav 				/* walk through old sigs, remove the old,
10747b5038d7SDag-Erling Smørgrav 				   and mark which keys (not) to use) */
10757b5038d7SDag-Erling Smørgrav 				cur_rrset->signatures =
10767b5038d7SDag-Erling Smørgrav 					ldns_dnssec_remove_signatures(cur_rrset->signatures,
10777b5038d7SDag-Erling Smørgrav 											key_list,
10787b5038d7SDag-Erling Smørgrav 											func,
10797b5038d7SDag-Erling Smørgrav 											arg);
10807b5038d7SDag-Erling Smørgrav 				if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
10817b5038d7SDag-Erling Smørgrav 					cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
10827b5038d7SDag-Erling Smørgrav 					ldns_key_list_filter_for_dnskey(key_list);
10837b5038d7SDag-Erling Smørgrav 
10847b5038d7SDag-Erling Smørgrav 				if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY)
10857b5038d7SDag-Erling Smørgrav 					ldns_key_list_filter_for_non_dnskey(key_list);
10867b5038d7SDag-Erling Smørgrav 
10877b5038d7SDag-Erling Smørgrav 				/* TODO: just set count to zero? */
10887b5038d7SDag-Erling Smørgrav 				rr_list = ldns_rr_list_new();
10897b5038d7SDag-Erling Smørgrav 
10907b5038d7SDag-Erling Smørgrav 				cur_rr = cur_rrset->rrs;
10917b5038d7SDag-Erling Smørgrav 				while (cur_rr) {
10927b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(rr_list, cur_rr->rr);
10937b5038d7SDag-Erling Smørgrav 					cur_rr = cur_rr->next;
10947b5038d7SDag-Erling Smørgrav 				}
10957b5038d7SDag-Erling Smørgrav 
10967b5038d7SDag-Erling Smørgrav 				/* only sign non-delegation RRsets */
10977b5038d7SDag-Erling Smørgrav 				/* (glue should have been marked earlier,
10987b5038d7SDag-Erling Smørgrav 				 *  except on the delegation points itself) */
10997b5038d7SDag-Erling Smørgrav 				if (!on_delegation_point ||
11007b5038d7SDag-Erling Smørgrav 						ldns_rr_list_type(rr_list)
11017b5038d7SDag-Erling Smørgrav 							== LDNS_RR_TYPE_DS ||
11027b5038d7SDag-Erling Smørgrav 						ldns_rr_list_type(rr_list)
11037b5038d7SDag-Erling Smørgrav 							== LDNS_RR_TYPE_NSEC ||
11047b5038d7SDag-Erling Smørgrav 						ldns_rr_list_type(rr_list)
11057b5038d7SDag-Erling Smørgrav 							== LDNS_RR_TYPE_NSEC3) {
11067b5038d7SDag-Erling Smørgrav 					siglist = ldns_sign_public(rr_list, key_list);
11077b5038d7SDag-Erling Smørgrav 					for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
11087b5038d7SDag-Erling Smørgrav 						if (cur_rrset->signatures) {
11097b5038d7SDag-Erling Smørgrav 							result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
11107b5038d7SDag-Erling Smørgrav 											   ldns_rr_list_rr(siglist,
11117b5038d7SDag-Erling Smørgrav 														    i));
11127b5038d7SDag-Erling Smørgrav 						} else {
11137b5038d7SDag-Erling Smørgrav 							cur_rrset->signatures = ldns_dnssec_rrs_new();
11147b5038d7SDag-Erling Smørgrav 							cur_rrset->signatures->rr =
11157b5038d7SDag-Erling Smørgrav 								ldns_rr_list_rr(siglist, i);
1116*2787e39aSDag-Erling Smørgrav 						}
1117*2787e39aSDag-Erling Smørgrav 						if (new_rrs) {
11187b5038d7SDag-Erling Smørgrav 							ldns_rr_list_push_rr(new_rrs,
11197b5038d7SDag-Erling Smørgrav 												 ldns_rr_list_rr(siglist,
11207b5038d7SDag-Erling Smørgrav 															  i));
11217b5038d7SDag-Erling Smørgrav 						}
11227b5038d7SDag-Erling Smørgrav 					}
11237b5038d7SDag-Erling Smørgrav 					ldns_rr_list_free(siglist);
11247b5038d7SDag-Erling Smørgrav 				}
11257b5038d7SDag-Erling Smørgrav 
11267b5038d7SDag-Erling Smørgrav 				ldns_rr_list_free(rr_list);
11277b5038d7SDag-Erling Smørgrav 
11287b5038d7SDag-Erling Smørgrav 				cur_rrset = cur_rrset->next;
11297b5038d7SDag-Erling Smørgrav 			}
11307b5038d7SDag-Erling Smørgrav 
11317b5038d7SDag-Erling Smørgrav 			/* sign the nsec */
11327b5038d7SDag-Erling Smørgrav 			ldns_key_list_set_use(key_list, true);
11337b5038d7SDag-Erling Smørgrav 			cur_name->nsec_signatures =
11347b5038d7SDag-Erling Smørgrav 				ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
11357b5038d7SDag-Erling Smørgrav 										key_list,
11367b5038d7SDag-Erling Smørgrav 										func,
11377b5038d7SDag-Erling Smørgrav 										arg);
11387b5038d7SDag-Erling Smørgrav 			ldns_key_list_filter_for_non_dnskey(key_list);
11397b5038d7SDag-Erling Smørgrav 
11407b5038d7SDag-Erling Smørgrav 			rr_list = ldns_rr_list_new();
11417b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(rr_list, cur_name->nsec);
11427b5038d7SDag-Erling Smørgrav 			siglist = ldns_sign_public(rr_list, key_list);
11437b5038d7SDag-Erling Smørgrav 
11447b5038d7SDag-Erling Smørgrav 			for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
11457b5038d7SDag-Erling Smørgrav 				if (cur_name->nsec_signatures) {
11467b5038d7SDag-Erling Smørgrav 					result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
11477b5038d7SDag-Erling Smørgrav 									   ldns_rr_list_rr(siglist, i));
11487b5038d7SDag-Erling Smørgrav 				} else {
11497b5038d7SDag-Erling Smørgrav 					cur_name->nsec_signatures = ldns_dnssec_rrs_new();
11507b5038d7SDag-Erling Smørgrav 					cur_name->nsec_signatures->rr =
11517b5038d7SDag-Erling Smørgrav 						ldns_rr_list_rr(siglist, i);
1152*2787e39aSDag-Erling Smørgrav 				}
1153*2787e39aSDag-Erling Smørgrav 				if (new_rrs) {
11547b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(new_rrs,
11557b5038d7SDag-Erling Smørgrav 								 ldns_rr_list_rr(siglist, i));
11567b5038d7SDag-Erling Smørgrav 				}
11577b5038d7SDag-Erling Smørgrav 			}
11587b5038d7SDag-Erling Smørgrav 
11597b5038d7SDag-Erling Smørgrav 			ldns_rr_list_free(siglist);
11607b5038d7SDag-Erling Smørgrav 			ldns_rr_list_free(rr_list);
11617b5038d7SDag-Erling Smørgrav 		}
11627b5038d7SDag-Erling Smørgrav 		cur_node = ldns_rbtree_next(cur_node);
11637b5038d7SDag-Erling Smørgrav 	}
11647b5038d7SDag-Erling Smørgrav 
11657b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(pubkey_list);
11667b5038d7SDag-Erling Smørgrav 	return result;
11677b5038d7SDag-Erling Smørgrav }
11687b5038d7SDag-Erling Smørgrav 
11697b5038d7SDag-Erling Smørgrav ldns_status
11707b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
11717b5038d7SDag-Erling Smørgrav 				  ldns_rr_list *new_rrs,
11727b5038d7SDag-Erling Smørgrav 				  ldns_key_list *key_list,
11737b5038d7SDag-Erling Smørgrav 				  int (*func)(ldns_rr *, void *),
11747b5038d7SDag-Erling Smørgrav 				  void *arg)
11757b5038d7SDag-Erling Smørgrav {
11767b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
11777b5038d7SDag-Erling Smørgrav }
11787b5038d7SDag-Erling Smørgrav 
11797b5038d7SDag-Erling Smørgrav ldns_status
11807b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
11817b5038d7SDag-Erling Smørgrav 				  ldns_rr_list *new_rrs,
11827b5038d7SDag-Erling Smørgrav 				  ldns_key_list *key_list,
11837b5038d7SDag-Erling Smørgrav 				  int (*func)(ldns_rr *, void *),
11847b5038d7SDag-Erling Smørgrav 				  void *arg,
11857b5038d7SDag-Erling Smørgrav 				  int flags)
11867b5038d7SDag-Erling Smørgrav {
11877b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
11887b5038d7SDag-Erling Smørgrav 
11897b5038d7SDag-Erling Smørgrav 	if (!zone || !new_rrs || !key_list) {
11907b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
11917b5038d7SDag-Erling Smørgrav 	}
11927b5038d7SDag-Erling Smørgrav 
11937b5038d7SDag-Erling Smørgrav 	/* zone is already sorted */
11947b5038d7SDag-Erling Smørgrav 	result = ldns_dnssec_zone_mark_glue(zone);
11957b5038d7SDag-Erling Smørgrav 	if (result != LDNS_STATUS_OK) {
11967b5038d7SDag-Erling Smørgrav 		return result;
11977b5038d7SDag-Erling Smørgrav 	}
11987b5038d7SDag-Erling Smørgrav 
11997b5038d7SDag-Erling Smørgrav 	/* check whether we need to add nsecs */
12007b5038d7SDag-Erling Smørgrav 	if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
12017b5038d7SDag-Erling Smørgrav 		result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
12027b5038d7SDag-Erling Smørgrav 		if (result != LDNS_STATUS_OK) {
12037b5038d7SDag-Erling Smørgrav 			return result;
12047b5038d7SDag-Erling Smørgrav 		}
12057b5038d7SDag-Erling Smørgrav 	}
12067b5038d7SDag-Erling Smørgrav 
12077b5038d7SDag-Erling Smørgrav 	result = ldns_dnssec_zone_create_rrsigs_flg(zone,
12087b5038d7SDag-Erling Smørgrav 					new_rrs,
12097b5038d7SDag-Erling Smørgrav 					key_list,
12107b5038d7SDag-Erling Smørgrav 					func,
12117b5038d7SDag-Erling Smørgrav 					arg,
12127b5038d7SDag-Erling Smørgrav 					flags);
12137b5038d7SDag-Erling Smørgrav 
12147b5038d7SDag-Erling Smørgrav 	return result;
12157b5038d7SDag-Erling Smørgrav }
12167b5038d7SDag-Erling Smørgrav 
12177b5038d7SDag-Erling Smørgrav ldns_status
12187b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
12197b5038d7SDag-Erling Smørgrav 					   ldns_rr_list *new_rrs,
12207b5038d7SDag-Erling Smørgrav 					   ldns_key_list *key_list,
12217b5038d7SDag-Erling Smørgrav 					   int (*func)(ldns_rr *, void *),
12227b5038d7SDag-Erling Smørgrav 					   void *arg,
12237b5038d7SDag-Erling Smørgrav 					   uint8_t algorithm,
12247b5038d7SDag-Erling Smørgrav 					   uint8_t flags,
12257b5038d7SDag-Erling Smørgrav 					   uint16_t iterations,
12267b5038d7SDag-Erling Smørgrav 					   uint8_t salt_length,
12277b5038d7SDag-Erling Smørgrav 					   uint8_t *salt)
12287b5038d7SDag-Erling Smørgrav {
12297b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
12307b5038d7SDag-Erling Smørgrav 		func, arg, algorithm, flags, iterations, salt_length, salt, 0,
12317b5038d7SDag-Erling Smørgrav 	       	NULL);
12327b5038d7SDag-Erling Smørgrav }
12337b5038d7SDag-Erling Smørgrav 
12347b5038d7SDag-Erling Smørgrav ldns_status
12357b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
12367b5038d7SDag-Erling Smørgrav 		ldns_rr_list *new_rrs,
12377b5038d7SDag-Erling Smørgrav 		ldns_key_list *key_list,
12387b5038d7SDag-Erling Smørgrav 		int (*func)(ldns_rr *, void *),
12397b5038d7SDag-Erling Smørgrav 		void *arg,
12407b5038d7SDag-Erling Smørgrav 		uint8_t algorithm,
12417b5038d7SDag-Erling Smørgrav 		uint8_t flags,
12427b5038d7SDag-Erling Smørgrav 		uint16_t iterations,
12437b5038d7SDag-Erling Smørgrav 		uint8_t salt_length,
12447b5038d7SDag-Erling Smørgrav 		uint8_t *salt,
12457b5038d7SDag-Erling Smørgrav 		int signflags,
12467b5038d7SDag-Erling Smørgrav 		ldns_rbtree_t **map)
12477b5038d7SDag-Erling Smørgrav {
12487b5038d7SDag-Erling Smørgrav 	ldns_rr *nsec3, *nsec3param;
12497b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
12507b5038d7SDag-Erling Smørgrav 
12517b5038d7SDag-Erling Smørgrav 	/* zone is already sorted */
12527b5038d7SDag-Erling Smørgrav 	result = ldns_dnssec_zone_mark_glue(zone);
12537b5038d7SDag-Erling Smørgrav 	if (result != LDNS_STATUS_OK) {
12547b5038d7SDag-Erling Smørgrav 		return result;
12557b5038d7SDag-Erling Smørgrav 	}
12567b5038d7SDag-Erling Smørgrav 
12577b5038d7SDag-Erling Smørgrav 	/* TODO if there are already nsec3s presents and their
12587b5038d7SDag-Erling Smørgrav 	 * parameters are the same as these, we don't have to recreate
12597b5038d7SDag-Erling Smørgrav 	 */
12607b5038d7SDag-Erling Smørgrav 	if (zone->names) {
12617b5038d7SDag-Erling Smørgrav 		/* add empty nonterminals */
12627b5038d7SDag-Erling Smørgrav 		result = ldns_dnssec_zone_add_empty_nonterminals(zone);
12637b5038d7SDag-Erling Smørgrav 		if (result != LDNS_STATUS_OK) {
12647b5038d7SDag-Erling Smørgrav 			return result;
12657b5038d7SDag-Erling Smørgrav 		}
12667b5038d7SDag-Erling Smørgrav 
12677b5038d7SDag-Erling Smørgrav 		nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
12687b5038d7SDag-Erling Smørgrav 		if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
12697b5038d7SDag-Erling Smørgrav 			/* no need to recreate */
12707b5038d7SDag-Erling Smørgrav 		} else {
12717b5038d7SDag-Erling Smørgrav 			if (!ldns_dnssec_zone_find_rrset(zone,
12727b5038d7SDag-Erling Smørgrav 									   zone->soa->name,
12737b5038d7SDag-Erling Smørgrav 									   LDNS_RR_TYPE_NSEC3PARAM)) {
12747b5038d7SDag-Erling Smørgrav 				/* create and add the nsec3param rr */
12757b5038d7SDag-Erling Smørgrav 				nsec3param =
12767b5038d7SDag-Erling Smørgrav 					ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM);
12777b5038d7SDag-Erling Smørgrav 				ldns_rr_set_owner(nsec3param,
12787b5038d7SDag-Erling Smørgrav 							   ldns_rdf_clone(zone->soa->name));
12797b5038d7SDag-Erling Smørgrav 				ldns_nsec3_add_param_rdfs(nsec3param,
12807b5038d7SDag-Erling Smørgrav 									 algorithm,
12817b5038d7SDag-Erling Smørgrav 									 flags,
12827b5038d7SDag-Erling Smørgrav 									 iterations,
12837b5038d7SDag-Erling Smørgrav 									 salt_length,
12847b5038d7SDag-Erling Smørgrav 									 salt);
12857b5038d7SDag-Erling Smørgrav 				/* always set bit 7 of the flags to zero, according to
12867b5038d7SDag-Erling Smørgrav 				 * rfc5155 section 11. The bits are counted from right to left,
12877b5038d7SDag-Erling Smørgrav 				 * so bit 7 in rfc5155 is bit 0 in ldns */
12887b5038d7SDag-Erling Smørgrav 				ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0);
12897b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_zone_add_rr(zone, nsec3param);
12907b5038d7SDag-Erling Smørgrav 				if (result != LDNS_STATUS_OK) {
12917b5038d7SDag-Erling Smørgrav 					return result;
12927b5038d7SDag-Erling Smørgrav 				}
12937b5038d7SDag-Erling Smørgrav 				ldns_rr_list_push_rr(new_rrs, nsec3param);
12947b5038d7SDag-Erling Smørgrav 			}
12957b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_zone_create_nsec3s_mkmap(zone,
12967b5038d7SDag-Erling Smørgrav 											new_rrs,
12977b5038d7SDag-Erling Smørgrav 											algorithm,
12987b5038d7SDag-Erling Smørgrav 											flags,
12997b5038d7SDag-Erling Smørgrav 											iterations,
13007b5038d7SDag-Erling Smørgrav 											salt_length,
13017b5038d7SDag-Erling Smørgrav 											salt,
13027b5038d7SDag-Erling Smørgrav 											map);
13037b5038d7SDag-Erling Smørgrav 			if (result != LDNS_STATUS_OK) {
13047b5038d7SDag-Erling Smørgrav 				return result;
13057b5038d7SDag-Erling Smørgrav 			}
13067b5038d7SDag-Erling Smørgrav 		}
13077b5038d7SDag-Erling Smørgrav 
13087b5038d7SDag-Erling Smørgrav 		result = ldns_dnssec_zone_create_rrsigs_flg(zone,
13097b5038d7SDag-Erling Smørgrav 						new_rrs,
13107b5038d7SDag-Erling Smørgrav 						key_list,
13117b5038d7SDag-Erling Smørgrav 						func,
13127b5038d7SDag-Erling Smørgrav 						arg,
13137b5038d7SDag-Erling Smørgrav 						signflags);
13147b5038d7SDag-Erling Smørgrav 	}
13157b5038d7SDag-Erling Smørgrav 
13167b5038d7SDag-Erling Smørgrav 	return result;
13177b5038d7SDag-Erling Smørgrav }
13187b5038d7SDag-Erling Smørgrav 
13197b5038d7SDag-Erling Smørgrav ldns_status
13207b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
13217b5038d7SDag-Erling Smørgrav 		ldns_rr_list *new_rrs,
13227b5038d7SDag-Erling Smørgrav 		ldns_key_list *key_list,
13237b5038d7SDag-Erling Smørgrav 		int (*func)(ldns_rr *, void *),
13247b5038d7SDag-Erling Smørgrav 		void *arg,
13257b5038d7SDag-Erling Smørgrav 		uint8_t algorithm,
13267b5038d7SDag-Erling Smørgrav 		uint8_t flags,
13277b5038d7SDag-Erling Smørgrav 		uint16_t iterations,
13287b5038d7SDag-Erling Smørgrav 		uint8_t salt_length,
13297b5038d7SDag-Erling Smørgrav 		uint8_t *salt,
13307b5038d7SDag-Erling Smørgrav 		int signflags)
13317b5038d7SDag-Erling Smørgrav {
13327b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
13337b5038d7SDag-Erling Smørgrav 		func, arg, algorithm, flags, iterations, salt_length, salt,
13347b5038d7SDag-Erling Smørgrav 		signflags, NULL);
13357b5038d7SDag-Erling Smørgrav }
13367b5038d7SDag-Erling Smørgrav 
13377b5038d7SDag-Erling Smørgrav ldns_zone *
13387b5038d7SDag-Erling Smørgrav ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
13397b5038d7SDag-Erling Smørgrav {
13407b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone *dnssec_zone;
13417b5038d7SDag-Erling Smørgrav 	ldns_zone *signed_zone;
13427b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new_rrs;
13437b5038d7SDag-Erling Smørgrav 	size_t i;
13447b5038d7SDag-Erling Smørgrav 
13457b5038d7SDag-Erling Smørgrav 	signed_zone = ldns_zone_new();
13467b5038d7SDag-Erling Smørgrav 	dnssec_zone = ldns_dnssec_zone_new();
13477b5038d7SDag-Erling Smørgrav 
13487b5038d7SDag-Erling Smørgrav 	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
13497b5038d7SDag-Erling Smørgrav 	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
13507b5038d7SDag-Erling Smørgrav 
13517b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
13527b5038d7SDag-Erling Smørgrav 		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
13537b5038d7SDag-Erling Smørgrav 								 ldns_rr_list_rr(ldns_zone_rrs(zone),
13547b5038d7SDag-Erling Smørgrav 											  i));
13557b5038d7SDag-Erling Smørgrav 		ldns_zone_push_rr(signed_zone,
13567b5038d7SDag-Erling Smørgrav 					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
13577b5038d7SDag-Erling Smørgrav 											   i)));
13587b5038d7SDag-Erling Smørgrav 	}
13597b5038d7SDag-Erling Smørgrav 
13607b5038d7SDag-Erling Smørgrav 	new_rrs = ldns_rr_list_new();
13617b5038d7SDag-Erling Smørgrav 	(void) ldns_dnssec_zone_sign(dnssec_zone,
13627b5038d7SDag-Erling Smørgrav 						    new_rrs,
13637b5038d7SDag-Erling Smørgrav 						    key_list,
13647b5038d7SDag-Erling Smørgrav 						    ldns_dnssec_default_replace_signatures,
13657b5038d7SDag-Erling Smørgrav 						    NULL);
13667b5038d7SDag-Erling Smørgrav 
13677b5038d7SDag-Erling Smørgrav     	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
13687b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
13697b5038d7SDag-Erling Smørgrav 						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
13707b5038d7SDag-Erling Smørgrav 	}
13717b5038d7SDag-Erling Smørgrav 
13727b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_rrs);
13737b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone_free(dnssec_zone);
13747b5038d7SDag-Erling Smørgrav 
13757b5038d7SDag-Erling Smørgrav 	return signed_zone;
13767b5038d7SDag-Erling Smørgrav }
13777b5038d7SDag-Erling Smørgrav 
13787b5038d7SDag-Erling Smørgrav ldns_zone *
13797b5038d7SDag-Erling Smørgrav ldns_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)
13807b5038d7SDag-Erling Smørgrav {
13817b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone *dnssec_zone;
13827b5038d7SDag-Erling Smørgrav 	ldns_zone *signed_zone;
13837b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new_rrs;
13847b5038d7SDag-Erling Smørgrav 	size_t i;
13857b5038d7SDag-Erling Smørgrav 
13867b5038d7SDag-Erling Smørgrav 	signed_zone = ldns_zone_new();
13877b5038d7SDag-Erling Smørgrav 	dnssec_zone = ldns_dnssec_zone_new();
13887b5038d7SDag-Erling Smørgrav 
13897b5038d7SDag-Erling Smørgrav 	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
13907b5038d7SDag-Erling Smørgrav 	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
13917b5038d7SDag-Erling Smørgrav 
13927b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
13937b5038d7SDag-Erling Smørgrav 		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
13947b5038d7SDag-Erling Smørgrav 								 ldns_rr_list_rr(ldns_zone_rrs(zone),
13957b5038d7SDag-Erling Smørgrav 											  i));
13967b5038d7SDag-Erling Smørgrav 		ldns_zone_push_rr(signed_zone,
13977b5038d7SDag-Erling Smørgrav 					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
13987b5038d7SDag-Erling Smørgrav 											   i)));
13997b5038d7SDag-Erling Smørgrav 	}
14007b5038d7SDag-Erling Smørgrav 
14017b5038d7SDag-Erling Smørgrav 	new_rrs = ldns_rr_list_new();
14027b5038d7SDag-Erling Smørgrav 	(void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
14037b5038d7SDag-Erling Smørgrav 								new_rrs,
14047b5038d7SDag-Erling Smørgrav 								key_list,
14057b5038d7SDag-Erling Smørgrav 								ldns_dnssec_default_replace_signatures,
14067b5038d7SDag-Erling Smørgrav 								NULL,
14077b5038d7SDag-Erling Smørgrav 								algorithm,
14087b5038d7SDag-Erling Smørgrav 								flags,
14097b5038d7SDag-Erling Smørgrav 								iterations,
14107b5038d7SDag-Erling Smørgrav 								salt_length,
14117b5038d7SDag-Erling Smørgrav 								salt);
14127b5038d7SDag-Erling Smørgrav 
14137b5038d7SDag-Erling Smørgrav     	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
14147b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
14157b5038d7SDag-Erling Smørgrav 						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
14167b5038d7SDag-Erling Smørgrav 	}
14177b5038d7SDag-Erling Smørgrav 
14187b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_rrs);
14197b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone_free(dnssec_zone);
14207b5038d7SDag-Erling Smørgrav 
14217b5038d7SDag-Erling Smørgrav 	return signed_zone;
14227b5038d7SDag-Erling Smørgrav }
14237b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
14247b5038d7SDag-Erling Smørgrav 
14257b5038d7SDag-Erling Smørgrav 
1426