xref: /dflybsd-src/contrib/ldns/dnssec_sign.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
1825eb42bSJan Lentfer #include <ldns/config.h>
2825eb42bSJan Lentfer 
3825eb42bSJan Lentfer #include <ldns/ldns.h>
4825eb42bSJan Lentfer 
5825eb42bSJan Lentfer #include <ldns/dnssec.h>
6825eb42bSJan Lentfer #include <ldns/dnssec_sign.h>
7825eb42bSJan Lentfer 
8825eb42bSJan Lentfer #include <strings.h>
9825eb42bSJan Lentfer #include <time.h>
10825eb42bSJan Lentfer 
11825eb42bSJan Lentfer #ifdef HAVE_SSL
12825eb42bSJan Lentfer /* this entire file is rather useless when you don't have
13825eb42bSJan Lentfer  * crypto...
14825eb42bSJan Lentfer  */
15825eb42bSJan Lentfer #include <openssl/ssl.h>
16825eb42bSJan Lentfer #include <openssl/evp.h>
17825eb42bSJan Lentfer #include <openssl/rand.h>
18825eb42bSJan Lentfer #include <openssl/err.h>
19825eb42bSJan Lentfer #include <openssl/md5.h>
20819dec71SDaniel Fojt #include <openssl/bn.h>
21819dec71SDaniel Fojt #include <openssl/rsa.h>
22819dec71SDaniel Fojt #ifdef USE_DSA
23819dec71SDaniel Fojt #include <openssl/dsa.h>
24819dec71SDaniel Fojt #endif
25825eb42bSJan Lentfer #endif /* HAVE_SSL */
26825eb42bSJan Lentfer 
27*ee791febSAntonio Huete Jimenez #define LDNS_SIGN_WITH_ZONEMD ( LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384 \
28*ee791febSAntonio Huete Jimenez                               | LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512 )
29*ee791febSAntonio Huete Jimenez 
30825eb42bSJan Lentfer ldns_rr *
ldns_create_empty_rrsig(const ldns_rr_list * rrset,const ldns_key * current_key)315340022aSzrj ldns_create_empty_rrsig(const ldns_rr_list *rrset,
325340022aSzrj                         const ldns_key *current_key)
33825eb42bSJan Lentfer {
34825eb42bSJan Lentfer 	uint32_t orig_ttl;
35825eb42bSJan Lentfer 	ldns_rr_class orig_class;
36825eb42bSJan Lentfer 	time_t now;
37825eb42bSJan Lentfer 	ldns_rr *current_sig;
38825eb42bSJan Lentfer 	uint8_t label_count;
39d1b2b5caSJohn Marino 	ldns_rdf *signame;
40825eb42bSJan Lentfer 
41825eb42bSJan Lentfer 	label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
42825eb42bSJan Lentfer 	                                                   0)));
43ac996e71SJan Lentfer         /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */
44ac996e71SJan Lentfer         if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))))
45ac996e71SJan Lentfer                 label_count --;
46825eb42bSJan Lentfer 
47825eb42bSJan Lentfer 	current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
48825eb42bSJan Lentfer 
49825eb42bSJan Lentfer 	/* set the type on the new signature */
50825eb42bSJan Lentfer 	orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
51825eb42bSJan Lentfer 	orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
52825eb42bSJan Lentfer 
53825eb42bSJan Lentfer 	ldns_rr_set_ttl(current_sig, orig_ttl);
54825eb42bSJan Lentfer 	ldns_rr_set_class(current_sig, orig_class);
55825eb42bSJan Lentfer 	ldns_rr_set_owner(current_sig,
56825eb42bSJan Lentfer 			  ldns_rdf_clone(
57825eb42bSJan Lentfer 			       ldns_rr_owner(
58825eb42bSJan Lentfer 				    ldns_rr_list_rr(rrset,
59825eb42bSJan Lentfer 						    0))));
60825eb42bSJan Lentfer 
61825eb42bSJan Lentfer 	/* fill in what we know of the signature */
62825eb42bSJan Lentfer 
63825eb42bSJan Lentfer 	/* set the orig_ttl */
64825eb42bSJan Lentfer 	(void)ldns_rr_rrsig_set_origttl(
65825eb42bSJan Lentfer 		   current_sig,
66825eb42bSJan Lentfer 		   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
67825eb42bSJan Lentfer 					 orig_ttl));
68825eb42bSJan Lentfer 	/* the signers name */
69d1b2b5caSJohn Marino 	signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
70d1b2b5caSJohn Marino 	ldns_dname2canonical(signame);
71825eb42bSJan Lentfer 	(void)ldns_rr_rrsig_set_signame(
72825eb42bSJan Lentfer 			current_sig,
73d1b2b5caSJohn Marino 			signame);
74825eb42bSJan Lentfer 	/* label count - get it from the first rr in the rr_list */
75825eb42bSJan Lentfer 	(void)ldns_rr_rrsig_set_labels(
76825eb42bSJan Lentfer 			current_sig,
77825eb42bSJan Lentfer 			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
78825eb42bSJan Lentfer 			                     label_count));
79825eb42bSJan Lentfer 	/* inception, expiration */
80825eb42bSJan Lentfer 	now = time(NULL);
81825eb42bSJan Lentfer 	if (ldns_key_inception(current_key) != 0) {
82825eb42bSJan Lentfer 		(void)ldns_rr_rrsig_set_inception(
83825eb42bSJan Lentfer 				current_sig,
84825eb42bSJan Lentfer 				ldns_native2rdf_int32(
85825eb42bSJan Lentfer 				    LDNS_RDF_TYPE_TIME,
86825eb42bSJan Lentfer 				    ldns_key_inception(current_key)));
87825eb42bSJan Lentfer 	} else {
88825eb42bSJan Lentfer 		(void)ldns_rr_rrsig_set_inception(
89825eb42bSJan Lentfer 				current_sig,
90825eb42bSJan Lentfer 				ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
91825eb42bSJan Lentfer 	}
92825eb42bSJan Lentfer 	if (ldns_key_expiration(current_key) != 0) {
93825eb42bSJan Lentfer 		(void)ldns_rr_rrsig_set_expiration(
94825eb42bSJan Lentfer 				current_sig,
95825eb42bSJan Lentfer 				ldns_native2rdf_int32(
96825eb42bSJan Lentfer 				    LDNS_RDF_TYPE_TIME,
97825eb42bSJan Lentfer 				    ldns_key_expiration(current_key)));
98825eb42bSJan Lentfer 	} else {
99825eb42bSJan Lentfer 		(void)ldns_rr_rrsig_set_expiration(
100825eb42bSJan Lentfer 			     current_sig,
101825eb42bSJan Lentfer 				ldns_native2rdf_int32(
102825eb42bSJan Lentfer 				    LDNS_RDF_TYPE_TIME,
103825eb42bSJan Lentfer 				    now + LDNS_DEFAULT_EXP_TIME));
104825eb42bSJan Lentfer 	}
105825eb42bSJan Lentfer 
106825eb42bSJan Lentfer 	(void)ldns_rr_rrsig_set_keytag(
107825eb42bSJan Lentfer 		   current_sig,
108825eb42bSJan Lentfer 		   ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
109825eb42bSJan Lentfer 		                         ldns_key_keytag(current_key)));
110825eb42bSJan Lentfer 
111825eb42bSJan Lentfer 	(void)ldns_rr_rrsig_set_algorithm(
112825eb42bSJan Lentfer 			current_sig,
113825eb42bSJan Lentfer 			ldns_native2rdf_int8(
114825eb42bSJan Lentfer 			    LDNS_RDF_TYPE_ALG,
115825eb42bSJan Lentfer 			    ldns_key_algorithm(current_key)));
116825eb42bSJan Lentfer 
117825eb42bSJan Lentfer 	(void)ldns_rr_rrsig_set_typecovered(
118825eb42bSJan Lentfer 			current_sig,
119825eb42bSJan Lentfer 			ldns_native2rdf_int16(
120825eb42bSJan Lentfer 			    LDNS_RDF_TYPE_TYPE,
121825eb42bSJan Lentfer 			    ldns_rr_get_type(ldns_rr_list_rr(rrset,
122825eb42bSJan Lentfer 			                                     0))));
123825eb42bSJan Lentfer 	return current_sig;
124825eb42bSJan Lentfer }
125825eb42bSJan Lentfer 
126825eb42bSJan Lentfer #ifdef HAVE_SSL
127825eb42bSJan Lentfer ldns_rdf *
ldns_sign_public_buffer(ldns_buffer * sign_buf,ldns_key * current_key)128825eb42bSJan Lentfer ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
129825eb42bSJan Lentfer {
130825eb42bSJan Lentfer 	ldns_rdf *b64rdf = NULL;
131825eb42bSJan Lentfer 
132825eb42bSJan Lentfer 	switch(ldns_key_algorithm(current_key)) {
1335340022aSzrj #ifdef USE_DSA
134825eb42bSJan Lentfer 	case LDNS_SIGN_DSA:
135fd185f4dSJan Lentfer 	case LDNS_SIGN_DSA_NSEC3:
136825eb42bSJan Lentfer 		b64rdf = ldns_sign_public_evp(
137825eb42bSJan Lentfer 				   sign_buf,
138825eb42bSJan Lentfer 				   ldns_key_evp_key(current_key),
1395340022aSzrj # ifdef HAVE_EVP_DSS1
1405340022aSzrj 				   EVP_dss1()
1415340022aSzrj # else
1425340022aSzrj 				   EVP_sha1()
1435340022aSzrj # endif
1445340022aSzrj 				   );
145825eb42bSJan Lentfer 		break;
1465340022aSzrj #endif /* USE_DSA */
147825eb42bSJan Lentfer 	case LDNS_SIGN_RSASHA1:
148825eb42bSJan Lentfer 	case LDNS_SIGN_RSASHA1_NSEC3:
149825eb42bSJan Lentfer 		b64rdf = ldns_sign_public_evp(
150825eb42bSJan Lentfer 				   sign_buf,
151825eb42bSJan Lentfer 				   ldns_key_evp_key(current_key),
152825eb42bSJan Lentfer 				   EVP_sha1());
153825eb42bSJan Lentfer 		break;
154825eb42bSJan Lentfer #ifdef USE_SHA2
155825eb42bSJan Lentfer 	case LDNS_SIGN_RSASHA256:
156825eb42bSJan Lentfer 		b64rdf = ldns_sign_public_evp(
157825eb42bSJan Lentfer 				   sign_buf,
158825eb42bSJan Lentfer 				   ldns_key_evp_key(current_key),
159825eb42bSJan Lentfer 				   EVP_sha256());
160825eb42bSJan Lentfer 		break;
161825eb42bSJan Lentfer 	case LDNS_SIGN_RSASHA512:
162825eb42bSJan Lentfer 		b64rdf = ldns_sign_public_evp(
163825eb42bSJan Lentfer 				   sign_buf,
164825eb42bSJan Lentfer 				   ldns_key_evp_key(current_key),
165825eb42bSJan Lentfer 				   EVP_sha512());
166825eb42bSJan Lentfer 		break;
167825eb42bSJan Lentfer #endif /* USE_SHA2 */
168825eb42bSJan Lentfer #ifdef USE_GOST
169ac996e71SJan Lentfer 	case LDNS_SIGN_ECC_GOST:
170825eb42bSJan Lentfer 		b64rdf = ldns_sign_public_evp(
171825eb42bSJan Lentfer 				   sign_buf,
172825eb42bSJan Lentfer 				   ldns_key_evp_key(current_key),
173825eb42bSJan Lentfer 				   EVP_get_digestbyname("md_gost94"));
174825eb42bSJan Lentfer 		break;
175825eb42bSJan Lentfer #endif /* USE_GOST */
176ac996e71SJan Lentfer #ifdef USE_ECDSA
177ac996e71SJan Lentfer         case LDNS_SIGN_ECDSAP256SHA256:
178ac996e71SJan Lentfer        		b64rdf = ldns_sign_public_evp(
179ac996e71SJan Lentfer 				   sign_buf,
180ac996e71SJan Lentfer 				   ldns_key_evp_key(current_key),
181ac996e71SJan Lentfer 				   EVP_sha256());
182ac996e71SJan Lentfer                 break;
183ac996e71SJan Lentfer         case LDNS_SIGN_ECDSAP384SHA384:
184ac996e71SJan Lentfer        		b64rdf = ldns_sign_public_evp(
185ac996e71SJan Lentfer 				   sign_buf,
186ac996e71SJan Lentfer 				   ldns_key_evp_key(current_key),
187ac996e71SJan Lentfer 				   EVP_sha384());
188ac996e71SJan Lentfer                 break;
189ac996e71SJan Lentfer #endif
1905340022aSzrj #ifdef USE_ED25519
1915340022aSzrj         case LDNS_SIGN_ED25519:
1925340022aSzrj 		b64rdf = ldns_sign_public_evp(
1935340022aSzrj 				   sign_buf,
1945340022aSzrj 				   ldns_key_evp_key(current_key),
195819dec71SDaniel Fojt 				   NULL);
1965340022aSzrj                 break;
1975340022aSzrj #endif
1985340022aSzrj #ifdef USE_ED448
1995340022aSzrj         case LDNS_SIGN_ED448:
2005340022aSzrj 		b64rdf = ldns_sign_public_evp(
2015340022aSzrj 				   sign_buf,
2025340022aSzrj 				   ldns_key_evp_key(current_key),
203819dec71SDaniel Fojt 				   NULL);
2045340022aSzrj                 break;
2055340022aSzrj #endif
206825eb42bSJan Lentfer 	case LDNS_SIGN_RSAMD5:
207825eb42bSJan Lentfer 		b64rdf = ldns_sign_public_evp(
208825eb42bSJan Lentfer 				   sign_buf,
209825eb42bSJan Lentfer 				   ldns_key_evp_key(current_key),
210825eb42bSJan Lentfer 				   EVP_md5());
211825eb42bSJan Lentfer 		break;
212825eb42bSJan Lentfer 	default:
213825eb42bSJan Lentfer 		/* do _you_ know this alg? */
214825eb42bSJan Lentfer 		printf("unknown algorithm, ");
215825eb42bSJan Lentfer 		printf("is the one used available on this system?\n");
216825eb42bSJan Lentfer 		break;
217825eb42bSJan Lentfer 	}
218825eb42bSJan Lentfer 
219825eb42bSJan Lentfer 	return b64rdf;
220825eb42bSJan Lentfer }
221825eb42bSJan Lentfer 
222825eb42bSJan Lentfer /**
223825eb42bSJan Lentfer  * use this function to sign with a public/private key alg
224825eb42bSJan Lentfer  * return the created signatures
225825eb42bSJan Lentfer  */
226825eb42bSJan Lentfer ldns_rr_list *
ldns_sign_public(ldns_rr_list * rrset,ldns_key_list * keys)227825eb42bSJan Lentfer ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
228825eb42bSJan Lentfer {
229825eb42bSJan Lentfer 	ldns_rr_list *signatures;
230825eb42bSJan Lentfer 	ldns_rr_list *rrset_clone;
231825eb42bSJan Lentfer 	ldns_rr *current_sig;
232825eb42bSJan Lentfer 	ldns_rdf *b64rdf;
233825eb42bSJan Lentfer 	ldns_key *current_key;
234825eb42bSJan Lentfer 	size_t key_count;
235825eb42bSJan Lentfer 	uint16_t i;
236825eb42bSJan Lentfer 	ldns_buffer *sign_buf;
237825eb42bSJan Lentfer 	ldns_rdf *new_owner;
238825eb42bSJan Lentfer 
239825eb42bSJan Lentfer 	if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
240825eb42bSJan Lentfer 		return NULL;
241825eb42bSJan Lentfer 	}
242825eb42bSJan Lentfer 
243825eb42bSJan Lentfer 	new_owner = NULL;
244825eb42bSJan Lentfer 
245825eb42bSJan Lentfer 	/* prepare a signature and add all the know data
246825eb42bSJan Lentfer 	 * prepare the rrset. Sign this together.  */
247825eb42bSJan Lentfer 	rrset_clone = ldns_rr_list_clone(rrset);
248825eb42bSJan Lentfer 	if (!rrset_clone) {
249825eb42bSJan Lentfer 		return NULL;
250825eb42bSJan Lentfer 	}
251825eb42bSJan Lentfer 
252825eb42bSJan Lentfer 	/* make it canonical */
253825eb42bSJan Lentfer 	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
254825eb42bSJan Lentfer 		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i),
255825eb42bSJan Lentfer 			ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
256825eb42bSJan Lentfer 		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
257825eb42bSJan Lentfer 	}
258825eb42bSJan Lentfer 	/* sort */
259825eb42bSJan Lentfer 	ldns_rr_list_sort(rrset_clone);
260825eb42bSJan Lentfer 
261819dec71SDaniel Fojt 	signatures = ldns_rr_list_new();
262819dec71SDaniel Fojt 
263825eb42bSJan Lentfer 	for (key_count = 0;
264825eb42bSJan Lentfer 		key_count < ldns_key_list_key_count(keys);
265825eb42bSJan Lentfer 		key_count++) {
266825eb42bSJan Lentfer 		if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
267825eb42bSJan Lentfer 			continue;
268825eb42bSJan Lentfer 		}
269825eb42bSJan Lentfer 		sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
270825eb42bSJan Lentfer 		if (!sign_buf) {
271825eb42bSJan Lentfer 			ldns_rr_list_free(rrset_clone);
272825eb42bSJan Lentfer 			ldns_rr_list_free(signatures);
273825eb42bSJan Lentfer 			ldns_rdf_free(new_owner);
274825eb42bSJan Lentfer 			return NULL;
275825eb42bSJan Lentfer 		}
276825eb42bSJan Lentfer 		b64rdf = NULL;
277825eb42bSJan Lentfer 
278825eb42bSJan Lentfer 		current_key = ldns_key_list_key(keys, key_count);
279825eb42bSJan Lentfer 		/* sign all RRs with keys that have ZSKbit, !SEPbit.
280825eb42bSJan Lentfer 		   sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
281ac996e71SJan Lentfer 		if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) {
282825eb42bSJan Lentfer 			current_sig = ldns_create_empty_rrsig(rrset_clone,
283825eb42bSJan Lentfer 			                                      current_key);
284825eb42bSJan Lentfer 
285825eb42bSJan Lentfer 			/* right now, we have: a key, a semi-sig and an rrset. For
286825eb42bSJan Lentfer 			 * which we can create the sig and base64 encode that and
287825eb42bSJan Lentfer 			 * add that to the signature */
288825eb42bSJan Lentfer 
289825eb42bSJan Lentfer 			if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
290825eb42bSJan Lentfer 			    != LDNS_STATUS_OK) {
291825eb42bSJan Lentfer 				ldns_buffer_free(sign_buf);
292825eb42bSJan Lentfer 				/* ERROR */
293825eb42bSJan Lentfer 				ldns_rr_list_deep_free(rrset_clone);
294d1b2b5caSJohn Marino 				ldns_rr_free(current_sig);
295d1b2b5caSJohn Marino 				ldns_rr_list_deep_free(signatures);
296825eb42bSJan Lentfer 				return NULL;
297825eb42bSJan Lentfer 			}
298825eb42bSJan Lentfer 
299825eb42bSJan Lentfer 			/* add the rrset in sign_buf */
300825eb42bSJan Lentfer 			if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
301825eb42bSJan Lentfer 			    != LDNS_STATUS_OK) {
302825eb42bSJan Lentfer 				ldns_buffer_free(sign_buf);
303825eb42bSJan Lentfer 				ldns_rr_list_deep_free(rrset_clone);
304d1b2b5caSJohn Marino 				ldns_rr_free(current_sig);
305d1b2b5caSJohn Marino 				ldns_rr_list_deep_free(signatures);
306825eb42bSJan Lentfer 				return NULL;
307825eb42bSJan Lentfer 			}
308825eb42bSJan Lentfer 
309825eb42bSJan Lentfer 			b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
310825eb42bSJan Lentfer 
311825eb42bSJan Lentfer 			if (!b64rdf) {
312825eb42bSJan Lentfer 				/* signing went wrong */
313825eb42bSJan Lentfer 				ldns_rr_list_deep_free(rrset_clone);
314d1b2b5caSJohn Marino 				ldns_rr_free(current_sig);
315d1b2b5caSJohn Marino 				ldns_rr_list_deep_free(signatures);
316825eb42bSJan Lentfer 				return NULL;
317825eb42bSJan Lentfer 			}
318825eb42bSJan Lentfer 
319825eb42bSJan Lentfer 			ldns_rr_rrsig_set_sig(current_sig, b64rdf);
320825eb42bSJan Lentfer 
321825eb42bSJan Lentfer 			/* push the signature to the signatures list */
322825eb42bSJan Lentfer 			ldns_rr_list_push_rr(signatures, current_sig);
323825eb42bSJan Lentfer 		}
324825eb42bSJan Lentfer 		ldns_buffer_free(sign_buf); /* restart for the next key */
325825eb42bSJan Lentfer 	}
326825eb42bSJan Lentfer 	ldns_rr_list_deep_free(rrset_clone);
327825eb42bSJan Lentfer 
328825eb42bSJan Lentfer 	return signatures;
329825eb42bSJan Lentfer }
330825eb42bSJan Lentfer 
331825eb42bSJan Lentfer ldns_rdf *
ldns_sign_public_dsa(ldns_buffer * to_sign,DSA * key)332825eb42bSJan Lentfer ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
333825eb42bSJan Lentfer {
3345340022aSzrj #ifdef USE_DSA
335825eb42bSJan Lentfer 	unsigned char *sha1_hash;
336825eb42bSJan Lentfer 	ldns_rdf *sigdata_rdf;
337825eb42bSJan Lentfer 	ldns_buffer *b64sig;
338825eb42bSJan Lentfer 
339825eb42bSJan Lentfer 	DSA_SIG *sig;
3405340022aSzrj 	const BIGNUM *R, *S;
341825eb42bSJan Lentfer 	uint8_t *data;
342825eb42bSJan Lentfer 	size_t pad;
343825eb42bSJan Lentfer 
344825eb42bSJan Lentfer 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
345825eb42bSJan Lentfer 	if (!b64sig) {
346825eb42bSJan Lentfer 		return NULL;
347825eb42bSJan Lentfer 	}
348825eb42bSJan Lentfer 
349825eb42bSJan Lentfer 	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
350825eb42bSJan Lentfer 				  ldns_buffer_position(to_sign), NULL);
351825eb42bSJan Lentfer 	if (!sha1_hash) {
352825eb42bSJan Lentfer 		ldns_buffer_free(b64sig);
353825eb42bSJan Lentfer 		return NULL;
354825eb42bSJan Lentfer 	}
355825eb42bSJan Lentfer 
356825eb42bSJan Lentfer 	sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
357fd185f4dSJan Lentfer         if(!sig) {
358fd185f4dSJan Lentfer 		ldns_buffer_free(b64sig);
359fd185f4dSJan Lentfer 		return NULL;
360fd185f4dSJan Lentfer         }
361825eb42bSJan Lentfer 
362825eb42bSJan Lentfer 	data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
363fd185f4dSJan Lentfer         if(!data) {
364fd185f4dSJan Lentfer 		ldns_buffer_free(b64sig);
365fd185f4dSJan Lentfer                 DSA_SIG_free(sig);
366fd185f4dSJan Lentfer 		return NULL;
367fd185f4dSJan Lentfer         }
368825eb42bSJan Lentfer 
369825eb42bSJan Lentfer 	data[0] = 1;
3705340022aSzrj # ifdef HAVE_DSA_SIG_GET0
3715340022aSzrj 	DSA_SIG_get0(sig, &R, &S);
3725340022aSzrj # else
3735340022aSzrj 	R = sig->r;
3745340022aSzrj 	S = sig->s;
3755340022aSzrj # endif
3765340022aSzrj 	pad = 20 - (size_t) BN_num_bytes(R);
377825eb42bSJan Lentfer 	if (pad > 0) {
378825eb42bSJan Lentfer 		memset(data + 1, 0, pad);
379825eb42bSJan Lentfer 	}
3805340022aSzrj 	BN_bn2bin(R, (unsigned char *) (data + 1) + pad);
381825eb42bSJan Lentfer 
3825340022aSzrj 	pad = 20 - (size_t) BN_num_bytes(S);
383825eb42bSJan Lentfer 	if (pad > 0) {
384825eb42bSJan Lentfer 		memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
385825eb42bSJan Lentfer 	}
3865340022aSzrj 	BN_bn2bin(S, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
387825eb42bSJan Lentfer 
388825eb42bSJan Lentfer 	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
389825eb42bSJan Lentfer 								 1 + 2 * SHA_DIGEST_LENGTH,
390825eb42bSJan Lentfer 								 data);
391825eb42bSJan Lentfer 
392825eb42bSJan Lentfer 	ldns_buffer_free(b64sig);
393825eb42bSJan Lentfer 	LDNS_FREE(data);
394fd185f4dSJan Lentfer         DSA_SIG_free(sig);
395825eb42bSJan Lentfer 
396825eb42bSJan Lentfer 	return sigdata_rdf;
3975340022aSzrj #else
3985340022aSzrj 	(void)to_sign; (void)key;
3995340022aSzrj 	return NULL;
4005340022aSzrj #endif
401825eb42bSJan Lentfer }
402825eb42bSJan Lentfer 
403ac996e71SJan Lentfer #ifdef USE_ECDSA
404fd185f4dSJan Lentfer #ifndef S_SPLINT_S
4055340022aSzrj /** returns the number of bytes per signature-component (i.e. bits/8), or 0. */
406ac996e71SJan Lentfer static int
ldns_pkey_is_ecdsa(EVP_PKEY * pkey)407ac996e71SJan Lentfer ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
408ac996e71SJan Lentfer {
409ac996e71SJan Lentfer         EC_KEY* ec;
410ac996e71SJan Lentfer         const EC_GROUP* g;
411*ee791febSAntonio Huete Jimenez #ifdef HAVE_EVP_PKEY_GET_BASE_ID
412*ee791febSAntonio Huete Jimenez         if(EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC)
413*ee791febSAntonio Huete Jimenez                 return 0;
414*ee791febSAntonio Huete Jimenez #elif defined(HAVE_EVP_PKEY_BASE_ID)
4155340022aSzrj         if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
416ac996e71SJan Lentfer                 return 0;
4175340022aSzrj #else
418*ee791febSAntonio Huete Jimenez         if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
4195340022aSzrj                 return 0;
4205340022aSzrj #endif
421ac996e71SJan Lentfer         ec = EVP_PKEY_get1_EC_KEY(pkey);
422ac996e71SJan Lentfer         g = EC_KEY_get0_group(ec);
423ac996e71SJan Lentfer         if(!g) {
424ac996e71SJan Lentfer                 EC_KEY_free(ec);
425ac996e71SJan Lentfer                 return 0;
426ac996e71SJan Lentfer         }
4275340022aSzrj         if(EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1) {
428ac996e71SJan Lentfer                 EC_KEY_free(ec);
4295340022aSzrj                 return 32; /* 256/8 */
4305340022aSzrj 	}
4315340022aSzrj         if(EC_GROUP_get_curve_name(g) == NID_secp384r1) {
4325340022aSzrj                 EC_KEY_free(ec);
4335340022aSzrj                 return 48; /* 384/8 */
434ac996e71SJan Lentfer         }
435ac996e71SJan Lentfer         /* downref the eckey, the original is still inside the pkey */
436ac996e71SJan Lentfer         EC_KEY_free(ec);
437ac996e71SJan Lentfer         return 0;
438ac996e71SJan Lentfer }
439fd185f4dSJan Lentfer #endif /* splint */
440ac996e71SJan Lentfer #endif /* USE_ECDSA */
441ac996e71SJan Lentfer 
442825eb42bSJan Lentfer ldns_rdf *
ldns_sign_public_evp(ldns_buffer * to_sign,EVP_PKEY * key,const EVP_MD * digest_type)443825eb42bSJan Lentfer ldns_sign_public_evp(ldns_buffer *to_sign,
444825eb42bSJan Lentfer 				 EVP_PKEY *key,
445825eb42bSJan Lentfer 				 const EVP_MD *digest_type)
446825eb42bSJan Lentfer {
447825eb42bSJan Lentfer 	unsigned int siglen;
4485340022aSzrj 	ldns_rdf *sigdata_rdf = NULL;
449825eb42bSJan Lentfer 	ldns_buffer *b64sig;
4505340022aSzrj 	EVP_MD_CTX *ctx;
451825eb42bSJan Lentfer 	const EVP_MD *md_type;
452825eb42bSJan Lentfer 	int r;
453825eb42bSJan Lentfer 
454825eb42bSJan Lentfer 	siglen = 0;
455825eb42bSJan Lentfer 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
456825eb42bSJan Lentfer 	if (!b64sig) {
457825eb42bSJan Lentfer 		return NULL;
458825eb42bSJan Lentfer 	}
459825eb42bSJan Lentfer 
460825eb42bSJan Lentfer 	/* initializes a signing context */
461825eb42bSJan Lentfer 	md_type = digest_type;
462819dec71SDaniel Fojt #ifdef USE_ED25519
463819dec71SDaniel Fojt 	if(EVP_PKEY_id(key) == NID_ED25519) {
464819dec71SDaniel Fojt 		/* digest must be NULL for ED25519 sign and verify */
465819dec71SDaniel Fojt 		md_type = NULL;
466819dec71SDaniel Fojt 	} else
467819dec71SDaniel Fojt #endif
468819dec71SDaniel Fojt #ifdef USE_ED448
469819dec71SDaniel Fojt 	if(EVP_PKEY_id(key) == NID_ED448) {
470819dec71SDaniel Fojt 		md_type = NULL;
471819dec71SDaniel Fojt 	} else
472819dec71SDaniel Fojt #endif
473825eb42bSJan Lentfer 	if(!md_type) {
474819dec71SDaniel Fojt 		/* unknown message digest */
475825eb42bSJan Lentfer 		ldns_buffer_free(b64sig);
476825eb42bSJan Lentfer 		return NULL;
477825eb42bSJan Lentfer 	}
478825eb42bSJan Lentfer 
4795340022aSzrj #ifdef HAVE_EVP_MD_CTX_NEW
4805340022aSzrj 	ctx = EVP_MD_CTX_new();
4815340022aSzrj #else
4825340022aSzrj 	ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
4835340022aSzrj 	if(ctx) EVP_MD_CTX_init(ctx);
4845340022aSzrj #endif
4855340022aSzrj 	if(!ctx) {
486825eb42bSJan Lentfer 		ldns_buffer_free(b64sig);
487825eb42bSJan Lentfer 		return NULL;
488825eb42bSJan Lentfer 	}
489825eb42bSJan Lentfer 
490819dec71SDaniel Fojt #if defined(USE_ED25519) || defined(USE_ED448)
491819dec71SDaniel Fojt 	if(md_type == NULL) {
492819dec71SDaniel Fojt 		/* for these methods we must use the one-shot DigestSign */
493819dec71SDaniel Fojt 		r = EVP_DigestSignInit(ctx, NULL, md_type, NULL, key);
494819dec71SDaniel Fojt 		if(r == 1) {
495819dec71SDaniel Fojt 			size_t siglen_sizet = ldns_buffer_capacity(b64sig);
496819dec71SDaniel Fojt 			r = EVP_DigestSign(ctx,
497819dec71SDaniel Fojt 				(unsigned char*)ldns_buffer_begin(b64sig),
498819dec71SDaniel Fojt 				&siglen_sizet,
499819dec71SDaniel Fojt 				(unsigned char*)ldns_buffer_begin(to_sign),
500819dec71SDaniel Fojt 				ldns_buffer_position(to_sign));
501819dec71SDaniel Fojt 			siglen = (unsigned int)siglen_sizet;
502819dec71SDaniel Fojt 		}
503819dec71SDaniel Fojt 	} else {
504819dec71SDaniel Fojt #else
505819dec71SDaniel Fojt 	r = 0;
506819dec71SDaniel Fojt 	if(md_type != NULL) {
507819dec71SDaniel Fojt #endif
5085340022aSzrj 		r = EVP_SignInit(ctx, md_type);
5095340022aSzrj 		if(r == 1) {
5105340022aSzrj 			r = EVP_SignUpdate(ctx, (unsigned char*)
5115340022aSzrj 						    ldns_buffer_begin(to_sign),
5125340022aSzrj 						    ldns_buffer_position(to_sign));
5135340022aSzrj 		}
5145340022aSzrj 		if(r == 1) {
5155340022aSzrj 			r = EVP_SignFinal(ctx, (unsigned char*)
5165340022aSzrj 						   ldns_buffer_begin(b64sig), &siglen, key);
517819dec71SDaniel Fojt 		}
5185340022aSzrj 	}
5195340022aSzrj 	if(r != 1) {
5205340022aSzrj 		ldns_buffer_free(b64sig);
5215340022aSzrj 		EVP_MD_CTX_destroy(ctx);
5225340022aSzrj 		return NULL;
5235340022aSzrj 	}
5245340022aSzrj 
5255340022aSzrj 	/* OpenSSL output is different, convert it */
5265340022aSzrj 	r = 0;
5275340022aSzrj #ifdef USE_DSA
5285340022aSzrj #ifndef S_SPLINT_S
5295340022aSzrj 	/* unfortunately, OpenSSL output is different from DNS DSA format */
530*ee791febSAntonio Huete Jimenez # ifdef HAVE_EVP_PKEY_GET_BASE_ID
531*ee791febSAntonio Huete Jimenez 	if (EVP_PKEY_get_base_id(key) == EVP_PKEY_DSA) {
532*ee791febSAntonio Huete Jimenez # elif defined(HAVE_EVP_PKEY_BASE_ID)
5335340022aSzrj 	if (EVP_PKEY_base_id(key) == EVP_PKEY_DSA) {
5345340022aSzrj # else
5355340022aSzrj 	if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
5365340022aSzrj # endif
5375340022aSzrj 		r = 1;
5385340022aSzrj 		sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
5395340022aSzrj 	}
5405340022aSzrj #endif
5415340022aSzrj #endif
542819dec71SDaniel Fojt #if defined(USE_ECDSA)
5435340022aSzrj 	if(
544*ee791febSAntonio Huete Jimenez #  ifdef HAVE_EVP_PKEY_GET_BASE_ID
545*ee791febSAntonio Huete Jimenez 		EVP_PKEY_get_base_id(key)
546*ee791febSAntonio Huete Jimenez #  elif defined(HAVE_EVP_PKEY_BASE_ID)
5475340022aSzrj 		EVP_PKEY_base_id(key)
5485340022aSzrj #  else
5495340022aSzrj 		EVP_PKEY_type(key->type)
5505340022aSzrj #  endif
5515340022aSzrj 		== EVP_PKEY_EC) {
5525340022aSzrj #  ifdef USE_ECDSA
5535340022aSzrj                 if(ldns_pkey_is_ecdsa(key)) {
5545340022aSzrj 			r = 1;
5555340022aSzrj 			sigdata_rdf = ldns_convert_ecdsa_rrsig_asn1len2rdf(
5565340022aSzrj 				b64sig, (long)siglen, ldns_pkey_is_ecdsa(key));
5575340022aSzrj 		}
5585340022aSzrj #  endif /* USE_ECDSA */
5595340022aSzrj 	}
5605340022aSzrj #endif /* PKEY_EC */
5615340022aSzrj 	if(r == 0) {
562825eb42bSJan Lentfer 		/* ok output for other types is the same */
563825eb42bSJan Lentfer 		sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
564825eb42bSJan Lentfer 									 ldns_buffer_begin(b64sig));
565825eb42bSJan Lentfer 	}
566825eb42bSJan Lentfer 	ldns_buffer_free(b64sig);
5675340022aSzrj 	EVP_MD_CTX_destroy(ctx);
568825eb42bSJan Lentfer 	return sigdata_rdf;
569825eb42bSJan Lentfer }
570825eb42bSJan Lentfer 
571825eb42bSJan Lentfer ldns_rdf *
572825eb42bSJan Lentfer ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
573825eb42bSJan Lentfer {
574825eb42bSJan Lentfer 	unsigned char *sha1_hash;
575825eb42bSJan Lentfer 	unsigned int siglen;
576825eb42bSJan Lentfer 	ldns_rdf *sigdata_rdf;
577825eb42bSJan Lentfer 	ldns_buffer *b64sig;
578825eb42bSJan Lentfer 	int result;
579825eb42bSJan Lentfer 
580825eb42bSJan Lentfer 	siglen = 0;
581825eb42bSJan Lentfer 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
582825eb42bSJan Lentfer 	if (!b64sig) {
583825eb42bSJan Lentfer 		return NULL;
584825eb42bSJan Lentfer 	}
585825eb42bSJan Lentfer 
586825eb42bSJan Lentfer 	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
587825eb42bSJan Lentfer 				  ldns_buffer_position(to_sign), NULL);
588825eb42bSJan Lentfer 	if (!sha1_hash) {
589825eb42bSJan Lentfer 		ldns_buffer_free(b64sig);
590825eb42bSJan Lentfer 		return NULL;
591825eb42bSJan Lentfer 	}
592825eb42bSJan Lentfer 
593825eb42bSJan Lentfer 	result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
594825eb42bSJan Lentfer 				   (unsigned char*)ldns_buffer_begin(b64sig),
595825eb42bSJan Lentfer 				   &siglen, key);
596825eb42bSJan Lentfer 	if (result != 1) {
597d1b2b5caSJohn Marino 		ldns_buffer_free(b64sig);
598825eb42bSJan Lentfer 		return NULL;
599825eb42bSJan Lentfer 	}
600825eb42bSJan Lentfer 
601825eb42bSJan Lentfer 	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
602825eb42bSJan Lentfer 								 ldns_buffer_begin(b64sig));
603825eb42bSJan Lentfer 	ldns_buffer_free(b64sig); /* can't free this buffer ?? */
604825eb42bSJan Lentfer 	return sigdata_rdf;
605825eb42bSJan Lentfer }
606825eb42bSJan Lentfer 
607825eb42bSJan Lentfer ldns_rdf *
608825eb42bSJan Lentfer ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
609825eb42bSJan Lentfer {
610825eb42bSJan Lentfer 	unsigned char *md5_hash;
611825eb42bSJan Lentfer 	unsigned int siglen;
612825eb42bSJan Lentfer 	ldns_rdf *sigdata_rdf;
613825eb42bSJan Lentfer 	ldns_buffer *b64sig;
614825eb42bSJan Lentfer 
615825eb42bSJan Lentfer 	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
616825eb42bSJan Lentfer 	if (!b64sig) {
617825eb42bSJan Lentfer 		return NULL;
618825eb42bSJan Lentfer 	}
619825eb42bSJan Lentfer 
620825eb42bSJan Lentfer 	md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
621825eb42bSJan Lentfer 				ldns_buffer_position(to_sign), NULL);
622825eb42bSJan Lentfer 	if (!md5_hash) {
623825eb42bSJan Lentfer 		ldns_buffer_free(b64sig);
624825eb42bSJan Lentfer 		return NULL;
625825eb42bSJan Lentfer 	}
626825eb42bSJan Lentfer 
627825eb42bSJan Lentfer 	RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
628825eb42bSJan Lentfer 		    (unsigned char*)ldns_buffer_begin(b64sig),
629825eb42bSJan Lentfer 		    &siglen, key);
630825eb42bSJan Lentfer 
631825eb42bSJan Lentfer 	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
632825eb42bSJan Lentfer 								 ldns_buffer_begin(b64sig));
633825eb42bSJan Lentfer 	ldns_buffer_free(b64sig);
634825eb42bSJan Lentfer 	return sigdata_rdf;
635825eb42bSJan Lentfer }
636825eb42bSJan Lentfer #endif /* HAVE_SSL */
637825eb42bSJan Lentfer 
638b5dedccaSJan Lentfer /**
639b5dedccaSJan Lentfer  * Pushes all rrs from the rrsets of type A and AAAA on gluelist.
640b5dedccaSJan Lentfer  */
641b5dedccaSJan Lentfer static ldns_status
642b5dedccaSJan Lentfer ldns_dnssec_addresses_on_glue_list(
643b5dedccaSJan Lentfer 		ldns_dnssec_rrsets *cur_rrset,
644b5dedccaSJan Lentfer 		ldns_rr_list *glue_list)
645825eb42bSJan Lentfer {
646b5dedccaSJan Lentfer 	ldns_dnssec_rrs *cur_rrs;
647825eb42bSJan Lentfer 	while (cur_rrset) {
648b5dedccaSJan Lentfer 		if (cur_rrset->type == LDNS_RR_TYPE_A
649b5dedccaSJan Lentfer 				|| cur_rrset->type == LDNS_RR_TYPE_AAAA) {
650b5dedccaSJan Lentfer 			for (cur_rrs = cur_rrset->rrs;
651b5dedccaSJan Lentfer 					cur_rrs;
652b5dedccaSJan Lentfer 					cur_rrs = cur_rrs->next) {
653b5dedccaSJan Lentfer 				if (cur_rrs->rr) {
654b5dedccaSJan Lentfer 					if (!ldns_rr_list_push_rr(glue_list,
655b5dedccaSJan Lentfer 							cur_rrs->rr)) {
656b5dedccaSJan Lentfer 						return LDNS_STATUS_MEM_ERR;
657b5dedccaSJan Lentfer 						/* ldns_rr_list_push_rr()
658b5dedccaSJan Lentfer 						 * returns false when unable
659b5dedccaSJan Lentfer 						 * to increase the capacity
660*ee791febSAntonio Huete Jimenez 						 * of the ldns_rr_list
661b5dedccaSJan Lentfer 						 */
662b5dedccaSJan Lentfer 					}
663b5dedccaSJan Lentfer 				}
664b5dedccaSJan Lentfer 			}
665b5dedccaSJan Lentfer 		}
666825eb42bSJan Lentfer 		cur_rrset = cur_rrset->next;
667825eb42bSJan Lentfer 	}
668b5dedccaSJan Lentfer 	return LDNS_STATUS_OK;
669825eb42bSJan Lentfer }
670825eb42bSJan Lentfer 
671b5dedccaSJan Lentfer ldns_status
672b5dedccaSJan Lentfer ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone,
673b5dedccaSJan Lentfer 	ldns_rr_list *glue_list)
674b5dedccaSJan Lentfer {
675b5dedccaSJan Lentfer 	ldns_rbnode_t    *node;
676b5dedccaSJan Lentfer 	ldns_dnssec_name *name;
677b5dedccaSJan Lentfer 	ldns_rdf         *owner;
678b5dedccaSJan Lentfer 	ldns_rdf         *cut = NULL; /* keeps track of zone cuts */
679b5dedccaSJan Lentfer 	/* When the cut is caused by a delegation, below_delegation will be 1.
680b5dedccaSJan Lentfer 	 * When caused by a DNAME, below_delegation will be 0.
681b5dedccaSJan Lentfer 	 */
682*ee791febSAntonio Huete Jimenez 	int below_delegation = -1; /* init suppresses compiler warning */
683b5dedccaSJan Lentfer 	ldns_status s;
684b5dedccaSJan Lentfer 
685b5dedccaSJan Lentfer 	if (!zone || !zone->names) {
686b5dedccaSJan Lentfer 		return LDNS_STATUS_NULL;
687825eb42bSJan Lentfer 	}
688b5dedccaSJan Lentfer 	for (node = ldns_rbtree_first(zone->names);
689b5dedccaSJan Lentfer 			node != LDNS_RBTREE_NULL;
690b5dedccaSJan Lentfer 			node = ldns_rbtree_next(node)) {
691b5dedccaSJan Lentfer 		name = (ldns_dnssec_name *) node->data;
692b5dedccaSJan Lentfer 		owner = ldns_dnssec_name_name(name);
693b5dedccaSJan Lentfer 
694b5dedccaSJan Lentfer 		if (cut) {
695b5dedccaSJan Lentfer 			/* The previous node was a zone cut, or a subdomain
696b5dedccaSJan Lentfer 			 * below a zone cut. Is this node (still) a subdomain
697b5dedccaSJan Lentfer 			 * below the cut? Then the name is occluded. Unless
698b5dedccaSJan Lentfer 			 * the name contains a SOA, after which we are
699b5dedccaSJan Lentfer 			 * authoritative again.
700b5dedccaSJan Lentfer 			 *
701b5dedccaSJan Lentfer 			 * FIXME! If there are labels in between the SOA and
702b5dedccaSJan Lentfer 			 * the cut, going from the authoritative space (below
703b5dedccaSJan Lentfer 			 * the SOA) up into occluded space again, will not be
704*ee791febSAntonio Huete Jimenez 			 * detected with the construct below!
705b5dedccaSJan Lentfer 			 */
706b5dedccaSJan Lentfer 			if (ldns_dname_is_subdomain(owner, cut) &&
707b5dedccaSJan Lentfer 					!ldns_dnssec_rrsets_contains_type(
708b5dedccaSJan Lentfer 					name->rrsets, LDNS_RR_TYPE_SOA)) {
709b5dedccaSJan Lentfer 
710b5dedccaSJan Lentfer 				if (below_delegation && glue_list) {
711b5dedccaSJan Lentfer 					s = ldns_dnssec_addresses_on_glue_list(
712b5dedccaSJan Lentfer 						name->rrsets, glue_list);
713b5dedccaSJan Lentfer 					if (s != LDNS_STATUS_OK) {
714b5dedccaSJan Lentfer 						return s;
715825eb42bSJan Lentfer 					}
716b5dedccaSJan Lentfer 				}
717b5dedccaSJan Lentfer 				name->is_glue = true; /* Mark occluded name! */
718b5dedccaSJan Lentfer 				continue;
719b5dedccaSJan Lentfer 			} else {
720b5dedccaSJan Lentfer 				cut = NULL;
721b5dedccaSJan Lentfer 			}
722b5dedccaSJan Lentfer 		}
723b5dedccaSJan Lentfer 
724b5dedccaSJan Lentfer 		/* The node is not below a zone cut. Is it a zone cut itself?
725b5dedccaSJan Lentfer 		 * Everything below a SOA is authoritative of course; Except
726b5dedccaSJan Lentfer 		 * when the name also contains a DNAME :).
727b5dedccaSJan Lentfer 		 */
728b5dedccaSJan Lentfer 		if (ldns_dnssec_rrsets_contains_type(
729b5dedccaSJan Lentfer 				name->rrsets, LDNS_RR_TYPE_NS)
730b5dedccaSJan Lentfer 			    && !ldns_dnssec_rrsets_contains_type(
731b5dedccaSJan Lentfer 				name->rrsets, LDNS_RR_TYPE_SOA)) {
732b5dedccaSJan Lentfer 			cut = owner;
733b5dedccaSJan Lentfer 			below_delegation = 1;
734b5dedccaSJan Lentfer 			if (glue_list) { /* record glue on the zone cut */
735b5dedccaSJan Lentfer 				s = ldns_dnssec_addresses_on_glue_list(
736b5dedccaSJan Lentfer 					name->rrsets, glue_list);
737b5dedccaSJan Lentfer 				if (s != LDNS_STATUS_OK) {
738b5dedccaSJan Lentfer 					return s;
739b5dedccaSJan Lentfer 				}
740b5dedccaSJan Lentfer 			}
741b5dedccaSJan Lentfer 		} else if (ldns_dnssec_rrsets_contains_type(
742b5dedccaSJan Lentfer 				name->rrsets, LDNS_RR_TYPE_DNAME)) {
743b5dedccaSJan Lentfer 			cut = owner;
744b5dedccaSJan Lentfer 			below_delegation = 0;
745825eb42bSJan Lentfer 		}
746825eb42bSJan Lentfer 	}
747825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
748825eb42bSJan Lentfer }
749825eb42bSJan Lentfer 
750b5dedccaSJan Lentfer ldns_status
751b5dedccaSJan Lentfer ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
752b5dedccaSJan Lentfer {
753b5dedccaSJan Lentfer 	return ldns_dnssec_zone_mark_and_get_glue(zone, NULL);
754b5dedccaSJan Lentfer }
755b5dedccaSJan Lentfer 
756825eb42bSJan Lentfer ldns_rbnode_t *
757825eb42bSJan Lentfer ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
758825eb42bSJan Lentfer {
759825eb42bSJan Lentfer 	ldns_rbnode_t *next_node = NULL;
760825eb42bSJan Lentfer 	ldns_dnssec_name *next_name = NULL;
761825eb42bSJan Lentfer 	bool done = false;
762825eb42bSJan Lentfer 
763825eb42bSJan Lentfer 	if (node == LDNS_RBTREE_NULL) {
764825eb42bSJan Lentfer 		return NULL;
765825eb42bSJan Lentfer 	}
766825eb42bSJan Lentfer 	next_node = node;
767825eb42bSJan Lentfer 	while (!done) {
768825eb42bSJan Lentfer 		if (next_node == LDNS_RBTREE_NULL) {
769825eb42bSJan Lentfer 			return NULL;
770825eb42bSJan Lentfer 		} else {
771825eb42bSJan Lentfer 			next_name = (ldns_dnssec_name *)next_node->data;
772825eb42bSJan Lentfer 			if (!next_name->is_glue) {
773825eb42bSJan Lentfer 				done = true;
774825eb42bSJan Lentfer 			} else {
775825eb42bSJan Lentfer 				next_node = ldns_rbtree_next(next_node);
776825eb42bSJan Lentfer 			}
777825eb42bSJan Lentfer 		}
778825eb42bSJan Lentfer 	}
779825eb42bSJan Lentfer 	return next_node;
780825eb42bSJan Lentfer }
781825eb42bSJan Lentfer 
782825eb42bSJan Lentfer ldns_status
783825eb42bSJan Lentfer ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
784825eb42bSJan Lentfer                               ldns_rr_list *new_rrs)
785825eb42bSJan Lentfer {
786825eb42bSJan Lentfer 
787825eb42bSJan Lentfer 	ldns_rbnode_t *first_node, *cur_node, *next_node;
788825eb42bSJan Lentfer 	ldns_dnssec_name *cur_name, *next_name;
789825eb42bSJan Lentfer 	ldns_rr *nsec_rr;
790825eb42bSJan Lentfer 	uint32_t nsec_ttl;
791825eb42bSJan Lentfer 	ldns_dnssec_rrsets *soa;
792825eb42bSJan Lentfer 
793*ee791febSAntonio Huete Jimenez 	/* The TTL value for any NSEC RR SHOULD be the same TTL value as the
794*ee791febSAntonio Huete Jimenez 	 * lesser of the MINIMUM field of the SOA record and the TTL of the SOA
795*ee791febSAntonio Huete Jimenez 	 * itself. This matches the definition of the TTL for negative
796*ee791febSAntonio Huete Jimenez 	 * responses in [RFC2308]. (draft-ietf-dnsop-nsec-ttl-01 update of
797*ee791febSAntonio Huete Jimenez 	 * RFC4035 Section 2.3)
798825eb42bSJan Lentfer 	 */
799825eb42bSJan Lentfer 	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
800825eb42bSJan Lentfer 
801825eb42bSJan Lentfer 	/* did the caller actually set it? if not,
802825eb42bSJan Lentfer 	 * fall back to default ttl
803825eb42bSJan Lentfer 	 */
804*ee791febSAntonio Huete Jimenez 	if (soa && soa->rrs && soa->rrs->rr) {
805*ee791febSAntonio Huete Jimenez 		ldns_rr  *soa_rr  = soa->rrs->rr;
806*ee791febSAntonio Huete Jimenez 		ldns_rdf *min_rdf = ldns_rr_rdf(soa_rr, 6);
807*ee791febSAntonio Huete Jimenez 
808*ee791febSAntonio Huete Jimenez 		nsec_ttl = min_rdf == NULL
809*ee791febSAntonio Huete Jimenez 		       || ldns_rr_ttl(soa_rr) < ldns_rdf2native_int32(min_rdf)
810*ee791febSAntonio Huete Jimenez 		        ? ldns_rr_ttl(soa_rr) : ldns_rdf2native_int32(min_rdf);
811825eb42bSJan Lentfer 	} else {
812825eb42bSJan Lentfer 		nsec_ttl = LDNS_DEFAULT_TTL;
813825eb42bSJan Lentfer 	}
814825eb42bSJan Lentfer 
815825eb42bSJan Lentfer 	first_node = ldns_dnssec_name_node_next_nonglue(
816825eb42bSJan Lentfer 			       ldns_rbtree_first(zone->names));
817825eb42bSJan Lentfer 	cur_node = first_node;
818825eb42bSJan Lentfer 	if (cur_node) {
819825eb42bSJan Lentfer 		next_node = ldns_dnssec_name_node_next_nonglue(
820825eb42bSJan Lentfer 			           ldns_rbtree_next(cur_node));
821825eb42bSJan Lentfer 	} else {
822825eb42bSJan Lentfer 		next_node = NULL;
823825eb42bSJan Lentfer 	}
824825eb42bSJan Lentfer 
825825eb42bSJan Lentfer 	while (cur_node && next_node) {
826825eb42bSJan Lentfer 		cur_name = (ldns_dnssec_name *)cur_node->data;
827825eb42bSJan Lentfer 		next_name = (ldns_dnssec_name *)next_node->data;
828825eb42bSJan Lentfer 		nsec_rr = ldns_dnssec_create_nsec(cur_name,
829825eb42bSJan Lentfer 		                                  next_name,
830825eb42bSJan Lentfer 		                                  LDNS_RR_TYPE_NSEC);
831825eb42bSJan Lentfer 		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
832fd185f4dSJan Lentfer 		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
833fd185f4dSJan Lentfer 			ldns_rr_free(nsec_rr);
834fd185f4dSJan Lentfer 			return LDNS_STATUS_ERR;
835fd185f4dSJan Lentfer 		}
836825eb42bSJan Lentfer 		ldns_rr_list_push_rr(new_rrs, nsec_rr);
837825eb42bSJan Lentfer 		cur_node = next_node;
838825eb42bSJan Lentfer 		if (cur_node) {
839825eb42bSJan Lentfer 			next_node = ldns_dnssec_name_node_next_nonglue(
840825eb42bSJan Lentfer                                ldns_rbtree_next(cur_node));
841825eb42bSJan Lentfer 		}
842825eb42bSJan Lentfer 	}
843825eb42bSJan Lentfer 
844825eb42bSJan Lentfer 	if (cur_node && !next_node) {
845825eb42bSJan Lentfer 		cur_name = (ldns_dnssec_name *)cur_node->data;
846825eb42bSJan Lentfer 		next_name = (ldns_dnssec_name *)first_node->data;
847825eb42bSJan Lentfer 		nsec_rr = ldns_dnssec_create_nsec(cur_name,
848825eb42bSJan Lentfer 		                                  next_name,
849825eb42bSJan Lentfer 		                                  LDNS_RR_TYPE_NSEC);
850825eb42bSJan Lentfer 		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
851fd185f4dSJan Lentfer 		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
852fd185f4dSJan Lentfer 			ldns_rr_free(nsec_rr);
853fd185f4dSJan Lentfer 			return LDNS_STATUS_ERR;
854fd185f4dSJan Lentfer 		}
855825eb42bSJan Lentfer 		ldns_rr_list_push_rr(new_rrs, nsec_rr);
856825eb42bSJan Lentfer 	} else {
857825eb42bSJan Lentfer 		printf("error\n");
858825eb42bSJan Lentfer 	}
859825eb42bSJan Lentfer 
860825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
861825eb42bSJan Lentfer }
862825eb42bSJan Lentfer 
863825eb42bSJan Lentfer #ifdef HAVE_SSL
8645340022aSzrj static void
8655340022aSzrj ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
8665340022aSzrj 	(void) arg;
8675340022aSzrj 	LDNS_FREE(node);
8685340022aSzrj }
869b5dedccaSJan Lentfer 
8705340022aSzrj static ldns_status
871b5dedccaSJan Lentfer ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
872825eb42bSJan Lentfer 		ldns_rr_list *new_rrs,
873825eb42bSJan Lentfer 		uint8_t algorithm,
874825eb42bSJan Lentfer 		uint8_t flags,
875825eb42bSJan Lentfer 		uint16_t iterations,
876825eb42bSJan Lentfer 		uint8_t salt_length,
877b5dedccaSJan Lentfer 		uint8_t *salt,
878b5dedccaSJan Lentfer 		ldns_rbtree_t **map)
879825eb42bSJan Lentfer {
880825eb42bSJan Lentfer 	ldns_rbnode_t *first_name_node;
881825eb42bSJan Lentfer 	ldns_rbnode_t *current_name_node;
882825eb42bSJan Lentfer 	ldns_dnssec_name *current_name;
883825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
884825eb42bSJan Lentfer 	ldns_rr *nsec_rr;
885825eb42bSJan Lentfer 	ldns_rr_list *nsec3_list;
886825eb42bSJan Lentfer 	uint32_t nsec_ttl;
887825eb42bSJan Lentfer 	ldns_dnssec_rrsets *soa;
888b5dedccaSJan Lentfer 	ldns_rbnode_t *hashmap_node;
889825eb42bSJan Lentfer 
890825eb42bSJan Lentfer 	if (!zone || !new_rrs || !zone->names) {
891825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
892825eb42bSJan Lentfer 	}
893825eb42bSJan Lentfer 
894*ee791febSAntonio Huete Jimenez 	/* The TTL value for any NSEC RR SHOULD be the same TTL value as the
895*ee791febSAntonio Huete Jimenez 	 * lesser of the MINIMUM field of the SOA record and the TTL of the SOA
896*ee791febSAntonio Huete Jimenez 	 * itself. This matches the definition of the TTL for negative
897*ee791febSAntonio Huete Jimenez 	 * responses in [RFC2308]. (draft-ietf-dnsop-nsec-ttl-01 update of
898*ee791febSAntonio Huete Jimenez 	 * RFC4035 Section 2.3)
899825eb42bSJan Lentfer 	 */
900825eb42bSJan Lentfer 	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
901825eb42bSJan Lentfer 
902825eb42bSJan Lentfer 	/* did the caller actually set it? if not,
903825eb42bSJan Lentfer 	 * fall back to default ttl
904825eb42bSJan Lentfer 	 */
905*ee791febSAntonio Huete Jimenez 	if (soa && soa->rrs && soa->rrs->rr) {
906*ee791febSAntonio Huete Jimenez 		ldns_rr  *soa_rr  = soa->rrs->rr;
907*ee791febSAntonio Huete Jimenez 		ldns_rdf *min_rdf = ldns_rr_rdf(soa_rr, 6);
908*ee791febSAntonio Huete Jimenez 
909*ee791febSAntonio Huete Jimenez 		nsec_ttl = min_rdf == NULL
910*ee791febSAntonio Huete Jimenez 		       || ldns_rr_ttl(soa_rr) < ldns_rdf2native_int32(min_rdf)
911*ee791febSAntonio Huete Jimenez 		        ? ldns_rr_ttl(soa_rr) : ldns_rdf2native_int32(min_rdf);
912825eb42bSJan Lentfer 	} else {
913825eb42bSJan Lentfer 		nsec_ttl = LDNS_DEFAULT_TTL;
914825eb42bSJan Lentfer 	}
915825eb42bSJan Lentfer 
9165340022aSzrj 	if (ldns_rdf_size(zone->soa->name) > 222) {
9175340022aSzrj 		return LDNS_STATUS_NSEC3_DOMAINNAME_OVERFLOW;
918b5dedccaSJan Lentfer 	}
9195340022aSzrj 
9205340022aSzrj 	if (zone->hashed_names) {
9215340022aSzrj 		ldns_traverse_postorder(zone->hashed_names,
9225340022aSzrj 				ldns_hashed_names_node_free, NULL);
9235340022aSzrj 		LDNS_FREE(zone->hashed_names);
9245340022aSzrj 	}
9255340022aSzrj 	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
9265340022aSzrj 	if (zone->hashed_names && map) {
9275340022aSzrj 		*map = zone->hashed_names;
9285340022aSzrj 	}
929825eb42bSJan Lentfer 
930825eb42bSJan Lentfer 	first_name_node = ldns_dnssec_name_node_next_nonglue(
931825eb42bSJan Lentfer 					  ldns_rbtree_first(zone->names));
932825eb42bSJan Lentfer 
933825eb42bSJan Lentfer 	current_name_node = first_name_node;
934825eb42bSJan Lentfer 
9355340022aSzrj 	while (current_name_node && current_name_node != LDNS_RBTREE_NULL &&
9365340022aSzrj 			result == LDNS_STATUS_OK) {
9375340022aSzrj 
938825eb42bSJan Lentfer 		current_name = (ldns_dnssec_name *) current_name_node->data;
939825eb42bSJan Lentfer 		nsec_rr = ldns_dnssec_create_nsec3(current_name,
940825eb42bSJan Lentfer 		                                   NULL,
941825eb42bSJan Lentfer 		                                   zone->soa->name,
942825eb42bSJan Lentfer 		                                   algorithm,
943825eb42bSJan Lentfer 		                                   flags,
944825eb42bSJan Lentfer 		                                   iterations,
945825eb42bSJan Lentfer 		                                   salt_length,
946825eb42bSJan Lentfer 		                                   salt);
947825eb42bSJan Lentfer 		/* by default, our nsec based generator adds rrsigs
948825eb42bSJan Lentfer 		 * remove the bitmap for empty nonterminals */
949825eb42bSJan Lentfer 		if (!current_name->rrsets) {
950825eb42bSJan Lentfer 			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
951825eb42bSJan Lentfer 		}
952825eb42bSJan Lentfer 		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
953fd185f4dSJan Lentfer 		result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
954825eb42bSJan Lentfer 		ldns_rr_list_push_rr(new_rrs, nsec_rr);
9555340022aSzrj 		if (ldns_rr_owner(nsec_rr)) {
956b5dedccaSJan Lentfer 			hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
9575340022aSzrj 			if (hashmap_node == NULL) {
9585340022aSzrj 				return LDNS_STATUS_MEM_ERR;
959b5dedccaSJan Lentfer 			}
9605340022aSzrj 			current_name->hashed_name =
9615340022aSzrj 				ldns_dname_label(ldns_rr_owner(nsec_rr), 0);
9625340022aSzrj 
9635340022aSzrj 			if (current_name->hashed_name == NULL) {
9645340022aSzrj 				LDNS_FREE(hashmap_node);
9655340022aSzrj 				return LDNS_STATUS_MEM_ERR;
9665340022aSzrj 			}
9675340022aSzrj 			hashmap_node->key  = current_name->hashed_name;
9685340022aSzrj 			hashmap_node->data = current_name;
9695340022aSzrj 
9705340022aSzrj 			if (! ldns_rbtree_insert(zone->hashed_names
9715340022aSzrj 						, hashmap_node)) {
9725340022aSzrj 				LDNS_FREE(hashmap_node);
973b5dedccaSJan Lentfer 			}
974b5dedccaSJan Lentfer 		}
975825eb42bSJan Lentfer 		current_name_node = ldns_dnssec_name_node_next_nonglue(
976825eb42bSJan Lentfer 		                   ldns_rbtree_next(current_name_node));
977825eb42bSJan Lentfer 	}
978fd185f4dSJan Lentfer 	if (result != LDNS_STATUS_OK) {
979fd185f4dSJan Lentfer 		return result;
980fd185f4dSJan Lentfer 	}
981825eb42bSJan Lentfer 
9825340022aSzrj 	/* Make sorted list of nsec3s (via zone->hashed_names)
9835340022aSzrj 	 */
9845340022aSzrj 	nsec3_list = ldns_rr_list_new();
9855340022aSzrj 	if (nsec3_list == NULL) {
9865340022aSzrj 		return LDNS_STATUS_MEM_ERR;
9875340022aSzrj 	}
9885340022aSzrj 	for ( hashmap_node  = ldns_rbtree_first(zone->hashed_names)
9895340022aSzrj 	    ; hashmap_node != LDNS_RBTREE_NULL
9905340022aSzrj 	    ; hashmap_node  = ldns_rbtree_next(hashmap_node)
9915340022aSzrj 	    ) {
9925340022aSzrj 		nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec;
9935340022aSzrj 		if (nsec_rr) {
9945340022aSzrj 			ldns_rr_list_push_rr(nsec3_list, nsec_rr);
9955340022aSzrj 		}
9965340022aSzrj 	}
997fd185f4dSJan Lentfer 	result = ldns_dnssec_chain_nsec3_list(nsec3_list);
998825eb42bSJan Lentfer 	ldns_rr_list_free(nsec3_list);
999d1b2b5caSJohn Marino 
1000825eb42bSJan Lentfer 	return result;
1001825eb42bSJan Lentfer }
1002b5dedccaSJan Lentfer 
1003b5dedccaSJan Lentfer ldns_status
1004b5dedccaSJan Lentfer ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
1005b5dedccaSJan Lentfer 		ldns_rr_list *new_rrs,
1006b5dedccaSJan Lentfer 		uint8_t algorithm,
1007b5dedccaSJan Lentfer 		uint8_t flags,
1008b5dedccaSJan Lentfer 		uint16_t iterations,
1009b5dedccaSJan Lentfer 		uint8_t salt_length,
1010b5dedccaSJan Lentfer 		uint8_t *salt)
1011b5dedccaSJan Lentfer {
1012b5dedccaSJan Lentfer 	return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm,
1013b5dedccaSJan Lentfer 		       	flags, iterations, salt_length, salt, NULL);
1014b5dedccaSJan Lentfer 
1015b5dedccaSJan Lentfer }
1016825eb42bSJan Lentfer #endif /* HAVE_SSL */
1017825eb42bSJan Lentfer 
1018825eb42bSJan Lentfer ldns_dnssec_rrs *
1019d1b2b5caSJohn Marino ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures
1020d1b2b5caSJohn Marino 			     , ATTR_UNUSED(ldns_key_list *key_list)
1021d1b2b5caSJohn Marino 			     , int (*func)(ldns_rr *, void *)
1022d1b2b5caSJohn Marino 			     , void *arg
1023d1b2b5caSJohn Marino 			     )
1024825eb42bSJan Lentfer {
1025825eb42bSJan Lentfer 	ldns_dnssec_rrs *base_rrs = signatures;
1026825eb42bSJan Lentfer 	ldns_dnssec_rrs *cur_rr = base_rrs;
1027825eb42bSJan Lentfer 	ldns_dnssec_rrs *prev_rr = NULL;
1028825eb42bSJan Lentfer 	ldns_dnssec_rrs *next_rr;
1029825eb42bSJan Lentfer 
1030825eb42bSJan Lentfer 	uint16_t keytag;
1031825eb42bSJan Lentfer 	size_t i;
1032825eb42bSJan Lentfer 
1033825eb42bSJan Lentfer 	if (!cur_rr) {
1034825eb42bSJan Lentfer 		switch(func(NULL, arg)) {
1035825eb42bSJan Lentfer 		case LDNS_SIGNATURE_LEAVE_ADD_NEW:
1036825eb42bSJan Lentfer 		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
1037825eb42bSJan Lentfer 		break;
1038825eb42bSJan Lentfer 		case LDNS_SIGNATURE_LEAVE_NO_ADD:
1039825eb42bSJan Lentfer 		case LDNS_SIGNATURE_REMOVE_NO_ADD:
1040825eb42bSJan Lentfer 		ldns_key_list_set_use(key_list, false);
1041825eb42bSJan Lentfer 		break;
1042825eb42bSJan Lentfer 		default:
10435340022aSzrj #ifdef STDERR_MSGS
1044825eb42bSJan Lentfer 			fprintf(stderr, "[XX] unknown return value from callback\n");
10455340022aSzrj #endif
1046825eb42bSJan Lentfer 			break;
1047825eb42bSJan Lentfer 		}
1048825eb42bSJan Lentfer 		return NULL;
1049825eb42bSJan Lentfer 	}
1050ac996e71SJan Lentfer 	(void)func(cur_rr->rr, arg);
1051825eb42bSJan Lentfer 
1052825eb42bSJan Lentfer 	while (cur_rr) {
1053825eb42bSJan Lentfer 		next_rr = cur_rr->next;
1054825eb42bSJan Lentfer 
1055825eb42bSJan Lentfer 		switch (func(cur_rr->rr, arg)) {
1056825eb42bSJan Lentfer 		case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
1057825eb42bSJan Lentfer 			prev_rr = cur_rr;
1058825eb42bSJan Lentfer 			break;
1059825eb42bSJan Lentfer 		case LDNS_SIGNATURE_LEAVE_NO_ADD:
1060825eb42bSJan Lentfer 			keytag = ldns_rdf2native_int16(
1061825eb42bSJan Lentfer 					   ldns_rr_rrsig_keytag(cur_rr->rr));
1062825eb42bSJan Lentfer 			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
1063825eb42bSJan Lentfer 				if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
1064825eb42bSJan Lentfer 				    keytag) {
1065825eb42bSJan Lentfer 					ldns_key_set_use(ldns_key_list_key(key_list, i),
1066825eb42bSJan Lentfer 								  false);
1067825eb42bSJan Lentfer 				}
1068825eb42bSJan Lentfer 			}
1069825eb42bSJan Lentfer 			prev_rr = cur_rr;
1070825eb42bSJan Lentfer 			break;
1071825eb42bSJan Lentfer 		case LDNS_SIGNATURE_REMOVE_NO_ADD:
1072825eb42bSJan Lentfer 			keytag = ldns_rdf2native_int16(
1073825eb42bSJan Lentfer 					   ldns_rr_rrsig_keytag(cur_rr->rr));
1074825eb42bSJan Lentfer 			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
1075825eb42bSJan Lentfer 				if (ldns_key_keytag(ldns_key_list_key(key_list, i))
1076825eb42bSJan Lentfer 				    == keytag) {
1077825eb42bSJan Lentfer 					ldns_key_set_use(ldns_key_list_key(key_list, i),
1078825eb42bSJan Lentfer 								  false);
1079825eb42bSJan Lentfer 				}
1080825eb42bSJan Lentfer 			}
1081825eb42bSJan Lentfer 			if (prev_rr) {
1082825eb42bSJan Lentfer 				prev_rr->next = next_rr;
1083825eb42bSJan Lentfer 			} else {
1084825eb42bSJan Lentfer 				base_rrs = next_rr;
1085825eb42bSJan Lentfer 			}
1086825eb42bSJan Lentfer 			LDNS_FREE(cur_rr);
1087825eb42bSJan Lentfer 			break;
1088825eb42bSJan Lentfer 		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
1089825eb42bSJan Lentfer 			if (prev_rr) {
1090825eb42bSJan Lentfer 				prev_rr->next = next_rr;
1091825eb42bSJan Lentfer 			} else {
1092825eb42bSJan Lentfer 				base_rrs = next_rr;
1093825eb42bSJan Lentfer 			}
1094825eb42bSJan Lentfer 			LDNS_FREE(cur_rr);
1095825eb42bSJan Lentfer 			break;
1096825eb42bSJan Lentfer 		default:
10975340022aSzrj #ifdef STDERR_MSGS
1098825eb42bSJan Lentfer 			fprintf(stderr, "[XX] unknown return value from callback\n");
10995340022aSzrj #endif
1100825eb42bSJan Lentfer 			break;
1101825eb42bSJan Lentfer 		}
1102825eb42bSJan Lentfer 		cur_rr = next_rr;
1103825eb42bSJan Lentfer 	}
1104825eb42bSJan Lentfer 
1105825eb42bSJan Lentfer 	return base_rrs;
1106825eb42bSJan Lentfer }
1107825eb42bSJan Lentfer 
1108825eb42bSJan Lentfer #ifdef HAVE_SSL
1109825eb42bSJan Lentfer ldns_status
1110825eb42bSJan Lentfer ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
1111825eb42bSJan Lentfer                                ldns_rr_list *new_rrs,
1112825eb42bSJan Lentfer                                ldns_key_list *key_list,
1113825eb42bSJan Lentfer                                int (*func)(ldns_rr *, void*),
1114825eb42bSJan Lentfer                                void *arg)
1115825eb42bSJan Lentfer {
1116825eb42bSJan Lentfer 	return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list,
1117825eb42bSJan Lentfer 		func, arg, 0);
1118825eb42bSJan Lentfer }
1119825eb42bSJan Lentfer 
1120825eb42bSJan Lentfer /** If there are KSKs use only them and mark ZSKs unused */
1121825eb42bSJan Lentfer static void
11225340022aSzrj ldns_key_list_filter_for_dnskey(ldns_key_list *key_list, int flags)
1123825eb42bSJan Lentfer {
11245340022aSzrj 	bool algos[256]
11255340022aSzrj #ifndef S_SPLINT_S
11265340022aSzrj 	                = { false }
11275340022aSzrj #endif
11285340022aSzrj 	                           ;
11295340022aSzrj 	ldns_signing_algorithm saw_ksk = 0;
11305340022aSzrj 	ldns_key *key;
1131825eb42bSJan Lentfer 	size_t i;
11325340022aSzrj 
11335340022aSzrj 	if (!ldns_key_list_key_count(key_list))
11345340022aSzrj 		return;
11355340022aSzrj 
1136*ee791febSAntonio Huete Jimenez 	/* Mark all KSKs */
11375340022aSzrj 	for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
11385340022aSzrj 		key = ldns_key_list_key(key_list, i);
1139*ee791febSAntonio Huete Jimenez 		if ((ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
1140*ee791febSAntonio Huete Jimenez 			if (!saw_ksk)
11415340022aSzrj 				saw_ksk = ldns_key_algorithm(key);
11425340022aSzrj 			algos[ldns_key_algorithm(key)] = true;
1143825eb42bSJan Lentfer 		}
1144*ee791febSAntonio Huete Jimenez 	}
1145825eb42bSJan Lentfer 	if (!saw_ksk)
1146*ee791febSAntonio Huete Jimenez 		return; /* No KSKs means sign using all ZSKs */
11475340022aSzrj 
1148*ee791febSAntonio Huete Jimenez 	/* Deselect the ZSKs so they do not sign DNSKEY RRs.
1149*ee791febSAntonio Huete Jimenez 	 * Except with the LDNS_SIGN_WITH_ALL_ALGORITHMS flag, then use it,
1150*ee791febSAntonio Huete Jimenez 	 * but only if it has an algorithm for which there is no KSK
1151*ee791febSAntonio Huete Jimenez 	 */
11525340022aSzrj 	for (i =0; i < ldns_key_list_key_count(key_list); i++) {
11535340022aSzrj 		key = ldns_key_list_key(key_list, i);
11545340022aSzrj 		if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
11555340022aSzrj 			/* We have a ZSK.
11565340022aSzrj 			 * Still use it if it has a unique algorithm though!
11575340022aSzrj 			 */
11585340022aSzrj 			if ((flags & LDNS_SIGN_WITH_ALL_ALGORITHMS) &&
1159*ee791febSAntonio Huete Jimenez 			    !algos[ldns_key_algorithm(key)])
1160*ee791febSAntonio Huete Jimenez 				algos[ldns_key_algorithm(key)] = true;
11615340022aSzrj 			else
11625340022aSzrj 				ldns_key_set_use(key, 0);
11635340022aSzrj 		}
11645340022aSzrj 	}
1165825eb42bSJan Lentfer }
1166825eb42bSJan Lentfer 
1167*ee791febSAntonio Huete Jimenez /** If there are no ZSKs use KSKs as ZSK too */
1168ac996e71SJan Lentfer static void
11695340022aSzrj ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list, int flags)
1170ac996e71SJan Lentfer {
11715340022aSzrj 	bool algos[256]
11725340022aSzrj #ifndef S_SPLINT_S
11735340022aSzrj 	                = { false }
11745340022aSzrj #endif
11755340022aSzrj 	                           ;
11765340022aSzrj 	ldns_signing_algorithm saw_zsk = 0;
11775340022aSzrj 	ldns_key *key;
1178ac996e71SJan Lentfer 	size_t i;
11795340022aSzrj 
11805340022aSzrj 	if (!ldns_key_list_key_count(key_list))
11815340022aSzrj 		return;
11825340022aSzrj 
1183*ee791febSAntonio Huete Jimenez 	/* Mark all ZSKs */
11845340022aSzrj 	for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
11855340022aSzrj 		key = ldns_key_list_key(key_list, i);
1186*ee791febSAntonio Huete Jimenez 		if (!(ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
1187*ee791febSAntonio Huete Jimenez 			if (!saw_zsk)
11885340022aSzrj 				saw_zsk = ldns_key_algorithm(key);
11895340022aSzrj 			algos[ldns_key_algorithm(key)] = true;
1190ac996e71SJan Lentfer 		}
1191*ee791febSAntonio Huete Jimenez 	}
1192ac996e71SJan Lentfer 	if (!saw_zsk)
1193*ee791febSAntonio Huete Jimenez 		return; /* No ZSKs means sign using all KSKs */
11945340022aSzrj 
1195*ee791febSAntonio Huete Jimenez 	/* Deselect the KSKs so they do not sign non DNSKEY RRs.
1196*ee791febSAntonio Huete Jimenez 	 * Except with the LDNS_SIGN_WITH_ALL_ALGORITHMS flag, then use it,
1197*ee791febSAntonio Huete Jimenez 	 * but only if it has an algorithm for which there is no ZSK
1198*ee791febSAntonio Huete Jimenez 	 */
11995340022aSzrj 	for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
12005340022aSzrj 		key = ldns_key_list_key(key_list, i);
12015340022aSzrj 		if((ldns_key_flags(key) & LDNS_KEY_SEP_KEY)) {
12025340022aSzrj 			/* We have a KSK.
12035340022aSzrj 			 * Still use it if it has a unique algorithm though!
12045340022aSzrj 			 */
12055340022aSzrj 			if ((flags & LDNS_SIGN_WITH_ALL_ALGORITHMS) &&
1206*ee791febSAntonio Huete Jimenez 			    !algos[ldns_key_algorithm(key)])
1207*ee791febSAntonio Huete Jimenez 				algos[ldns_key_algorithm(key)] = true;
12085340022aSzrj 			else
12095340022aSzrj 				ldns_key_set_use(key, 0);
12105340022aSzrj 		}
12115340022aSzrj 	}
1212ac996e71SJan Lentfer }
1213ac996e71SJan Lentfer 
1214825eb42bSJan Lentfer ldns_status
1215d1b2b5caSJohn Marino ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
1216d1b2b5caSJohn Marino 				  , ldns_rr_list *new_rrs
1217d1b2b5caSJohn Marino 				  , ldns_key_list *key_list
1218d1b2b5caSJohn Marino 				  , int (*func)(ldns_rr *, void*)
1219d1b2b5caSJohn Marino 				  , void *arg
1220d1b2b5caSJohn Marino 				  , int flags
1221d1b2b5caSJohn Marino 				  )
1222825eb42bSJan Lentfer {
1223825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
1224825eb42bSJan Lentfer 
1225825eb42bSJan Lentfer 	ldns_rbnode_t *cur_node;
1226825eb42bSJan Lentfer 	ldns_rr_list *rr_list;
1227825eb42bSJan Lentfer 
1228825eb42bSJan Lentfer 	ldns_dnssec_name *cur_name;
1229825eb42bSJan Lentfer 	ldns_dnssec_rrsets *cur_rrset;
1230825eb42bSJan Lentfer 	ldns_dnssec_rrs *cur_rr;
1231825eb42bSJan Lentfer 
1232825eb42bSJan Lentfer 	ldns_rr_list *siglist;
1233825eb42bSJan Lentfer 
1234825eb42bSJan Lentfer 	size_t i;
1235825eb42bSJan Lentfer 
1236b5dedccaSJan Lentfer 	int on_delegation_point = 0; /* handle partially occluded names */
1237b5dedccaSJan Lentfer 
1238825eb42bSJan Lentfer 	ldns_rr_list *pubkey_list = ldns_rr_list_new();
1239825eb42bSJan Lentfer 	for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
1240d1b2b5caSJohn Marino 		ldns_rr_list_push_rr( pubkey_list
1241d1b2b5caSJohn Marino 				    , ldns_key2rr(ldns_key_list_key(
1242d1b2b5caSJohn Marino 							key_list, i))
1243d1b2b5caSJohn Marino 				    );
1244825eb42bSJan Lentfer 	}
1245825eb42bSJan Lentfer 	/* TODO: callback to see is list should be signed */
1246825eb42bSJan Lentfer 	/* TODO: remove 'old' signatures from signature list */
1247825eb42bSJan Lentfer 	cur_node = ldns_rbtree_first(zone->names);
1248825eb42bSJan Lentfer 	while (cur_node != LDNS_RBTREE_NULL) {
1249825eb42bSJan Lentfer 		cur_name = (ldns_dnssec_name *) cur_node->data;
1250825eb42bSJan Lentfer 
1251825eb42bSJan Lentfer 		if (!cur_name->is_glue) {
1252b5dedccaSJan Lentfer 			on_delegation_point = ldns_dnssec_rrsets_contains_type(
1253b5dedccaSJan Lentfer 					cur_name->rrsets, LDNS_RR_TYPE_NS)
1254b5dedccaSJan Lentfer 				&& !ldns_dnssec_rrsets_contains_type(
1255b5dedccaSJan Lentfer 					cur_name->rrsets, LDNS_RR_TYPE_SOA);
1256825eb42bSJan Lentfer 			cur_rrset = cur_name->rrsets;
1257825eb42bSJan Lentfer 			while (cur_rrset) {
1258825eb42bSJan Lentfer 				/* reset keys to use */
1259825eb42bSJan Lentfer 				ldns_key_list_set_use(key_list, true);
1260825eb42bSJan Lentfer 
1261825eb42bSJan Lentfer 				/* walk through old sigs, remove the old,
1262825eb42bSJan Lentfer 				   and mark which keys (not) to use) */
1263825eb42bSJan Lentfer 				cur_rrset->signatures =
1264825eb42bSJan Lentfer 					ldns_dnssec_remove_signatures(cur_rrset->signatures,
1265825eb42bSJan Lentfer 											key_list,
1266825eb42bSJan Lentfer 											func,
1267825eb42bSJan Lentfer 											arg);
1268819dec71SDaniel Fojt 				if(cur_rrset->type == LDNS_RR_TYPE_DNSKEY ||
1269819dec71SDaniel Fojt 				   cur_rrset->type == LDNS_RR_TYPE_CDNSKEY ||
1270819dec71SDaniel Fojt 				   cur_rrset->type == LDNS_RR_TYPE_CDS) {
1271819dec71SDaniel Fojt 					if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK)) {
12725340022aSzrj 						ldns_key_list_filter_for_dnskey(key_list, flags);
1273819dec71SDaniel Fojt 					}
1274819dec71SDaniel Fojt 				} else {
12755340022aSzrj 					ldns_key_list_filter_for_non_dnskey(key_list, flags);
1276819dec71SDaniel Fojt 				}
1277ac996e71SJan Lentfer 
1278825eb42bSJan Lentfer 				/* TODO: just set count to zero? */
1279825eb42bSJan Lentfer 				rr_list = ldns_rr_list_new();
1280825eb42bSJan Lentfer 
1281825eb42bSJan Lentfer 				cur_rr = cur_rrset->rrs;
1282825eb42bSJan Lentfer 				while (cur_rr) {
1283825eb42bSJan Lentfer 					ldns_rr_list_push_rr(rr_list, cur_rr->rr);
1284825eb42bSJan Lentfer 					cur_rr = cur_rr->next;
1285825eb42bSJan Lentfer 				}
1286825eb42bSJan Lentfer 
1287825eb42bSJan Lentfer 				/* only sign non-delegation RRsets */
1288b5dedccaSJan Lentfer 				/* (glue should have been marked earlier,
1289b5dedccaSJan Lentfer 				 *  except on the delegation points itself) */
1290b5dedccaSJan Lentfer 				if (!on_delegation_point ||
1291b5dedccaSJan Lentfer 						ldns_rr_list_type(rr_list)
1292b5dedccaSJan Lentfer 							== LDNS_RR_TYPE_DS ||
1293b5dedccaSJan Lentfer 						ldns_rr_list_type(rr_list)
1294b5dedccaSJan Lentfer 							== LDNS_RR_TYPE_NSEC ||
1295b5dedccaSJan Lentfer 						ldns_rr_list_type(rr_list)
1296b5dedccaSJan Lentfer 							== LDNS_RR_TYPE_NSEC3) {
1297825eb42bSJan Lentfer 					siglist = ldns_sign_public(rr_list, key_list);
1298825eb42bSJan Lentfer 					for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
1299825eb42bSJan Lentfer 						if (cur_rrset->signatures) {
1300fd185f4dSJan Lentfer 							result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
1301825eb42bSJan Lentfer 											   ldns_rr_list_rr(siglist,
1302825eb42bSJan Lentfer 														    i));
1303825eb42bSJan Lentfer 						} else {
1304825eb42bSJan Lentfer 							cur_rrset->signatures = ldns_dnssec_rrs_new();
1305825eb42bSJan Lentfer 							cur_rrset->signatures->rr =
1306825eb42bSJan Lentfer 								ldns_rr_list_rr(siglist, i);
1307d1b2b5caSJohn Marino 						}
1308d1b2b5caSJohn Marino 						if (new_rrs) {
1309825eb42bSJan Lentfer 							ldns_rr_list_push_rr(new_rrs,
1310825eb42bSJan Lentfer 												 ldns_rr_list_rr(siglist,
1311825eb42bSJan Lentfer 															  i));
1312825eb42bSJan Lentfer 						}
1313825eb42bSJan Lentfer 					}
1314825eb42bSJan Lentfer 					ldns_rr_list_free(siglist);
1315825eb42bSJan Lentfer 				}
1316825eb42bSJan Lentfer 
1317825eb42bSJan Lentfer 				ldns_rr_list_free(rr_list);
1318825eb42bSJan Lentfer 
1319825eb42bSJan Lentfer 				cur_rrset = cur_rrset->next;
1320825eb42bSJan Lentfer 			}
1321825eb42bSJan Lentfer 
1322825eb42bSJan Lentfer 			/* sign the nsec */
1323ac996e71SJan Lentfer 			ldns_key_list_set_use(key_list, true);
1324825eb42bSJan Lentfer 			cur_name->nsec_signatures =
1325825eb42bSJan Lentfer 				ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
1326825eb42bSJan Lentfer 										key_list,
1327825eb42bSJan Lentfer 										func,
1328825eb42bSJan Lentfer 										arg);
13295340022aSzrj 			ldns_key_list_filter_for_non_dnskey(key_list, flags);
1330825eb42bSJan Lentfer 
1331825eb42bSJan Lentfer 			rr_list = ldns_rr_list_new();
1332825eb42bSJan Lentfer 			ldns_rr_list_push_rr(rr_list, cur_name->nsec);
1333825eb42bSJan Lentfer 			siglist = ldns_sign_public(rr_list, key_list);
1334825eb42bSJan Lentfer 
1335825eb42bSJan Lentfer 			for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
1336825eb42bSJan Lentfer 				if (cur_name->nsec_signatures) {
1337fd185f4dSJan Lentfer 					result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
1338825eb42bSJan Lentfer 									   ldns_rr_list_rr(siglist, i));
1339825eb42bSJan Lentfer 				} else {
1340825eb42bSJan Lentfer 					cur_name->nsec_signatures = ldns_dnssec_rrs_new();
1341825eb42bSJan Lentfer 					cur_name->nsec_signatures->rr =
1342825eb42bSJan Lentfer 						ldns_rr_list_rr(siglist, i);
1343d1b2b5caSJohn Marino 				}
1344d1b2b5caSJohn Marino 				if (new_rrs) {
1345825eb42bSJan Lentfer 					ldns_rr_list_push_rr(new_rrs,
1346825eb42bSJan Lentfer 								 ldns_rr_list_rr(siglist, i));
1347825eb42bSJan Lentfer 				}
1348825eb42bSJan Lentfer 			}
1349825eb42bSJan Lentfer 
1350825eb42bSJan Lentfer 			ldns_rr_list_free(siglist);
1351825eb42bSJan Lentfer 			ldns_rr_list_free(rr_list);
1352825eb42bSJan Lentfer 		}
1353825eb42bSJan Lentfer 		cur_node = ldns_rbtree_next(cur_node);
1354825eb42bSJan Lentfer 	}
1355825eb42bSJan Lentfer 
1356825eb42bSJan Lentfer 	ldns_rr_list_deep_free(pubkey_list);
1357825eb42bSJan Lentfer 	return result;
1358825eb42bSJan Lentfer }
1359825eb42bSJan Lentfer 
1360825eb42bSJan Lentfer ldns_status
1361825eb42bSJan Lentfer ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
1362825eb42bSJan Lentfer 				  ldns_rr_list *new_rrs,
1363825eb42bSJan Lentfer 				  ldns_key_list *key_list,
1364825eb42bSJan Lentfer 				  int (*func)(ldns_rr *, void *),
1365825eb42bSJan Lentfer 				  void *arg)
1366825eb42bSJan Lentfer {
1367825eb42bSJan Lentfer 	return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
1368825eb42bSJan Lentfer }
1369825eb42bSJan Lentfer 
1370*ee791febSAntonio Huete Jimenez ldns_status dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1371*ee791febSAntonio Huete Jimenez 		ldns_rr_list *new_rrs, ldns_key_list *key_list, int flags);
1372825eb42bSJan Lentfer ldns_status
1373825eb42bSJan Lentfer ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
1374825eb42bSJan Lentfer 				  ldns_rr_list *new_rrs,
1375825eb42bSJan Lentfer 				  ldns_key_list *key_list,
1376825eb42bSJan Lentfer 				  int (*func)(ldns_rr *, void *),
1377825eb42bSJan Lentfer 				  void *arg,
1378825eb42bSJan Lentfer 				  int flags)
1379825eb42bSJan Lentfer {
1380825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
1381*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets zonemd_rrset;
1382*ee791febSAntonio Huete Jimenez 	bool zonemd_added = false;
1383825eb42bSJan Lentfer 
1384825eb42bSJan Lentfer 	if (!zone || !new_rrs || !key_list) {
1385825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1386825eb42bSJan Lentfer 	}
1387*ee791febSAntonio Huete Jimenez 	if (flags & LDNS_SIGN_WITH_ZONEMD) {
1388*ee791febSAntonio Huete Jimenez 		ldns_dnssec_rrsets **rrsets_ref = &zone->soa->rrsets;
1389825eb42bSJan Lentfer 
1390*ee791febSAntonio Huete Jimenez 		while (*rrsets_ref
1391*ee791febSAntonio Huete Jimenez 		   && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD)
1392*ee791febSAntonio Huete Jimenez 			rrsets_ref = &(*rrsets_ref)->next;
1393*ee791febSAntonio Huete Jimenez 		if (!*rrsets_ref
1394*ee791febSAntonio Huete Jimenez 		||  (*rrsets_ref)->type > LDNS_RR_TYPE_ZONEMD) {
1395*ee791febSAntonio Huete Jimenez 			zonemd_rrset.rrs = NULL;
1396*ee791febSAntonio Huete Jimenez 			zonemd_rrset.type = LDNS_RR_TYPE_ZONEMD;
1397*ee791febSAntonio Huete Jimenez 			zonemd_rrset.signatures = NULL;
1398*ee791febSAntonio Huete Jimenez 			zonemd_rrset.next = *rrsets_ref;
1399*ee791febSAntonio Huete Jimenez 			*rrsets_ref = &zonemd_rrset;
1400*ee791febSAntonio Huete Jimenez 			zonemd_added = true;
1401*ee791febSAntonio Huete Jimenez 		}
1402*ee791febSAntonio Huete Jimenez 	}
1403825eb42bSJan Lentfer 	/* zone is already sorted */
1404fd185f4dSJan Lentfer 	result = ldns_dnssec_zone_mark_glue(zone);
1405fd185f4dSJan Lentfer 	if (result != LDNS_STATUS_OK) {
1406fd185f4dSJan Lentfer 		return result;
1407fd185f4dSJan Lentfer 	}
1408825eb42bSJan Lentfer 	/* check whether we need to add nsecs */
1409*ee791febSAntonio Huete Jimenez 	if ((flags & LDNS_SIGN_NO_KEYS_NO_NSECS)
1410*ee791febSAntonio Huete Jimenez 	&&  ldns_key_list_key_count(key_list) < 1)
1411*ee791febSAntonio Huete Jimenez 		; /* pass */
1412*ee791febSAntonio Huete Jimenez 
1413*ee791febSAntonio Huete Jimenez 	else if (zone->names
1414*ee791febSAntonio Huete Jimenez 	     && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
1415*ee791febSAntonio Huete Jimenez 
1416825eb42bSJan Lentfer 		result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
1417825eb42bSJan Lentfer 		if (result != LDNS_STATUS_OK) {
1418825eb42bSJan Lentfer 			return result;
1419825eb42bSJan Lentfer 		}
1420825eb42bSJan Lentfer 	}
1421825eb42bSJan Lentfer 	result = ldns_dnssec_zone_create_rrsigs_flg(zone,
1422825eb42bSJan Lentfer 					new_rrs,
1423825eb42bSJan Lentfer 					key_list,
1424825eb42bSJan Lentfer 					func,
1425825eb42bSJan Lentfer 					arg,
1426825eb42bSJan Lentfer 					flags);
1427825eb42bSJan Lentfer 
1428*ee791febSAntonio Huete Jimenez 	if (zonemd_added) {
1429*ee791febSAntonio Huete Jimenez 		ldns_dnssec_rrsets **rrsets_ref
1430*ee791febSAntonio Huete Jimenez 		    = &zone->soa->rrsets;
1431*ee791febSAntonio Huete Jimenez 
1432*ee791febSAntonio Huete Jimenez 		while (*rrsets_ref
1433*ee791febSAntonio Huete Jimenez 		   && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD)
1434*ee791febSAntonio Huete Jimenez 			rrsets_ref = &(*rrsets_ref)->next;
1435*ee791febSAntonio Huete Jimenez 		*rrsets_ref = zonemd_rrset.next;
1436*ee791febSAntonio Huete Jimenez 	}
1437*ee791febSAntonio Huete Jimenez 	return flags & LDNS_SIGN_WITH_ZONEMD
1438*ee791febSAntonio Huete Jimenez 	     ? dnssec_zone_equip_zonemd(zone, new_rrs, key_list, flags)
1439*ee791febSAntonio Huete Jimenez 	     : result;
1440825eb42bSJan Lentfer }
1441825eb42bSJan Lentfer 
1442825eb42bSJan Lentfer ldns_status
1443825eb42bSJan Lentfer ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
1444825eb42bSJan Lentfer 					   ldns_rr_list *new_rrs,
1445825eb42bSJan Lentfer 					   ldns_key_list *key_list,
1446825eb42bSJan Lentfer 					   int (*func)(ldns_rr *, void *),
1447825eb42bSJan Lentfer 					   void *arg,
1448825eb42bSJan Lentfer 					   uint8_t algorithm,
1449825eb42bSJan Lentfer 					   uint8_t flags,
1450825eb42bSJan Lentfer 					   uint16_t iterations,
1451825eb42bSJan Lentfer 					   uint8_t salt_length,
1452825eb42bSJan Lentfer 					   uint8_t *salt)
1453825eb42bSJan Lentfer {
1454b5dedccaSJan Lentfer 	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
1455b5dedccaSJan Lentfer 		func, arg, algorithm, flags, iterations, salt_length, salt, 0,
1456b5dedccaSJan Lentfer 	       	NULL);
1457825eb42bSJan Lentfer }
1458825eb42bSJan Lentfer 
1459825eb42bSJan Lentfer ldns_status
1460b5dedccaSJan Lentfer ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
1461825eb42bSJan Lentfer 		ldns_rr_list *new_rrs,
1462825eb42bSJan Lentfer 		ldns_key_list *key_list,
1463825eb42bSJan Lentfer 		int (*func)(ldns_rr *, void *),
1464825eb42bSJan Lentfer 		void *arg,
1465825eb42bSJan Lentfer 		uint8_t algorithm,
1466825eb42bSJan Lentfer 		uint8_t flags,
1467825eb42bSJan Lentfer 		uint16_t iterations,
1468825eb42bSJan Lentfer 		uint8_t salt_length,
1469825eb42bSJan Lentfer 		uint8_t *salt,
1470b5dedccaSJan Lentfer 		int signflags,
1471b5dedccaSJan Lentfer 		ldns_rbtree_t **map)
1472825eb42bSJan Lentfer {
1473b5dedccaSJan Lentfer 	ldns_rr *nsec3, *nsec3param;
1474825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
1475*ee791febSAntonio Huete Jimenez 	bool zonemd_added = false;
1476*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets zonemd_rrset;
1477825eb42bSJan Lentfer 
1478825eb42bSJan Lentfer 	/* zone is already sorted */
1479fd185f4dSJan Lentfer 	result = ldns_dnssec_zone_mark_glue(zone);
1480fd185f4dSJan Lentfer 	if (result != LDNS_STATUS_OK) {
1481fd185f4dSJan Lentfer 		return result;
1482fd185f4dSJan Lentfer 	}
1483825eb42bSJan Lentfer 
1484825eb42bSJan Lentfer 	/* TODO if there are already nsec3s presents and their
1485825eb42bSJan Lentfer 	 * parameters are the same as these, we don't have to recreate
1486825eb42bSJan Lentfer 	 */
1487825eb42bSJan Lentfer 	if (zone->names) {
1488825eb42bSJan Lentfer 		/* add empty nonterminals */
1489fd185f4dSJan Lentfer 		result = ldns_dnssec_zone_add_empty_nonterminals(zone);
1490fd185f4dSJan Lentfer 		if (result != LDNS_STATUS_OK) {
1491fd185f4dSJan Lentfer 			return result;
1492fd185f4dSJan Lentfer 		}
1493825eb42bSJan Lentfer 
1494825eb42bSJan Lentfer 		nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
1495*ee791febSAntonio Huete Jimenez 
1496*ee791febSAntonio Huete Jimenez 		/* check whether we need to add nsecs */
1497*ee791febSAntonio Huete Jimenez 		if ((signflags & LDNS_SIGN_NO_KEYS_NO_NSECS)
1498*ee791febSAntonio Huete Jimenez 		&&  ldns_key_list_key_count(key_list) < 1)
1499*ee791febSAntonio Huete Jimenez 			; /* pass */
1500*ee791febSAntonio Huete Jimenez 
1501*ee791febSAntonio Huete Jimenez 		else if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
1502825eb42bSJan Lentfer 			/* no need to recreate */
1503825eb42bSJan Lentfer 		} else {
1504825eb42bSJan Lentfer 			if (!ldns_dnssec_zone_find_rrset(zone,
1505825eb42bSJan Lentfer 									   zone->soa->name,
1506b5dedccaSJan Lentfer 									   LDNS_RR_TYPE_NSEC3PARAM)) {
1507b5dedccaSJan Lentfer 				/* create and add the nsec3param rr */
1508b5dedccaSJan Lentfer 				nsec3param =
1509b5dedccaSJan Lentfer 					ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM);
1510b5dedccaSJan Lentfer 				ldns_rr_set_owner(nsec3param,
1511825eb42bSJan Lentfer 							   ldns_rdf_clone(zone->soa->name));
1512b5dedccaSJan Lentfer 				ldns_nsec3_add_param_rdfs(nsec3param,
1513825eb42bSJan Lentfer 									 algorithm,
1514825eb42bSJan Lentfer 									 flags,
1515825eb42bSJan Lentfer 									 iterations,
1516825eb42bSJan Lentfer 									 salt_length,
1517825eb42bSJan Lentfer 									 salt);
1518825eb42bSJan Lentfer 				/* always set bit 7 of the flags to zero, according to
1519d1b2b5caSJohn Marino 				 * rfc5155 section 11. The bits are counted from right to left,
1520d1b2b5caSJohn Marino 				 * so bit 7 in rfc5155 is bit 0 in ldns */
1521d1b2b5caSJohn Marino 				ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0);
1522b5dedccaSJan Lentfer 				result = ldns_dnssec_zone_add_rr(zone, nsec3param);
1523fd185f4dSJan Lentfer 				if (result != LDNS_STATUS_OK) {
1524fd185f4dSJan Lentfer 					return result;
1525fd185f4dSJan Lentfer 				}
1526b5dedccaSJan Lentfer 				ldns_rr_list_push_rr(new_rrs, nsec3param);
1527825eb42bSJan Lentfer 			}
1528*ee791febSAntonio Huete Jimenez 			if (signflags & LDNS_SIGN_WITH_ZONEMD) {
1529*ee791febSAntonio Huete Jimenez 				ldns_dnssec_rrsets **rrsets_ref
1530*ee791febSAntonio Huete Jimenez 				    = &zone->soa->rrsets;
1531*ee791febSAntonio Huete Jimenez 
1532*ee791febSAntonio Huete Jimenez 				while (*rrsets_ref
1533*ee791febSAntonio Huete Jimenez 				   && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD)
1534*ee791febSAntonio Huete Jimenez 					rrsets_ref = &(*rrsets_ref)->next;
1535*ee791febSAntonio Huete Jimenez 				if (!*rrsets_ref
1536*ee791febSAntonio Huete Jimenez 				||  (*rrsets_ref)->type > LDNS_RR_TYPE_ZONEMD) {
1537*ee791febSAntonio Huete Jimenez 					zonemd_rrset.rrs = NULL;
1538*ee791febSAntonio Huete Jimenez 					zonemd_rrset.type = LDNS_RR_TYPE_ZONEMD;
1539*ee791febSAntonio Huete Jimenez 					zonemd_rrset.signatures = NULL;
1540*ee791febSAntonio Huete Jimenez 					zonemd_rrset.next = *rrsets_ref;
1541*ee791febSAntonio Huete Jimenez 					*rrsets_ref = &zonemd_rrset;
1542*ee791febSAntonio Huete Jimenez 					zonemd_added = true;
1543*ee791febSAntonio Huete Jimenez 				}
1544*ee791febSAntonio Huete Jimenez 			}
1545b5dedccaSJan Lentfer 			result = ldns_dnssec_zone_create_nsec3s_mkmap(zone,
1546825eb42bSJan Lentfer 											new_rrs,
1547825eb42bSJan Lentfer 											algorithm,
1548825eb42bSJan Lentfer 											flags,
1549825eb42bSJan Lentfer 											iterations,
1550825eb42bSJan Lentfer 											salt_length,
1551b5dedccaSJan Lentfer 											salt,
1552b5dedccaSJan Lentfer 											map);
1553*ee791febSAntonio Huete Jimenez 			if (zonemd_added) {
1554*ee791febSAntonio Huete Jimenez 				ldns_dnssec_rrsets **rrsets_ref
1555*ee791febSAntonio Huete Jimenez 				    = &zone->soa->rrsets;
1556*ee791febSAntonio Huete Jimenez 
1557*ee791febSAntonio Huete Jimenez 				while (*rrsets_ref
1558*ee791febSAntonio Huete Jimenez 				   && (*rrsets_ref)->type < LDNS_RR_TYPE_ZONEMD)
1559*ee791febSAntonio Huete Jimenez 					rrsets_ref = &(*rrsets_ref)->next;
1560*ee791febSAntonio Huete Jimenez 				*rrsets_ref = zonemd_rrset.next;
1561*ee791febSAntonio Huete Jimenez 			}
1562825eb42bSJan Lentfer 			if (result != LDNS_STATUS_OK) {
1563825eb42bSJan Lentfer 				return result;
1564825eb42bSJan Lentfer 			}
1565825eb42bSJan Lentfer 		}
1566825eb42bSJan Lentfer 
1567825eb42bSJan Lentfer 		result = ldns_dnssec_zone_create_rrsigs_flg(zone,
1568825eb42bSJan Lentfer 						new_rrs,
1569825eb42bSJan Lentfer 						key_list,
1570825eb42bSJan Lentfer 						func,
1571825eb42bSJan Lentfer 						arg,
1572825eb42bSJan Lentfer 						signflags);
1573825eb42bSJan Lentfer 	}
1574*ee791febSAntonio Huete Jimenez 	if (result || !zone->names)
1575825eb42bSJan Lentfer 		return result;
1576*ee791febSAntonio Huete Jimenez 
1577*ee791febSAntonio Huete Jimenez 	return signflags & LDNS_SIGN_WITH_ZONEMD
1578*ee791febSAntonio Huete Jimenez 	     ? dnssec_zone_equip_zonemd(zone, new_rrs, key_list, signflags)
1579*ee791febSAntonio Huete Jimenez 	     : result;
1580825eb42bSJan Lentfer }
1581825eb42bSJan Lentfer 
1582b5dedccaSJan Lentfer ldns_status
1583b5dedccaSJan Lentfer ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
1584b5dedccaSJan Lentfer 		ldns_rr_list *new_rrs,
1585b5dedccaSJan Lentfer 		ldns_key_list *key_list,
1586b5dedccaSJan Lentfer 		int (*func)(ldns_rr *, void *),
1587b5dedccaSJan Lentfer 		void *arg,
1588b5dedccaSJan Lentfer 		uint8_t algorithm,
1589b5dedccaSJan Lentfer 		uint8_t flags,
1590b5dedccaSJan Lentfer 		uint16_t iterations,
1591b5dedccaSJan Lentfer 		uint8_t salt_length,
1592b5dedccaSJan Lentfer 		uint8_t *salt,
1593b5dedccaSJan Lentfer 		int signflags)
1594b5dedccaSJan Lentfer {
1595b5dedccaSJan Lentfer 	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
1596b5dedccaSJan Lentfer 		func, arg, algorithm, flags, iterations, salt_length, salt,
1597b5dedccaSJan Lentfer 		signflags, NULL);
1598b5dedccaSJan Lentfer }
1599825eb42bSJan Lentfer 
1600825eb42bSJan Lentfer ldns_zone *
1601825eb42bSJan Lentfer ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
1602825eb42bSJan Lentfer {
1603825eb42bSJan Lentfer 	ldns_dnssec_zone *dnssec_zone;
1604825eb42bSJan Lentfer 	ldns_zone *signed_zone;
1605825eb42bSJan Lentfer 	ldns_rr_list *new_rrs;
1606825eb42bSJan Lentfer 	size_t i;
1607825eb42bSJan Lentfer 
1608825eb42bSJan Lentfer 	signed_zone = ldns_zone_new();
1609825eb42bSJan Lentfer 	dnssec_zone = ldns_dnssec_zone_new();
1610825eb42bSJan Lentfer 
1611825eb42bSJan Lentfer 	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
1612ac996e71SJan Lentfer 	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
1613825eb42bSJan Lentfer 
1614825eb42bSJan Lentfer 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
1615825eb42bSJan Lentfer 		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
1616825eb42bSJan Lentfer 								 ldns_rr_list_rr(ldns_zone_rrs(zone),
1617825eb42bSJan Lentfer 											  i));
1618825eb42bSJan Lentfer 		ldns_zone_push_rr(signed_zone,
1619825eb42bSJan Lentfer 					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
1620825eb42bSJan Lentfer 											   i)));
1621825eb42bSJan Lentfer 	}
1622825eb42bSJan Lentfer 
1623825eb42bSJan Lentfer 	new_rrs = ldns_rr_list_new();
1624825eb42bSJan Lentfer 	(void) ldns_dnssec_zone_sign(dnssec_zone,
1625825eb42bSJan Lentfer 						    new_rrs,
1626825eb42bSJan Lentfer 						    key_list,
1627825eb42bSJan Lentfer 						    ldns_dnssec_default_replace_signatures,
1628825eb42bSJan Lentfer 						    NULL);
1629825eb42bSJan Lentfer 
1630825eb42bSJan Lentfer     	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
1631825eb42bSJan Lentfer 		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
1632825eb42bSJan Lentfer 						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
1633825eb42bSJan Lentfer 	}
1634825eb42bSJan Lentfer 
1635825eb42bSJan Lentfer 	ldns_rr_list_deep_free(new_rrs);
1636825eb42bSJan Lentfer 	ldns_dnssec_zone_free(dnssec_zone);
1637825eb42bSJan Lentfer 
1638825eb42bSJan Lentfer 	return signed_zone;
1639825eb42bSJan Lentfer }
1640825eb42bSJan Lentfer 
1641825eb42bSJan Lentfer ldns_zone *
1642825eb42bSJan Lentfer 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)
1643825eb42bSJan Lentfer {
1644825eb42bSJan Lentfer 	ldns_dnssec_zone *dnssec_zone;
1645825eb42bSJan Lentfer 	ldns_zone *signed_zone;
1646825eb42bSJan Lentfer 	ldns_rr_list *new_rrs;
1647825eb42bSJan Lentfer 	size_t i;
1648825eb42bSJan Lentfer 
1649825eb42bSJan Lentfer 	signed_zone = ldns_zone_new();
1650825eb42bSJan Lentfer 	dnssec_zone = ldns_dnssec_zone_new();
1651825eb42bSJan Lentfer 
1652825eb42bSJan Lentfer 	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
1653ac996e71SJan Lentfer 	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
1654825eb42bSJan Lentfer 
1655825eb42bSJan Lentfer 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
1656825eb42bSJan Lentfer 		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
1657825eb42bSJan Lentfer 								 ldns_rr_list_rr(ldns_zone_rrs(zone),
1658825eb42bSJan Lentfer 											  i));
1659825eb42bSJan Lentfer 		ldns_zone_push_rr(signed_zone,
1660825eb42bSJan Lentfer 					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
1661825eb42bSJan Lentfer 											   i)));
1662825eb42bSJan Lentfer 	}
1663825eb42bSJan Lentfer 
1664825eb42bSJan Lentfer 	new_rrs = ldns_rr_list_new();
1665825eb42bSJan Lentfer 	(void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
1666825eb42bSJan Lentfer 								new_rrs,
1667825eb42bSJan Lentfer 								key_list,
1668825eb42bSJan Lentfer 								ldns_dnssec_default_replace_signatures,
1669825eb42bSJan Lentfer 								NULL,
1670825eb42bSJan Lentfer 								algorithm,
1671825eb42bSJan Lentfer 								flags,
1672825eb42bSJan Lentfer 								iterations,
1673825eb42bSJan Lentfer 								salt_length,
1674825eb42bSJan Lentfer 								salt);
1675825eb42bSJan Lentfer 
1676825eb42bSJan Lentfer     	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
1677825eb42bSJan Lentfer 		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
1678825eb42bSJan Lentfer 						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
1679825eb42bSJan Lentfer 	}
1680825eb42bSJan Lentfer 
1681825eb42bSJan Lentfer 	ldns_rr_list_deep_free(new_rrs);
1682825eb42bSJan Lentfer 	ldns_dnssec_zone_free(dnssec_zone);
1683825eb42bSJan Lentfer 
1684825eb42bSJan Lentfer 	return signed_zone;
1685825eb42bSJan Lentfer }
1686825eb42bSJan Lentfer #endif /* HAVE_SSL */
1687825eb42bSJan Lentfer 
1688b5dedccaSJan Lentfer 
1689