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