Commit | Line | Data |
---|---|---|
825eb42b JL |
1 | #include <ldns/config.h> |
2 | ||
3 | #include <ldns/ldns.h> | |
4 | ||
5 | #include <ldns/dnssec.h> | |
6 | #include <ldns/dnssec_sign.h> | |
7 | ||
8 | #include <strings.h> | |
9 | #include <time.h> | |
10 | ||
11 | #ifdef HAVE_SSL | |
12 | /* this entire file is rather useless when you don't have | |
13 | * crypto... | |
14 | */ | |
15 | #include <openssl/ssl.h> | |
16 | #include <openssl/evp.h> | |
17 | #include <openssl/rand.h> | |
18 | #include <openssl/err.h> | |
19 | #include <openssl/md5.h> | |
20 | #endif /* HAVE_SSL */ | |
21 | ||
22 | ldns_rr * | |
23 | ldns_create_empty_rrsig(ldns_rr_list *rrset, | |
24 | ldns_key *current_key) | |
25 | { | |
26 | uint32_t orig_ttl; | |
27 | ldns_rr_class orig_class; | |
28 | time_t now; | |
29 | ldns_rr *current_sig; | |
30 | uint8_t label_count; | |
d1b2b5ca | 31 | ldns_rdf *signame; |
825eb42b JL |
32 | |
33 | label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset, | |
34 | 0))); | |
ac996e71 JL |
35 | /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */ |
36 | if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) | |
37 | label_count --; | |
38 | ||
825eb42b | 39 | current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG); |
ac996e71 | 40 | |
825eb42b JL |
41 | /* set the type on the new signature */ |
42 | orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)); | |
43 | orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0)); | |
44 | ||
45 | ldns_rr_set_ttl(current_sig, orig_ttl); | |
46 | ldns_rr_set_class(current_sig, orig_class); | |
ac996e71 | 47 | ldns_rr_set_owner(current_sig, |
825eb42b JL |
48 | ldns_rdf_clone( |
49 | ldns_rr_owner( | |
50 | ldns_rr_list_rr(rrset, | |
51 | 0)))); | |
52 | ||
53 | /* fill in what we know of the signature */ | |
ac996e71 | 54 | |
825eb42b JL |
55 | /* set the orig_ttl */ |
56 | (void)ldns_rr_rrsig_set_origttl( | |
ac996e71 | 57 | current_sig, |
825eb42b JL |
58 | ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, |
59 | orig_ttl)); | |
60 | /* the signers name */ | |
d1b2b5ca JM |
61 | signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key)); |
62 | ldns_dname2canonical(signame); | |
825eb42b | 63 | (void)ldns_rr_rrsig_set_signame( |
ac996e71 | 64 | current_sig, |
d1b2b5ca | 65 | signame); |
825eb42b JL |
66 | /* label count - get it from the first rr in the rr_list */ |
67 | (void)ldns_rr_rrsig_set_labels( | |
ac996e71 | 68 | current_sig, |
825eb42b JL |
69 | ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, |
70 | label_count)); | |
71 | /* inception, expiration */ | |
72 | now = time(NULL); | |
73 | if (ldns_key_inception(current_key) != 0) { | |
74 | (void)ldns_rr_rrsig_set_inception( | |
75 | current_sig, | |
76 | ldns_native2rdf_int32( | |
ac996e71 | 77 | LDNS_RDF_TYPE_TIME, |
825eb42b JL |
78 | ldns_key_inception(current_key))); |
79 | } else { | |
80 | (void)ldns_rr_rrsig_set_inception( | |
81 | current_sig, | |
82 | ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now)); | |
83 | } | |
84 | if (ldns_key_expiration(current_key) != 0) { | |
85 | (void)ldns_rr_rrsig_set_expiration( | |
86 | current_sig, | |
87 | ldns_native2rdf_int32( | |
ac996e71 | 88 | LDNS_RDF_TYPE_TIME, |
825eb42b JL |
89 | ldns_key_expiration(current_key))); |
90 | } else { | |
91 | (void)ldns_rr_rrsig_set_expiration( | |
92 | current_sig, | |
93 | ldns_native2rdf_int32( | |
ac996e71 | 94 | LDNS_RDF_TYPE_TIME, |
825eb42b JL |
95 | now + LDNS_DEFAULT_EXP_TIME)); |
96 | } | |
97 | ||
98 | (void)ldns_rr_rrsig_set_keytag( | |
99 | current_sig, | |
ac996e71 | 100 | ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, |
825eb42b JL |
101 | ldns_key_keytag(current_key))); |
102 | ||
103 | (void)ldns_rr_rrsig_set_algorithm( | |
104 | current_sig, | |
105 | ldns_native2rdf_int8( | |
ac996e71 | 106 | LDNS_RDF_TYPE_ALG, |
825eb42b JL |
107 | ldns_key_algorithm(current_key))); |
108 | ||
109 | (void)ldns_rr_rrsig_set_typecovered( | |
110 | current_sig, | |
111 | ldns_native2rdf_int16( | |
112 | LDNS_RDF_TYPE_TYPE, | |
113 | ldns_rr_get_type(ldns_rr_list_rr(rrset, | |
114 | 0)))); | |
115 | return current_sig; | |
116 | } | |
117 | ||
118 | #ifdef HAVE_SSL | |
119 | ldns_rdf * | |
120 | ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key) | |
121 | { | |
122 | ldns_rdf *b64rdf = NULL; | |
123 | ||
124 | switch(ldns_key_algorithm(current_key)) { | |
125 | case LDNS_SIGN_DSA: | |
fd185f4d | 126 | case LDNS_SIGN_DSA_NSEC3: |
825eb42b JL |
127 | b64rdf = ldns_sign_public_evp( |
128 | sign_buf, | |
129 | ldns_key_evp_key(current_key), | |
130 | EVP_dss1()); | |
131 | break; | |
132 | case LDNS_SIGN_RSASHA1: | |
133 | case LDNS_SIGN_RSASHA1_NSEC3: | |
134 | b64rdf = ldns_sign_public_evp( | |
135 | sign_buf, | |
136 | ldns_key_evp_key(current_key), | |
137 | EVP_sha1()); | |
138 | break; | |
139 | #ifdef USE_SHA2 | |
140 | case LDNS_SIGN_RSASHA256: | |
141 | b64rdf = ldns_sign_public_evp( | |
142 | sign_buf, | |
143 | ldns_key_evp_key(current_key), | |
144 | EVP_sha256()); | |
145 | break; | |
146 | case LDNS_SIGN_RSASHA512: | |
147 | b64rdf = ldns_sign_public_evp( | |
148 | sign_buf, | |
149 | ldns_key_evp_key(current_key), | |
150 | EVP_sha512()); | |
151 | break; | |
152 | #endif /* USE_SHA2 */ | |
153 | #ifdef USE_GOST | |
ac996e71 | 154 | case LDNS_SIGN_ECC_GOST: |
825eb42b JL |
155 | b64rdf = ldns_sign_public_evp( |
156 | sign_buf, | |
157 | ldns_key_evp_key(current_key), | |
158 | EVP_get_digestbyname("md_gost94")); | |
159 | break; | |
160 | #endif /* USE_GOST */ | |
ac996e71 JL |
161 | #ifdef USE_ECDSA |
162 | case LDNS_SIGN_ECDSAP256SHA256: | |
163 | b64rdf = ldns_sign_public_evp( | |
164 | sign_buf, | |
165 | ldns_key_evp_key(current_key), | |
166 | EVP_sha256()); | |
167 | break; | |
168 | case LDNS_SIGN_ECDSAP384SHA384: | |
169 | b64rdf = ldns_sign_public_evp( | |
170 | sign_buf, | |
171 | ldns_key_evp_key(current_key), | |
172 | EVP_sha384()); | |
173 | break; | |
174 | #endif | |
825eb42b JL |
175 | case LDNS_SIGN_RSAMD5: |
176 | b64rdf = ldns_sign_public_evp( | |
177 | sign_buf, | |
178 | ldns_key_evp_key(current_key), | |
179 | EVP_md5()); | |
180 | break; | |
181 | default: | |
182 | /* do _you_ know this alg? */ | |
183 | printf("unknown algorithm, "); | |
184 | printf("is the one used available on this system?\n"); | |
185 | break; | |
186 | } | |
ac996e71 | 187 | |
825eb42b JL |
188 | return b64rdf; |
189 | } | |
190 | ||
191 | /** | |
192 | * use this function to sign with a public/private key alg | |
193 | * return the created signatures | |
194 | */ | |
195 | ldns_rr_list * | |
196 | ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) | |
197 | { | |
198 | ldns_rr_list *signatures; | |
199 | ldns_rr_list *rrset_clone; | |
200 | ldns_rr *current_sig; | |
201 | ldns_rdf *b64rdf; | |
202 | ldns_key *current_key; | |
203 | size_t key_count; | |
204 | uint16_t i; | |
205 | ldns_buffer *sign_buf; | |
206 | ldns_rdf *new_owner; | |
207 | ||
208 | if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) { | |
209 | return NULL; | |
210 | } | |
ac996e71 | 211 | |
825eb42b JL |
212 | new_owner = NULL; |
213 | ||
825eb42b JL |
214 | signatures = ldns_rr_list_new(); |
215 | ||
216 | /* prepare a signature and add all the know data | |
217 | * prepare the rrset. Sign this together. */ | |
218 | rrset_clone = ldns_rr_list_clone(rrset); | |
219 | if (!rrset_clone) { | |
220 | return NULL; | |
221 | } | |
222 | ||
223 | /* make it canonical */ | |
224 | for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { | |
225 | ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), | |
226 | ldns_rr_ttl(ldns_rr_list_rr(rrset, 0))); | |
227 | ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); | |
228 | } | |
229 | /* sort */ | |
230 | ldns_rr_list_sort(rrset_clone); | |
ac996e71 | 231 | |
825eb42b JL |
232 | for (key_count = 0; |
233 | key_count < ldns_key_list_key_count(keys); | |
234 | key_count++) { | |
235 | if (!ldns_key_use(ldns_key_list_key(keys, key_count))) { | |
236 | continue; | |
237 | } | |
238 | sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); | |
239 | if (!sign_buf) { | |
240 | ldns_rr_list_free(rrset_clone); | |
241 | ldns_rr_list_free(signatures); | |
242 | ldns_rdf_free(new_owner); | |
243 | return NULL; | |
244 | } | |
245 | b64rdf = NULL; | |
246 | ||
247 | current_key = ldns_key_list_key(keys, key_count); | |
248 | /* sign all RRs with keys that have ZSKbit, !SEPbit. | |
249 | sign DNSKEY RRs with keys that have ZSKbit&SEPbit */ | |
ac996e71 | 250 | if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) { |
825eb42b JL |
251 | current_sig = ldns_create_empty_rrsig(rrset_clone, |
252 | current_key); | |
253 | ||
254 | /* right now, we have: a key, a semi-sig and an rrset. For | |
255 | * which we can create the sig and base64 encode that and | |
256 | * add that to the signature */ | |
257 | ||
258 | if (ldns_rrsig2buffer_wire(sign_buf, current_sig) | |
259 | != LDNS_STATUS_OK) { | |
260 | ldns_buffer_free(sign_buf); | |
261 | /* ERROR */ | |
262 | ldns_rr_list_deep_free(rrset_clone); | |
d1b2b5ca JM |
263 | ldns_rr_free(current_sig); |
264 | ldns_rr_list_deep_free(signatures); | |
825eb42b JL |
265 | return NULL; |
266 | } | |
267 | ||
268 | /* add the rrset in sign_buf */ | |
269 | if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone) | |
270 | != LDNS_STATUS_OK) { | |
271 | ldns_buffer_free(sign_buf); | |
272 | ldns_rr_list_deep_free(rrset_clone); | |
d1b2b5ca JM |
273 | ldns_rr_free(current_sig); |
274 | ldns_rr_list_deep_free(signatures); | |
825eb42b JL |
275 | return NULL; |
276 | } | |
277 | ||
278 | b64rdf = ldns_sign_public_buffer(sign_buf, current_key); | |
279 | ||
280 | if (!b64rdf) { | |
281 | /* signing went wrong */ | |
282 | ldns_rr_list_deep_free(rrset_clone); | |
d1b2b5ca JM |
283 | ldns_rr_free(current_sig); |
284 | ldns_rr_list_deep_free(signatures); | |
825eb42b JL |
285 | return NULL; |
286 | } | |
287 | ||
288 | ldns_rr_rrsig_set_sig(current_sig, b64rdf); | |
289 | ||
290 | /* push the signature to the signatures list */ | |
291 | ldns_rr_list_push_rr(signatures, current_sig); | |
292 | } | |
293 | ldns_buffer_free(sign_buf); /* restart for the next key */ | |
294 | } | |
295 | ldns_rr_list_deep_free(rrset_clone); | |
296 | ||
297 | return signatures; | |
298 | } | |
299 | ||
300 | /** | |
301 | * Sign data with DSA | |
302 | * | |
303 | * \param[in] to_sign The ldns_buffer containing raw data that is | |
304 | * to be signed | |
305 | * \param[in] key The DSA key structure to sign with | |
306 | * \return ldns_rdf for the RRSIG ldns_rr | |
307 | */ | |
308 | ldns_rdf * | |
309 | ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) | |
310 | { | |
311 | unsigned char *sha1_hash; | |
312 | ldns_rdf *sigdata_rdf; | |
313 | ldns_buffer *b64sig; | |
314 | ||
315 | DSA_SIG *sig; | |
316 | uint8_t *data; | |
317 | size_t pad; | |
318 | ||
319 | b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); | |
320 | if (!b64sig) { | |
321 | return NULL; | |
322 | } | |
ac996e71 | 323 | |
825eb42b JL |
324 | sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), |
325 | ldns_buffer_position(to_sign), NULL); | |
326 | if (!sha1_hash) { | |
327 | ldns_buffer_free(b64sig); | |
328 | return NULL; | |
329 | } | |
330 | ||
825eb42b | 331 | sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key); |
fd185f4d JL |
332 | if(!sig) { |
333 | ldns_buffer_free(b64sig); | |
334 | return NULL; | |
335 | } | |
825eb42b JL |
336 | |
337 | data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH); | |
fd185f4d JL |
338 | if(!data) { |
339 | ldns_buffer_free(b64sig); | |
340 | DSA_SIG_free(sig); | |
341 | return NULL; | |
342 | } | |
825eb42b JL |
343 | |
344 | data[0] = 1; | |
345 | pad = 20 - (size_t) BN_num_bytes(sig->r); | |
346 | if (pad > 0) { | |
347 | memset(data + 1, 0, pad); | |
348 | } | |
349 | BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad); | |
350 | ||
351 | pad = 20 - (size_t) BN_num_bytes(sig->s); | |
352 | if (pad > 0) { | |
353 | memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad); | |
354 | } | |
355 | BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad)); | |
356 | ||
357 | sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, | |
358 | 1 + 2 * SHA_DIGEST_LENGTH, | |
359 | data); | |
360 | ||
361 | ldns_buffer_free(b64sig); | |
362 | LDNS_FREE(data); | |
fd185f4d | 363 | DSA_SIG_free(sig); |
825eb42b JL |
364 | |
365 | return sigdata_rdf; | |
366 | } | |
367 | ||
ac996e71 | 368 | #ifdef USE_ECDSA |
fd185f4d | 369 | #ifndef S_SPLINT_S |
ac996e71 JL |
370 | static int |
371 | ldns_pkey_is_ecdsa(EVP_PKEY* pkey) | |
372 | { | |
373 | EC_KEY* ec; | |
374 | const EC_GROUP* g; | |
375 | if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) | |
376 | return 0; | |
377 | ec = EVP_PKEY_get1_EC_KEY(pkey); | |
378 | g = EC_KEY_get0_group(ec); | |
379 | if(!g) { | |
380 | EC_KEY_free(ec); | |
381 | return 0; | |
382 | } | |
383 | if(EC_GROUP_get_curve_name(g) == NID_secp224r1 || | |
384 | EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 || | |
385 | EC_GROUP_get_curve_name(g) == NID_secp384r1) { | |
386 | EC_KEY_free(ec); | |
387 | return 1; | |
388 | } | |
389 | /* downref the eckey, the original is still inside the pkey */ | |
390 | EC_KEY_free(ec); | |
391 | return 0; | |
392 | } | |
fd185f4d | 393 | #endif /* splint */ |
ac996e71 JL |
394 | #endif /* USE_ECDSA */ |
395 | ||
825eb42b JL |
396 | ldns_rdf * |
397 | ldns_sign_public_evp(ldns_buffer *to_sign, | |
398 | EVP_PKEY *key, | |
399 | const EVP_MD *digest_type) | |
400 | { | |
401 | unsigned int siglen; | |
402 | ldns_rdf *sigdata_rdf; | |
403 | ldns_buffer *b64sig; | |
404 | EVP_MD_CTX ctx; | |
405 | const EVP_MD *md_type; | |
406 | int r; | |
407 | ||
408 | siglen = 0; | |
409 | b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); | |
410 | if (!b64sig) { | |
411 | return NULL; | |
412 | } | |
413 | ||
414 | /* initializes a signing context */ | |
415 | md_type = digest_type; | |
416 | if(!md_type) { | |
417 | /* unknown message difest */ | |
418 | ldns_buffer_free(b64sig); | |
419 | return NULL; | |
420 | } | |
421 | ||
422 | EVP_MD_CTX_init(&ctx); | |
423 | r = EVP_SignInit(&ctx, md_type); | |
424 | if(r == 1) { | |
425 | r = EVP_SignUpdate(&ctx, (unsigned char*) | |
ac996e71 | 426 | ldns_buffer_begin(to_sign), |
825eb42b JL |
427 | ldns_buffer_position(to_sign)); |
428 | } else { | |
429 | ldns_buffer_free(b64sig); | |
430 | return NULL; | |
431 | } | |
432 | if(r == 1) { | |
433 | r = EVP_SignFinal(&ctx, (unsigned char*) | |
434 | ldns_buffer_begin(b64sig), &siglen, key); | |
435 | } else { | |
436 | ldns_buffer_free(b64sig); | |
437 | return NULL; | |
438 | } | |
439 | if(r != 1) { | |
440 | ldns_buffer_free(b64sig); | |
441 | return NULL; | |
442 | } | |
443 | ||
444 | /* unfortunately, OpenSSL output is differenct from DNS DSA format */ | |
fd185f4d | 445 | #ifndef S_SPLINT_S |
825eb42b JL |
446 | if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { |
447 | sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen); | |
ac996e71 JL |
448 | #ifdef USE_ECDSA |
449 | } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC && | |
450 | ldns_pkey_is_ecdsa(key)) { | |
451 | sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen); | |
452 | #endif | |
825eb42b JL |
453 | } else { |
454 | /* ok output for other types is the same */ | |
455 | sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, | |
456 | ldns_buffer_begin(b64sig)); | |
457 | } | |
fd185f4d | 458 | #endif /* splint */ |
825eb42b JL |
459 | ldns_buffer_free(b64sig); |
460 | EVP_MD_CTX_cleanup(&ctx); | |
461 | return sigdata_rdf; | |
462 | } | |
463 | ||
464 | ldns_rdf * | |
465 | ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) | |
466 | { | |
467 | unsigned char *sha1_hash; | |
468 | unsigned int siglen; | |
469 | ldns_rdf *sigdata_rdf; | |
470 | ldns_buffer *b64sig; | |
471 | int result; | |
472 | ||
473 | siglen = 0; | |
474 | b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); | |
475 | if (!b64sig) { | |
476 | return NULL; | |
477 | } | |
478 | ||
479 | sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), | |
480 | ldns_buffer_position(to_sign), NULL); | |
481 | if (!sha1_hash) { | |
482 | ldns_buffer_free(b64sig); | |
483 | return NULL; | |
484 | } | |
485 | ||
486 | result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, | |
487 | (unsigned char*)ldns_buffer_begin(b64sig), | |
488 | &siglen, key); | |
489 | if (result != 1) { | |
d1b2b5ca | 490 | ldns_buffer_free(b64sig); |
825eb42b JL |
491 | return NULL; |
492 | } | |
493 | ||
494 | sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, | |
495 | ldns_buffer_begin(b64sig)); | |
496 | ldns_buffer_free(b64sig); /* can't free this buffer ?? */ | |
497 | return sigdata_rdf; | |
498 | } | |
499 | ||
500 | ldns_rdf * | |
501 | ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) | |
502 | { | |
503 | unsigned char *md5_hash; | |
504 | unsigned int siglen; | |
505 | ldns_rdf *sigdata_rdf; | |
506 | ldns_buffer *b64sig; | |
507 | ||
508 | b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); | |
509 | if (!b64sig) { | |
510 | return NULL; | |
511 | } | |
ac996e71 | 512 | |
825eb42b JL |
513 | md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign), |
514 | ldns_buffer_position(to_sign), NULL); | |
515 | if (!md5_hash) { | |
516 | ldns_buffer_free(b64sig); | |
517 | return NULL; | |
518 | } | |
519 | ||
520 | RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH, | |
521 | (unsigned char*)ldns_buffer_begin(b64sig), | |
522 | &siglen, key); | |
523 | ||
ac996e71 | 524 | sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, |
825eb42b JL |
525 | ldns_buffer_begin(b64sig)); |
526 | ldns_buffer_free(b64sig); | |
527 | return sigdata_rdf; | |
528 | } | |
529 | #endif /* HAVE_SSL */ | |
530 | ||
b5dedcca JL |
531 | /** |
532 | * Pushes all rrs from the rrsets of type A and AAAA on gluelist. | |
533 | */ | |
534 | static ldns_status | |
535 | ldns_dnssec_addresses_on_glue_list( | |
536 | ldns_dnssec_rrsets *cur_rrset, | |
537 | ldns_rr_list *glue_list) | |
825eb42b | 538 | { |
b5dedcca | 539 | ldns_dnssec_rrs *cur_rrs; |
825eb42b | 540 | while (cur_rrset) { |
b5dedcca JL |
541 | if (cur_rrset->type == LDNS_RR_TYPE_A |
542 | || cur_rrset->type == LDNS_RR_TYPE_AAAA) { | |
543 | for (cur_rrs = cur_rrset->rrs; | |
544 | cur_rrs; | |
545 | cur_rrs = cur_rrs->next) { | |
546 | if (cur_rrs->rr) { | |
547 | if (!ldns_rr_list_push_rr(glue_list, | |
548 | cur_rrs->rr)) { | |
549 | return LDNS_STATUS_MEM_ERR; | |
550 | /* ldns_rr_list_push_rr() | |
551 | * returns false when unable | |
552 | * to increase the capacity | |
553 | * of the ldsn_rr_list | |
554 | */ | |
555 | } | |
556 | } | |
557 | } | |
825eb42b | 558 | } |
b5dedcca | 559 | cur_rrset = cur_rrset->next; |
825eb42b | 560 | } |
b5dedcca | 561 | return LDNS_STATUS_OK; |
825eb42b JL |
562 | } |
563 | ||
b5dedcca JL |
564 | /** |
565 | * Marks the names in the zone that are occluded. Those names will be skipped | |
566 | * when walking the tree with the ldns_dnssec_name_node_next_nonglue() | |
567 | * function. But watch out! Names that are partially occluded (like glue with | |
568 | * the same name as the delegation) will not be marked and should specifically | |
569 | * be taken into account seperately. | |
570 | * | |
571 | * When glue_list is given (not NULL), in the process of marking the names, all | |
572 | * glue resource records will be pushed to that list, even glue at delegation names. | |
573 | * | |
574 | * \param[in] zone the zone in which to mark the names | |
575 | * \param[in] glue_list the list to which to push the glue rrs | |
576 | * \return LDNS_STATUS_OK on success, an error code otherwise | |
577 | */ | |
825eb42b | 578 | ldns_status |
b5dedcca JL |
579 | ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, |
580 | ldns_rr_list *glue_list) | |
825eb42b | 581 | { |
b5dedcca JL |
582 | ldns_rbnode_t *node; |
583 | ldns_dnssec_name *name; | |
584 | ldns_rdf *owner; | |
585 | ldns_rdf *cut = NULL; /* keeps track of zone cuts */ | |
586 | /* When the cut is caused by a delegation, below_delegation will be 1. | |
587 | * When caused by a DNAME, below_delegation will be 0. | |
588 | */ | |
589 | int below_delegation = -1; /* init suppresses comiler warning */ | |
590 | ldns_status s; | |
825eb42b | 591 | |
b5dedcca JL |
592 | if (!zone || !zone->names) { |
593 | return LDNS_STATUS_NULL; | |
594 | } | |
595 | for (node = ldns_rbtree_first(zone->names); | |
596 | node != LDNS_RBTREE_NULL; | |
597 | node = ldns_rbtree_next(node)) { | |
598 | name = (ldns_dnssec_name *) node->data; | |
599 | owner = ldns_dnssec_name_name(name); | |
600 | ||
601 | if (cut) { | |
602 | /* The previous node was a zone cut, or a subdomain | |
603 | * below a zone cut. Is this node (still) a subdomain | |
604 | * below the cut? Then the name is occluded. Unless | |
605 | * the name contains a SOA, after which we are | |
606 | * authoritative again. | |
607 | * | |
608 | * FIXME! If there are labels in between the SOA and | |
609 | * the cut, going from the authoritative space (below | |
610 | * the SOA) up into occluded space again, will not be | |
611 | * detected with the contruct below! | |
612 | */ | |
613 | if (ldns_dname_is_subdomain(owner, cut) && | |
614 | !ldns_dnssec_rrsets_contains_type( | |
615 | name->rrsets, LDNS_RR_TYPE_SOA)) { | |
616 | ||
617 | if (below_delegation && glue_list) { | |
618 | s = ldns_dnssec_addresses_on_glue_list( | |
619 | name->rrsets, glue_list); | |
620 | if (s != LDNS_STATUS_OK) { | |
621 | return s; | |
622 | } | |
623 | } | |
624 | name->is_glue = true; /* Mark occluded name! */ | |
625 | continue; | |
626 | } else { | |
627 | cut = NULL; | |
628 | } | |
629 | } | |
630 | ||
631 | /* The node is not below a zone cut. Is it a zone cut itself? | |
632 | * Everything below a SOA is authoritative of course; Except | |
633 | * when the name also contains a DNAME :). | |
634 | */ | |
635 | if (ldns_dnssec_rrsets_contains_type( | |
636 | name->rrsets, LDNS_RR_TYPE_NS) | |
637 | && !ldns_dnssec_rrsets_contains_type( | |
638 | name->rrsets, LDNS_RR_TYPE_SOA)) { | |
639 | cut = owner; | |
640 | below_delegation = 1; | |
641 | if (glue_list) { /* record glue on the zone cut */ | |
642 | s = ldns_dnssec_addresses_on_glue_list( | |
643 | name->rrsets, glue_list); | |
644 | if (s != LDNS_STATUS_OK) { | |
645 | return s; | |
825eb42b | 646 | } |
825eb42b | 647 | } |
b5dedcca JL |
648 | } else if (ldns_dnssec_rrsets_contains_type( |
649 | name->rrsets, LDNS_RR_TYPE_DNAME)) { | |
650 | cut = owner; | |
651 | below_delegation = 0; | |
825eb42b JL |
652 | } |
653 | } | |
654 | return LDNS_STATUS_OK; | |
655 | } | |
656 | ||
b5dedcca JL |
657 | /** |
658 | * Marks the names in the zone that are occluded. Those names will be skipped | |
659 | * when walking the tree with the ldns_dnssec_name_node_next_nonglue() | |
660 | * function. But watch out! Names that are partially occluded (like glue with | |
661 | * the same name as the delegation) will not be marked and should specifically | |
662 | * be taken into account seperately. | |
663 | * | |
664 | * \param[in] zone the zone in which to mark the names | |
665 | * \return LDNS_STATUS_OK on success, an error code otherwise | |
666 | */ | |
667 | ldns_status | |
668 | ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone) | |
669 | { | |
670 | return ldns_dnssec_zone_mark_and_get_glue(zone, NULL); | |
671 | } | |
672 | ||
825eb42b JL |
673 | ldns_rbnode_t * |
674 | ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node) | |
675 | { | |
676 | ldns_rbnode_t *next_node = NULL; | |
677 | ldns_dnssec_name *next_name = NULL; | |
678 | bool done = false; | |
679 | ||
680 | if (node == LDNS_RBTREE_NULL) { | |
681 | return NULL; | |
682 | } | |
683 | next_node = node; | |
684 | while (!done) { | |
685 | if (next_node == LDNS_RBTREE_NULL) { | |
686 | return NULL; | |
687 | } else { | |
688 | next_name = (ldns_dnssec_name *)next_node->data; | |
689 | if (!next_name->is_glue) { | |
690 | done = true; | |
691 | } else { | |
692 | next_node = ldns_rbtree_next(next_node); | |
693 | } | |
694 | } | |
695 | } | |
696 | return next_node; | |
697 | } | |
698 | ||
699 | ldns_status | |
700 | ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, | |
701 | ldns_rr_list *new_rrs) | |
702 | { | |
703 | ||
704 | ldns_rbnode_t *first_node, *cur_node, *next_node; | |
705 | ldns_dnssec_name *cur_name, *next_name; | |
706 | ldns_rr *nsec_rr; | |
707 | uint32_t nsec_ttl; | |
708 | ldns_dnssec_rrsets *soa; | |
ac996e71 | 709 | |
825eb42b JL |
710 | /* the TTL of NSEC rrs should be set to the minimum TTL of |
711 | * the zone SOA (RFC4035 Section 2.3) | |
712 | */ | |
713 | soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); | |
ac996e71 | 714 | |
825eb42b JL |
715 | /* did the caller actually set it? if not, |
716 | * fall back to default ttl | |
717 | */ | |
b5dedcca JL |
718 | if (soa && soa->rrs && soa->rrs->rr |
719 | && (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) { | |
720 | nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); | |
825eb42b JL |
721 | } else { |
722 | nsec_ttl = LDNS_DEFAULT_TTL; | |
723 | } | |
ac996e71 | 724 | |
825eb42b JL |
725 | first_node = ldns_dnssec_name_node_next_nonglue( |
726 | ldns_rbtree_first(zone->names)); | |
727 | cur_node = first_node; | |
728 | if (cur_node) { | |
729 | next_node = ldns_dnssec_name_node_next_nonglue( | |
730 | ldns_rbtree_next(cur_node)); | |
731 | } else { | |
732 | next_node = NULL; | |
733 | } | |
734 | ||
735 | while (cur_node && next_node) { | |
736 | cur_name = (ldns_dnssec_name *)cur_node->data; | |
737 | next_name = (ldns_dnssec_name *)next_node->data; | |
738 | nsec_rr = ldns_dnssec_create_nsec(cur_name, | |
739 | next_name, | |
740 | LDNS_RR_TYPE_NSEC); | |
741 | ldns_rr_set_ttl(nsec_rr, nsec_ttl); | |
fd185f4d JL |
742 | if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ |
743 | ldns_rr_free(nsec_rr); | |
744 | return LDNS_STATUS_ERR; | |
745 | } | |
825eb42b JL |
746 | ldns_rr_list_push_rr(new_rrs, nsec_rr); |
747 | cur_node = next_node; | |
748 | if (cur_node) { | |
749 | next_node = ldns_dnssec_name_node_next_nonglue( | |
750 | ldns_rbtree_next(cur_node)); | |
751 | } | |
752 | } | |
753 | ||
754 | if (cur_node && !next_node) { | |
755 | cur_name = (ldns_dnssec_name *)cur_node->data; | |
756 | next_name = (ldns_dnssec_name *)first_node->data; | |
757 | nsec_rr = ldns_dnssec_create_nsec(cur_name, | |
758 | next_name, | |
759 | LDNS_RR_TYPE_NSEC); | |
760 | ldns_rr_set_ttl(nsec_rr, nsec_ttl); | |
fd185f4d JL |
761 | if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ |
762 | ldns_rr_free(nsec_rr); | |
763 | return LDNS_STATUS_ERR; | |
764 | } | |
825eb42b JL |
765 | ldns_rr_list_push_rr(new_rrs, nsec_rr); |
766 | } else { | |
767 | printf("error\n"); | |
768 | } | |
769 | ||
770 | return LDNS_STATUS_OK; | |
771 | } | |
772 | ||
773 | #ifdef HAVE_SSL | |
b5dedcca JL |
774 | /* in dnssec_zone.c */ |
775 | extern int ldns_dname_compare_v(const void *a, const void *b); | |
776 | ||
825eb42b | 777 | ldns_status |
b5dedcca JL |
778 | ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, |
779 | ldns_rr_list *new_rrs, | |
780 | uint8_t algorithm, | |
781 | uint8_t flags, | |
782 | uint16_t iterations, | |
783 | uint8_t salt_length, | |
784 | uint8_t *salt, | |
785 | ldns_rbtree_t **map) | |
825eb42b JL |
786 | { |
787 | ldns_rbnode_t *first_name_node; | |
788 | ldns_rbnode_t *current_name_node; | |
789 | ldns_dnssec_name *current_name; | |
790 | ldns_status result = LDNS_STATUS_OK; | |
791 | ldns_rr *nsec_rr; | |
792 | ldns_rr_list *nsec3_list; | |
793 | uint32_t nsec_ttl; | |
794 | ldns_dnssec_rrsets *soa; | |
b5dedcca | 795 | ldns_rbnode_t *hashmap_node; |
ac996e71 | 796 | |
825eb42b JL |
797 | if (!zone || !new_rrs || !zone->names) { |
798 | return LDNS_STATUS_ERR; | |
799 | } | |
ac996e71 | 800 | |
825eb42b JL |
801 | /* the TTL of NSEC rrs should be set to the minimum TTL of |
802 | * the zone SOA (RFC4035 Section 2.3) | |
803 | */ | |
804 | soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); | |
ac996e71 | 805 | |
825eb42b JL |
806 | /* did the caller actually set it? if not, |
807 | * fall back to default ttl | |
808 | */ | |
b5dedcca JL |
809 | if (soa && soa->rrs && soa->rrs->rr |
810 | && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) { | |
811 | nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); | |
825eb42b JL |
812 | } else { |
813 | nsec_ttl = LDNS_DEFAULT_TTL; | |
814 | } | |
815 | ||
b5dedcca JL |
816 | if (map) { |
817 | if ((*map = ldns_rbtree_create(ldns_dname_compare_v)) | |
818 | == NULL) { | |
819 | map = NULL; | |
820 | }; | |
821 | } | |
825eb42b JL |
822 | nsec3_list = ldns_rr_list_new(); |
823 | ||
824 | first_name_node = ldns_dnssec_name_node_next_nonglue( | |
825 | ldns_rbtree_first(zone->names)); | |
ac996e71 | 826 | |
825eb42b JL |
827 | current_name_node = first_name_node; |
828 | ||
829 | while (current_name_node && | |
830 | current_name_node != LDNS_RBTREE_NULL) { | |
831 | current_name = (ldns_dnssec_name *) current_name_node->data; | |
832 | nsec_rr = ldns_dnssec_create_nsec3(current_name, | |
833 | NULL, | |
834 | zone->soa->name, | |
835 | algorithm, | |
836 | flags, | |
837 | iterations, | |
838 | salt_length, | |
839 | salt); | |
840 | /* by default, our nsec based generator adds rrsigs | |
841 | * remove the bitmap for empty nonterminals */ | |
842 | if (!current_name->rrsets) { | |
843 | ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr)); | |
844 | } | |
845 | ldns_rr_set_ttl(nsec_rr, nsec_ttl); | |
fd185f4d | 846 | result = ldns_dnssec_name_add_rr(current_name, nsec_rr); |
825eb42b JL |
847 | ldns_rr_list_push_rr(new_rrs, nsec_rr); |
848 | ldns_rr_list_push_rr(nsec3_list, nsec_rr); | |
b5dedcca JL |
849 | if (map) { |
850 | hashmap_node = LDNS_MALLOC(ldns_rbnode_t); | |
851 | if (hashmap_node && ldns_rr_owner(nsec_rr)) { | |
852 | hashmap_node->key = ldns_dname_label( | |
853 | ldns_rr_owner(nsec_rr), 0); | |
854 | if (hashmap_node->key) { | |
855 | hashmap_node->data = current_name->name; | |
856 | (void) ldns_rbtree_insert( | |
857 | *map, hashmap_node); | |
858 | } | |
859 | } | |
860 | } | |
825eb42b JL |
861 | current_name_node = ldns_dnssec_name_node_next_nonglue( |
862 | ldns_rbtree_next(current_name_node)); | |
863 | } | |
fd185f4d | 864 | if (result != LDNS_STATUS_OK) { |
d1b2b5ca | 865 | ldns_rr_list_free(nsec3_list); |
fd185f4d JL |
866 | return result; |
867 | } | |
825eb42b JL |
868 | |
869 | ldns_rr_list_sort_nsec3(nsec3_list); | |
fd185f4d | 870 | result = ldns_dnssec_chain_nsec3_list(nsec3_list); |
825eb42b | 871 | ldns_rr_list_free(nsec3_list); |
d1b2b5ca | 872 | |
825eb42b JL |
873 | return result; |
874 | } | |
b5dedcca JL |
875 | |
876 | ldns_status | |
877 | ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, | |
878 | ldns_rr_list *new_rrs, | |
879 | uint8_t algorithm, | |
880 | uint8_t flags, | |
881 | uint16_t iterations, | |
882 | uint8_t salt_length, | |
883 | uint8_t *salt) | |
884 | { | |
885 | return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm, | |
886 | flags, iterations, salt_length, salt, NULL); | |
887 | ||
888 | } | |
825eb42b JL |
889 | #endif /* HAVE_SSL */ |
890 | ||
891 | ldns_dnssec_rrs * | |
d1b2b5ca JM |
892 | ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures |
893 | , ATTR_UNUSED(ldns_key_list *key_list) | |
894 | , int (*func)(ldns_rr *, void *) | |
895 | , void *arg | |
896 | ) | |
825eb42b JL |
897 | { |
898 | ldns_dnssec_rrs *base_rrs = signatures; | |
899 | ldns_dnssec_rrs *cur_rr = base_rrs; | |
900 | ldns_dnssec_rrs *prev_rr = NULL; | |
901 | ldns_dnssec_rrs *next_rr; | |
902 | ||
903 | uint16_t keytag; | |
904 | size_t i; | |
825eb42b | 905 | |
825eb42b JL |
906 | if (!cur_rr) { |
907 | switch(func(NULL, arg)) { | |
908 | case LDNS_SIGNATURE_LEAVE_ADD_NEW: | |
909 | case LDNS_SIGNATURE_REMOVE_ADD_NEW: | |
910 | break; | |
911 | case LDNS_SIGNATURE_LEAVE_NO_ADD: | |
912 | case LDNS_SIGNATURE_REMOVE_NO_ADD: | |
913 | ldns_key_list_set_use(key_list, false); | |
914 | break; | |
915 | default: | |
916 | fprintf(stderr, "[XX] unknown return value from callback\n"); | |
917 | break; | |
918 | } | |
919 | return NULL; | |
920 | } | |
ac996e71 | 921 | (void)func(cur_rr->rr, arg); |
825eb42b JL |
922 | |
923 | while (cur_rr) { | |
924 | next_rr = cur_rr->next; | |
ac996e71 | 925 | |
825eb42b JL |
926 | switch (func(cur_rr->rr, arg)) { |
927 | case LDNS_SIGNATURE_LEAVE_ADD_NEW: | |
928 | prev_rr = cur_rr; | |
929 | break; | |
930 | case LDNS_SIGNATURE_LEAVE_NO_ADD: | |
931 | keytag = ldns_rdf2native_int16( | |
932 | ldns_rr_rrsig_keytag(cur_rr->rr)); | |
933 | for (i = 0; i < ldns_key_list_key_count(key_list); i++) { | |
934 | if (ldns_key_keytag(ldns_key_list_key(key_list, i)) == | |
935 | keytag) { | |
936 | ldns_key_set_use(ldns_key_list_key(key_list, i), | |
937 | false); | |
938 | } | |
939 | } | |
940 | prev_rr = cur_rr; | |
941 | break; | |
942 | case LDNS_SIGNATURE_REMOVE_NO_ADD: | |
943 | keytag = ldns_rdf2native_int16( | |
944 | ldns_rr_rrsig_keytag(cur_rr->rr)); | |
945 | for (i = 0; i < ldns_key_list_key_count(key_list); i++) { | |
946 | if (ldns_key_keytag(ldns_key_list_key(key_list, i)) | |
947 | == keytag) { | |
948 | ldns_key_set_use(ldns_key_list_key(key_list, i), | |
949 | false); | |
950 | } | |
951 | } | |
952 | if (prev_rr) { | |
953 | prev_rr->next = next_rr; | |
954 | } else { | |
955 | base_rrs = next_rr; | |
956 | } | |
957 | LDNS_FREE(cur_rr); | |
958 | break; | |
959 | case LDNS_SIGNATURE_REMOVE_ADD_NEW: | |
960 | if (prev_rr) { | |
961 | prev_rr->next = next_rr; | |
962 | } else { | |
963 | base_rrs = next_rr; | |
964 | } | |
965 | LDNS_FREE(cur_rr); | |
966 | break; | |
967 | default: | |
968 | fprintf(stderr, "[XX] unknown return value from callback\n"); | |
969 | break; | |
970 | } | |
971 | cur_rr = next_rr; | |
972 | } | |
973 | ||
974 | return base_rrs; | |
975 | } | |
976 | ||
977 | #ifdef HAVE_SSL | |
978 | ldns_status | |
979 | ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, | |
980 | ldns_rr_list *new_rrs, | |
981 | ldns_key_list *key_list, | |
982 | int (*func)(ldns_rr *, void*), | |
983 | void *arg) | |
984 | { | |
ac996e71 | 985 | return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, |
825eb42b JL |
986 | func, arg, 0); |
987 | } | |
988 | ||
989 | /** If there are KSKs use only them and mark ZSKs unused */ | |
990 | static void | |
991 | ldns_key_list_filter_for_dnskey(ldns_key_list *key_list) | |
992 | { | |
993 | int saw_ksk = 0; | |
994 | size_t i; | |
995 | for(i=0; i<ldns_key_list_key_count(key_list); i++) | |
996 | if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) { | |
997 | saw_ksk = 1; | |
998 | break; | |
999 | } | |
1000 | if(!saw_ksk) | |
1001 | return; | |
1002 | for(i=0; i<ldns_key_list_key_count(key_list); i++) | |
1003 | if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) | |
1004 | ldns_key_set_use(ldns_key_list_key(key_list, i), 0); | |
1005 | } | |
1006 | ||
ac996e71 JL |
1007 | /** If there are no ZSKs use KSK as ZSK */ |
1008 | static void | |
1009 | ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list) | |
1010 | { | |
1011 | int saw_zsk = 0; | |
1012 | size_t i; | |
1013 | for(i=0; i<ldns_key_list_key_count(key_list); i++) | |
1014 | if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) { | |
1015 | saw_zsk = 1; | |
1016 | break; | |
1017 | } | |
1018 | if(!saw_zsk) | |
1019 | return; | |
1020 | /* else filter all KSKs */ | |
1021 | for(i=0; i<ldns_key_list_key_count(key_list); i++) | |
1022 | if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) | |
1023 | ldns_key_set_use(ldns_key_list_key(key_list, i), 0); | |
1024 | } | |
1025 | ||
825eb42b | 1026 | ldns_status |
d1b2b5ca JM |
1027 | ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone |
1028 | , ldns_rr_list *new_rrs | |
1029 | , ldns_key_list *key_list | |
1030 | , int (*func)(ldns_rr *, void*) | |
1031 | , void *arg | |
1032 | , int flags | |
1033 | ) | |
825eb42b JL |
1034 | { |
1035 | ldns_status result = LDNS_STATUS_OK; | |
1036 | ||
1037 | ldns_rbnode_t *cur_node; | |
1038 | ldns_rr_list *rr_list; | |
1039 | ||
1040 | ldns_dnssec_name *cur_name; | |
1041 | ldns_dnssec_rrsets *cur_rrset; | |
1042 | ldns_dnssec_rrs *cur_rr; | |
1043 | ||
1044 | ldns_rr_list *siglist; | |
ac996e71 | 1045 | |
825eb42b JL |
1046 | size_t i; |
1047 | ||
b5dedcca JL |
1048 | int on_delegation_point = 0; /* handle partially occluded names */ |
1049 | ||
825eb42b | 1050 | ldns_rr_list *pubkey_list = ldns_rr_list_new(); |
825eb42b | 1051 | for (i = 0; i<ldns_key_list_key_count(key_list); i++) { |
d1b2b5ca JM |
1052 | ldns_rr_list_push_rr( pubkey_list |
1053 | , ldns_key2rr(ldns_key_list_key( | |
1054 | key_list, i)) | |
1055 | ); | |
825eb42b JL |
1056 | } |
1057 | /* TODO: callback to see is list should be signed */ | |
1058 | /* TODO: remove 'old' signatures from signature list */ | |
1059 | cur_node = ldns_rbtree_first(zone->names); | |
1060 | while (cur_node != LDNS_RBTREE_NULL) { | |
1061 | cur_name = (ldns_dnssec_name *) cur_node->data; | |
1062 | ||
1063 | if (!cur_name->is_glue) { | |
b5dedcca JL |
1064 | on_delegation_point = ldns_dnssec_rrsets_contains_type( |
1065 | cur_name->rrsets, LDNS_RR_TYPE_NS) | |
1066 | && !ldns_dnssec_rrsets_contains_type( | |
1067 | cur_name->rrsets, LDNS_RR_TYPE_SOA); | |
825eb42b JL |
1068 | cur_rrset = cur_name->rrsets; |
1069 | while (cur_rrset) { | |
1070 | /* reset keys to use */ | |
1071 | ldns_key_list_set_use(key_list, true); | |
ac996e71 | 1072 | |
825eb42b JL |
1073 | /* walk through old sigs, remove the old, |
1074 | and mark which keys (not) to use) */ | |
1075 | cur_rrset->signatures = | |
1076 | ldns_dnssec_remove_signatures(cur_rrset->signatures, | |
1077 | key_list, | |
1078 | func, | |
1079 | arg); | |
1080 | if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) && | |
1081 | cur_rrset->type == LDNS_RR_TYPE_DNSKEY) | |
1082 | ldns_key_list_filter_for_dnskey(key_list); | |
ac996e71 JL |
1083 | |
1084 | if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY) | |
1085 | ldns_key_list_filter_for_non_dnskey(key_list); | |
1086 | ||
825eb42b JL |
1087 | /* TODO: just set count to zero? */ |
1088 | rr_list = ldns_rr_list_new(); | |
ac996e71 | 1089 | |
825eb42b JL |
1090 | cur_rr = cur_rrset->rrs; |
1091 | while (cur_rr) { | |
1092 | ldns_rr_list_push_rr(rr_list, cur_rr->rr); | |
1093 | cur_rr = cur_rr->next; | |
1094 | } | |
ac996e71 | 1095 | |
825eb42b | 1096 | /* only sign non-delegation RRsets */ |
b5dedcca JL |
1097 | /* (glue should have been marked earlier, |
1098 | * except on the delegation points itself) */ | |
1099 | if (!on_delegation_point || | |
1100 | ldns_rr_list_type(rr_list) | |
1101 | == LDNS_RR_TYPE_DS || | |
1102 | ldns_rr_list_type(rr_list) | |
1103 | == LDNS_RR_TYPE_NSEC || | |
1104 | ldns_rr_list_type(rr_list) | |
1105 | == LDNS_RR_TYPE_NSEC3) { | |
825eb42b JL |
1106 | siglist = ldns_sign_public(rr_list, key_list); |
1107 | for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { | |
1108 | if (cur_rrset->signatures) { | |
fd185f4d | 1109 | result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures, |
825eb42b JL |
1110 | ldns_rr_list_rr(siglist, |
1111 | i)); | |
1112 | } else { | |
1113 | cur_rrset->signatures = ldns_dnssec_rrs_new(); | |
1114 | cur_rrset->signatures->rr = | |
1115 | ldns_rr_list_rr(siglist, i); | |
d1b2b5ca JM |
1116 | } |
1117 | if (new_rrs) { | |
825eb42b | 1118 | ldns_rr_list_push_rr(new_rrs, |
d1b2b5ca JM |
1119 | ldns_rr_list_rr(siglist, |
1120 | i)); | |
825eb42b JL |
1121 | } |
1122 | } | |
1123 | ldns_rr_list_free(siglist); | |
1124 | } | |
ac996e71 | 1125 | |
825eb42b | 1126 | ldns_rr_list_free(rr_list); |
ac996e71 | 1127 | |
825eb42b JL |
1128 | cur_rrset = cur_rrset->next; |
1129 | } | |
ac996e71 | 1130 | |
825eb42b | 1131 | /* sign the nsec */ |
ac996e71 | 1132 | ldns_key_list_set_use(key_list, true); |
825eb42b JL |
1133 | cur_name->nsec_signatures = |
1134 | ldns_dnssec_remove_signatures(cur_name->nsec_signatures, | |
1135 | key_list, | |
1136 | func, | |
1137 | arg); | |
ac996e71 JL |
1138 | ldns_key_list_filter_for_non_dnskey(key_list); |
1139 | ||
825eb42b JL |
1140 | rr_list = ldns_rr_list_new(); |
1141 | ldns_rr_list_push_rr(rr_list, cur_name->nsec); | |
1142 | siglist = ldns_sign_public(rr_list, key_list); | |
ac996e71 | 1143 | |
825eb42b JL |
1144 | for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { |
1145 | if (cur_name->nsec_signatures) { | |
fd185f4d | 1146 | result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, |
825eb42b JL |
1147 | ldns_rr_list_rr(siglist, i)); |
1148 | } else { | |
1149 | cur_name->nsec_signatures = ldns_dnssec_rrs_new(); | |
1150 | cur_name->nsec_signatures->rr = | |
1151 | ldns_rr_list_rr(siglist, i); | |
d1b2b5ca JM |
1152 | } |
1153 | if (new_rrs) { | |
825eb42b | 1154 | ldns_rr_list_push_rr(new_rrs, |
d1b2b5ca | 1155 | ldns_rr_list_rr(siglist, i)); |
825eb42b JL |
1156 | } |
1157 | } | |
ac996e71 | 1158 | |
825eb42b JL |
1159 | ldns_rr_list_free(siglist); |
1160 | ldns_rr_list_free(rr_list); | |
1161 | } | |
1162 | cur_node = ldns_rbtree_next(cur_node); | |
1163 | } | |
1164 | ||
1165 | ldns_rr_list_deep_free(pubkey_list); | |
1166 | return result; | |
1167 | } | |
1168 | ||
1169 | ldns_status | |
1170 | ldns_dnssec_zone_sign(ldns_dnssec_zone *zone, | |
1171 | ldns_rr_list *new_rrs, | |
1172 | ldns_key_list *key_list, | |
1173 | int (*func)(ldns_rr *, void *), | |
1174 | void *arg) | |
1175 | { | |
1176 | return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0); | |
1177 | } | |
1178 | ||
1179 | ldns_status | |
1180 | ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, | |
1181 | ldns_rr_list *new_rrs, | |
1182 | ldns_key_list *key_list, | |
1183 | int (*func)(ldns_rr *, void *), | |
1184 | void *arg, | |
1185 | int flags) | |
1186 | { | |
1187 | ldns_status result = LDNS_STATUS_OK; | |
1188 | ||
1189 | if (!zone || !new_rrs || !key_list) { | |
1190 | return LDNS_STATUS_ERR; | |
1191 | } | |
1192 | ||
1193 | /* zone is already sorted */ | |
fd185f4d JL |
1194 | result = ldns_dnssec_zone_mark_glue(zone); |
1195 | if (result != LDNS_STATUS_OK) { | |
1196 | return result; | |
1197 | } | |
ac996e71 | 1198 | |
825eb42b JL |
1199 | /* check whether we need to add nsecs */ |
1200 | if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { | |
1201 | result = ldns_dnssec_zone_create_nsecs(zone, new_rrs); | |
1202 | if (result != LDNS_STATUS_OK) { | |
1203 | return result; | |
1204 | } | |
1205 | } | |
1206 | ||
1207 | result = ldns_dnssec_zone_create_rrsigs_flg(zone, | |
1208 | new_rrs, | |
1209 | key_list, | |
1210 | func, | |
1211 | arg, | |
1212 | flags); | |
1213 | ||
1214 | return result; | |
1215 | } | |
1216 | ||
1217 | ldns_status | |
1218 | ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, | |
1219 | ldns_rr_list *new_rrs, | |
1220 | ldns_key_list *key_list, | |
1221 | int (*func)(ldns_rr *, void *), | |
1222 | void *arg, | |
1223 | uint8_t algorithm, | |
1224 | uint8_t flags, | |
1225 | uint16_t iterations, | |
1226 | uint8_t salt_length, | |
1227 | uint8_t *salt) | |
1228 | { | |
b5dedcca JL |
1229 | return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, |
1230 | func, arg, algorithm, flags, iterations, salt_length, salt, 0, | |
1231 | NULL); | |
825eb42b JL |
1232 | } |
1233 | ||
1234 | ldns_status | |
b5dedcca JL |
1235 | ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, |
1236 | ldns_rr_list *new_rrs, | |
1237 | ldns_key_list *key_list, | |
1238 | int (*func)(ldns_rr *, void *), | |
1239 | void *arg, | |
1240 | uint8_t algorithm, | |
1241 | uint8_t flags, | |
1242 | uint16_t iterations, | |
1243 | uint8_t salt_length, | |
1244 | uint8_t *salt, | |
1245 | int signflags, | |
1246 | ldns_rbtree_t **map) | |
825eb42b | 1247 | { |
b5dedcca | 1248 | ldns_rr *nsec3, *nsec3param; |
825eb42b JL |
1249 | ldns_status result = LDNS_STATUS_OK; |
1250 | ||
1251 | /* zone is already sorted */ | |
fd185f4d JL |
1252 | result = ldns_dnssec_zone_mark_glue(zone); |
1253 | if (result != LDNS_STATUS_OK) { | |
1254 | return result; | |
1255 | } | |
825eb42b JL |
1256 | |
1257 | /* TODO if there are already nsec3s presents and their | |
1258 | * parameters are the same as these, we don't have to recreate | |
1259 | */ | |
1260 | if (zone->names) { | |
1261 | /* add empty nonterminals */ | |
fd185f4d JL |
1262 | result = ldns_dnssec_zone_add_empty_nonterminals(zone); |
1263 | if (result != LDNS_STATUS_OK) { | |
1264 | return result; | |
1265 | } | |
825eb42b JL |
1266 | |
1267 | nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec; | |
1268 | if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) { | |
1269 | /* no need to recreate */ | |
1270 | } else { | |
1271 | if (!ldns_dnssec_zone_find_rrset(zone, | |
1272 | zone->soa->name, | |
b5dedcca JL |
1273 | LDNS_RR_TYPE_NSEC3PARAM)) { |
1274 | /* create and add the nsec3param rr */ | |
1275 | nsec3param = | |
1276 | ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM); | |
1277 | ldns_rr_set_owner(nsec3param, | |
825eb42b | 1278 | ldns_rdf_clone(zone->soa->name)); |
b5dedcca | 1279 | ldns_nsec3_add_param_rdfs(nsec3param, |
825eb42b JL |
1280 | algorithm, |
1281 | flags, | |
1282 | iterations, | |
1283 | salt_length, | |
1284 | salt); | |
1285 | /* always set bit 7 of the flags to zero, according to | |
d1b2b5ca JM |
1286 | * rfc5155 section 11. The bits are counted from right to left, |
1287 | * so bit 7 in rfc5155 is bit 0 in ldns */ | |
1288 | ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0); | |
b5dedcca | 1289 | result = ldns_dnssec_zone_add_rr(zone, nsec3param); |
fd185f4d JL |
1290 | if (result != LDNS_STATUS_OK) { |
1291 | return result; | |
1292 | } | |
b5dedcca | 1293 | ldns_rr_list_push_rr(new_rrs, nsec3param); |
825eb42b | 1294 | } |
b5dedcca | 1295 | result = ldns_dnssec_zone_create_nsec3s_mkmap(zone, |
825eb42b JL |
1296 | new_rrs, |
1297 | algorithm, | |
1298 | flags, | |
1299 | iterations, | |
1300 | salt_length, | |
b5dedcca JL |
1301 | salt, |
1302 | map); | |
825eb42b JL |
1303 | if (result != LDNS_STATUS_OK) { |
1304 | return result; | |
1305 | } | |
1306 | } | |
1307 | ||
1308 | result = ldns_dnssec_zone_create_rrsigs_flg(zone, | |
1309 | new_rrs, | |
1310 | key_list, | |
1311 | func, | |
1312 | arg, | |
1313 | signflags); | |
1314 | } | |
ac996e71 | 1315 | |
825eb42b JL |
1316 | return result; |
1317 | } | |
1318 | ||
b5dedcca JL |
1319 | ldns_status |
1320 | ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, | |
1321 | ldns_rr_list *new_rrs, | |
1322 | ldns_key_list *key_list, | |
1323 | int (*func)(ldns_rr *, void *), | |
1324 | void *arg, | |
1325 | uint8_t algorithm, | |
1326 | uint8_t flags, | |
1327 | uint16_t iterations, | |
1328 | uint8_t salt_length, | |
1329 | uint8_t *salt, | |
1330 | int signflags) | |
1331 | { | |
1332 | return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, | |
1333 | func, arg, algorithm, flags, iterations, salt_length, salt, | |
1334 | signflags, NULL); | |
1335 | } | |
825eb42b JL |
1336 | |
1337 | ldns_zone * | |
1338 | ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) | |
1339 | { | |
1340 | ldns_dnssec_zone *dnssec_zone; | |
1341 | ldns_zone *signed_zone; | |
1342 | ldns_rr_list *new_rrs; | |
1343 | size_t i; | |
1344 | ||
1345 | signed_zone = ldns_zone_new(); | |
1346 | dnssec_zone = ldns_dnssec_zone_new(); | |
1347 | ||
1348 | (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); | |
ac996e71 JL |
1349 | ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); |
1350 | ||
825eb42b JL |
1351 | for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { |
1352 | (void) ldns_dnssec_zone_add_rr(dnssec_zone, | |
1353 | ldns_rr_list_rr(ldns_zone_rrs(zone), | |
1354 | i)); | |
ac996e71 | 1355 | ldns_zone_push_rr(signed_zone, |
825eb42b JL |
1356 | ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), |
1357 | i))); | |
1358 | } | |
1359 | ||
1360 | new_rrs = ldns_rr_list_new(); | |
1361 | (void) ldns_dnssec_zone_sign(dnssec_zone, | |
1362 | new_rrs, | |
1363 | key_list, | |
1364 | ldns_dnssec_default_replace_signatures, | |
1365 | NULL); | |
1366 | ||
1367 | for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { | |
1368 | ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), | |
1369 | ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); | |
1370 | } | |
1371 | ||
1372 | ldns_rr_list_deep_free(new_rrs); | |
1373 | ldns_dnssec_zone_free(dnssec_zone); | |
1374 | ||
1375 | return signed_zone; | |
1376 | } | |
1377 | ||
1378 | ldns_zone * | |
1379 | 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) | |
1380 | { | |
1381 | ldns_dnssec_zone *dnssec_zone; | |
1382 | ldns_zone *signed_zone; | |
1383 | ldns_rr_list *new_rrs; | |
1384 | size_t i; | |
1385 | ||
1386 | signed_zone = ldns_zone_new(); | |
1387 | dnssec_zone = ldns_dnssec_zone_new(); | |
1388 | ||
1389 | (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); | |
ac996e71 JL |
1390 | ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); |
1391 | ||
825eb42b JL |
1392 | for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { |
1393 | (void) ldns_dnssec_zone_add_rr(dnssec_zone, | |
1394 | ldns_rr_list_rr(ldns_zone_rrs(zone), | |
1395 | i)); | |
1396 | ldns_zone_push_rr(signed_zone, | |
1397 | ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), | |
1398 | i))); | |
1399 | } | |
1400 | ||
1401 | new_rrs = ldns_rr_list_new(); | |
1402 | (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone, | |
1403 | new_rrs, | |
1404 | key_list, | |
1405 | ldns_dnssec_default_replace_signatures, | |
1406 | NULL, | |
1407 | algorithm, | |
1408 | flags, | |
1409 | iterations, | |
1410 | salt_length, | |
1411 | salt); | |
1412 | ||
1413 | for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { | |
1414 | ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), | |
1415 | ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); | |
1416 | } | |
1417 | ||
1418 | ldns_rr_list_deep_free(new_rrs); | |
1419 | ldns_dnssec_zone_free(dnssec_zone); | |
1420 | ||
1421 | return signed_zone; | |
1422 | } | |
1423 | #endif /* HAVE_SSL */ | |
1424 | ||
b5dedcca | 1425 |