]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/dnssec_v2/dnssec_v2_validation.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / dnssec_v2 / dnssec_v2_validation.c
1 //
2 // dnssec_v2_validation.c
3 // mDNSResponder
4 //
5 // Copyright (c) 2020 Apple Inc. All rights reserved.
6 //
7
8 #include "mDNSEmbeddedAPI.h"
9 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
10 #include <string.h> // for strerror
11 #include <errno.h> // for errno
12 #include "DNSCommon.h" // DomainNameHashValue
13 #include "dnssec_v2_structs.h"
14 #include "dnssec_v2_validation.h"
15 #include "dnssec_v2_retrieval.h"
16 #include "dnssec_v2_crypto.h"
17 #include "dnssec_v2_trust_anchor.h"
18 #include "dnssec_v2_log.h"
19 #include "dnssec_v2_helper.h"
20 #include "base_n.h"
21
22 //======================================================================================================================
23 // MARK: - macros
24 //======================================================================================================================
25
26 #define NSEC3_FLAG_OPT_OUT_BIT 1
27 #define NSEC3_FLAG_SET NSEC3_FLAG_OPT_OUT_BIT
28
29 //======================================================================================================================
30 // MARK: - validator type define
31 //======================================================================================================================
32 typedef struct dnssec_validator_node dnssec_validator_node_t;
33 struct dnssec_validator_node {
34 union {
35 struct {
36 response_type_t rr_response_type;
37 } rr;
38 struct {
39 const dnssec_dnskey_t * _Nullable key;
40 const dnssec_rrsig_t * _Nullable sig;
41 } zsk;
42 struct {
43 const dnssec_dnskey_t * _Nullable key;
44 const dnssec_rrsig_t * _Nullable sig;
45 const dnssec_ds_t * _Nullable ds;
46 } ksk;
47 struct {
48 const dnssec_nsec_t * _Nullable nsec;
49 } nsec;
50 struct {
51 const dnssec_nsec3_t * _Nullable nsec3;
52 } nsec3;
53 } u;
54 dnssec_validator_node_type_t type;
55 const mDNSu8 * _Nonnull name;
56 // type: resource_records, list_t<dnssec_original_t>; type: zone_signing_key, list<dnssec_dnskey_t>; type: key_signing_key, list<dnssec_dnskey_t>;
57 // type: nsec, list_t<one_nsec_with_rrsigs>; type: nsec3, list_t<one_nsec3_wtih_rrsigs>
58 const list_t * _Nullable siblings;
59 const list_t * _Nonnull rrssigs_covering_it;
60 mDNSBool trusted;
61 };
62
63 //======================================================================================================================
64 // MARK: - local functions prototype
65 //======================================================================================================================
66
67
68 // MARK: NSEC validation
69
70 mDNSlocal dnssec_validation_result_t
71 validate_nsec_response(
72 const mDNSu32 qname_hash,
73 const mDNSu8 * const _Nonnull qname,
74 const mDNSu16 qclass,
75 const mDNSu16 qtype,
76 const nsecs_with_rrsig_t * const _Nonnull nsecs_with_rrsig,
77 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_1,
78 const list_t * _Nullable * _Nonnull out_rrsigs_1,
79 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_2,
80 const list_t * _Nullable * _Nonnull out_rrsigs_2);
81
82 mDNSlocal mDNSBool
83 nsec_proves_no_data(
84 const mDNSu32 qname_hash,
85 const mDNSu8 * const _Nonnull qname,
86 const mDNSu16 qclass,
87 const mDNSu16 qtype,
88 const list_t * const _Nonnull nsecs,
89 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_data,
90 const list_t * _Nullable * _Nonnull out_rrsigs);
91
92 mDNSlocal mDNSBool
93 nsec_proves_name_error(
94 const mDNSu8 * const _Nonnull qname,
95 const list_t * const _Nonnull nsecs,
96 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_exact_match,
97 const list_t * _Nullable * _Nonnull out_rrsigs_no_exact_match,
98 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_wildcard,
99 const list_t * _Nullable * _Nonnull out_rrsigs_no_wildcard);
100
101 mDNSlocal mDNSBool
102 nsec_proves_wildcard_answer(
103 const mDNSu8 * const _Nonnull qname,
104 const mDNSu16 qtype,
105 const list_t * const _Nonnull nsecs,
106 const list_t * const _Nonnull wildcard_answer,
107 const list_t * const _Nonnull wildcard_rrsig,
108 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_exact_match,
109 const list_t * _Nullable * _Nonnull out_rrsigs_no_exact_match);
110
111 mDNSlocal mDNSBool
112 nsec_proves_wildcard_no_data(
113 const mDNSu8 * const _Nonnull qname,
114 const mDNSu16 qclass,
115 const mDNSu16 qtype,
116 const list_t * const _Nonnull nsecs,
117 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_exact_match,
118 const list_t * _Nullable * _Nonnull out_rrsigs_no_exact_match,
119 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_matching_stype,
120 const list_t * _Nullable * _Nonnull out_rrsigs_no_matching_stype);
121
122 // MARK: NSEC3 validation
123
124 mDNSlocal mDNSBool
125 is_nsec3_iteration_valid(const dnssec_context_t * const context);
126
127 mDNSlocal mDNSu16
128 get_maximum_nsec3_iteration_for_dnskey_length(mDNSu16 key_length);
129
130 mDNSlocal dnssec_validation_result_t
131 get_initial_children_to_validate(
132 dnssec_context_t * const _Nonnull context,
133 dnssec_validator_node_t * const _Nonnull child,
134 mDNSu8 * const _Nonnull out_child_size);
135
136 mDNSlocal dnssec_validation_result_t
137 validate_nsec3_response(
138 const mDNSu8 * const _Nonnull qname,
139 const mDNSu16 qtype,
140 const nsec3s_with_rrsig_t * const _Nonnull nsec3s_with_rrsig,
141 const dnssec_nsec3_t * _Nullable * _Nonnull out_nsec3_1,
142 const list_t * _Nullable * _Nonnull out_rrsig_1,
143 const dnssec_nsec3_t * _Nullable * _Nonnull out_nsec3_2,
144 const list_t * _Nullable * _Nonnull out_rrsig_2,
145 const dnssec_nsec3_t * _Nullable * _Nonnull out_nsec3_3,
146 const list_t * _Nullable * _Nonnull out_rrsig_3);
147
148 mDNSlocal dnssec_validation_result_t
149 nsec3_proves_closest_encloser(
150 const mDNSu8 * const _Nonnull name,
151 const list_t * const _Nonnull nsec3s,
152 const mDNSu8 * const _Nonnull zone_name,
153 mDNSu8 canonical_name[MAX_DOMAIN_NAME],
154 const dnssec_nsec3_t * _Nullable * const _Nonnull out_nsec3_closest_encloser_proof,
155 const list_t * _Nullable * const _Nonnull out_rrsig_closest_encloser_proof,
156 const dnssec_nsec3_t * _Nullable * const _Nonnull out_nsec3_next_closer_proof,
157 const list_t * _Nullable * const _Nonnull out_rrsig_next_closer_proof,
158 const mDNSu8 * _Nullable * const _Nonnull out_closest_encloser_name,
159 const mDNSu8 * _Nullable * const _Nonnull out_next_closer_name);
160
161 mDNSlocal mDNSBool
162 nsec3_contains_different_hash_iteration_salt(const list_t * const nsec3s);
163
164 mDNSlocal mDNSBool
165 ignore_this_nsec3_record(const dnssec_nsec3_t * const _Nonnull dnssec_nsec3);
166
167 // MARK: NSEC/NSEC3 helper function
168
169 mDNSlocal mDNSBool
170 bit_map_contain_dns_type(const mDNSu8 * const _Nonnull bit_maps, const mDNSu16 bit_maps_length, const mDNSu16 type);
171
172 // MARK: validator initializer
173
174 mDNSlocal void
175 initialize_validator_node_with_rr(
176 dnssec_validator_node_t * const _Nonnull node,
177 const mDNSu8 * const _Nonnull name,
178 const list_t * const _Nonnull siblings,
179 const list_t * const _Nonnull rrsigs_covering_it, // list_t<dnssec_rrsig_t>
180 response_type_t response_type); // list_t<dnssec_rrsig_t>
181
182 mDNSlocal void
183 initialize_validator_node_with_nsec(
184 dnssec_validator_node_t * const _Nonnull node,
185 const dnssec_nsec_t * _Nullable nsec,
186 const mDNSu8 * const _Nonnull name,
187 const list_t * const _Nonnull rrsig_covering_it ); // list_t<dnssec_rrsig_t>
188
189 mDNSlocal void
190 initialize_validator_node_with_nsec3(
191 dnssec_validator_node_t * const _Nonnull node,
192 const dnssec_nsec3_t * _Nullable nsec3,
193 const mDNSu8 * const _Nonnull name,
194 const list_t * const _Nonnull rrsig_covering_it); // list_t<dnssec_rrsig_t>
195
196 mDNSlocal void
197 initialize_validator_node_with_zsk(
198 dnssec_validator_node_t * const _Nonnull node,
199 const dnssec_dnskey_t * const _Nonnull key,
200 const dnssec_rrsig_t * const _Nonnull sig,
201 const mDNSu8 * const _Nonnull name,
202 const list_t * const _Nonnull siblings, // list<dnssec_dnskey_t>
203 const list_t * const _Nonnull rrsig_covering_it, // list_t<dnssec_rrsig_t>
204 mDNSBool trusted);
205
206 mDNSlocal void
207 initialize_validator_node_with_ksk(
208 dnssec_validator_node_t * const _Nonnull node,
209 const dnssec_dnskey_t * const _Nonnull key,
210 const dnssec_rrsig_t * const _Nonnull sig,
211 const dnssec_ds_t * const _Nullable ds,
212 const mDNSu8 * const _Nonnull name,
213 const list_t * const _Nonnull siblings, // list<dnssec_ds_t>
214 const list_t * const _Nonnull rrsig_covering_it, // list_t<dnssec_rrsig_t>
215 mDNSBool trusted);
216
217 mDNSlocal void
218 uninitialize_validator_node(dnssec_validator_node_t * const _Nonnull node);
219
220 // MARK: validation function
221
222 mDNSlocal dnssec_validation_result_t
223 build_trust_from_ksk_to_zsk(
224 const mDNSu32 request_id,
225 const dnssec_zone_t * const _Nonnull zone,
226 const list_t * const _Nonnull dnskeys,
227 const list_t * const _Nonnull dses,
228 const list_t * const _Nonnull rrsigs_covering_dnskey,
229 dnssec_validator_node_t * _Nonnull children,
230 const mDNSu8 child_size,
231 dnssec_validator_node_t * _Nonnull parents,
232 mDNSu8 * const _Nonnull out_parent_size);
233
234 mDNSlocal dnssec_validation_result_t
235 build_trust_from_zsk(
236 const mDNSu32 request_id,
237 const dnssec_zone_t * const _Nonnull zone,
238 const list_t * const _Nonnull dnskey_list,
239 const list_t * const _Nonnull rrsig_list_covering_dnskey,
240 dnssec_validator_node_t * _Nonnull children,
241 const mDNSu8 child_size,
242 dnssec_validator_node_t * _Nonnull parents,
243 mDNSu8 * const _Nonnull out_parent_size);
244
245 mDNSlocal dnssec_validation_result_t
246 validate_validator_node(const dnssec_validator_node_t * const _Nonnull nodes, const mDNSu8 nodes_count);
247
248 mDNSlocal dnssec_validation_result_t
249 validate_validator_path_between_parents_and_children(
250 const mDNSu32 request_id,
251 dnssec_validator_node_t * _Nonnull children,
252 dnssec_validator_node_t * _Nonnull parents,
253 mDNSu8 * const _Nonnull out_parent_size);
254
255 mDNSlocal dnssec_validation_result_t
256 validate_validator_path(
257 const mDNSu32 request_id,
258 const dnssec_validator_node_t * const _Nonnull child,
259 const dnssec_validator_node_t * const _Nonnull parent);
260
261 mDNSlocal dnssec_validation_result_t
262 check_trust_validator_node(const dnssec_validator_node_t * const _Nonnull node);
263
264 mDNSlocal void
265 dedup_validator_with_the_same_siblings(
266 dnssec_validator_node_t * _Nonnull parents,
267 mDNSu8 * const _Nonnull out_parent_size);
268
269 mDNSlocal void
270 print_ds_validation_progress(const dnssec_validator_node_t * const _Nonnull nodes, const mDNSu8 nodes_count);
271
272 mDNSlocal dnssec_validation_result_t
273 validate_zone_records_type(const dnssec_zone_t * const _Nonnull zone);
274
275 mDNSlocal dnssec_validation_result_t
276 validate_ds(const dnssec_ds_t * const _Nonnull ds);
277
278 mDNSlocal dnssec_validation_result_t
279 validate_dnskey(const dnssec_dnskey_t * const _Nonnull dnskey, mDNSBool security_entry_point);
280
281 mDNSlocal dnssec_validation_result_t
282 validate_rrsig(const dnssec_rrsig_t * const _Nonnull rrsig);
283
284 mDNSlocal dnssec_validation_result_t
285 validate_nsec(const dnssec_nsec_t * const _Nonnull nsec);
286
287 mDNSlocal dnssec_validation_result_t
288 validate_nsec3(const dnssec_nsec3_t * const _Nonnull nsec3);
289
290 mDNSlocal dnssec_validation_result_t
291 check_if_ds_ksk_matches(const dnssec_ds_t * const _Nonnull ds, const dnssec_dnskey_t * const _Nonnull ksk);
292
293 mDNSlocal dnssec_validation_result_t
294 validate_path_from_zsk_to_rr(
295 const mDNSu32 request_id,
296 const dnssec_validator_node_t * const _Nonnull parent,
297 const list_t * const _Nonnull originals /* list_t<dnssec_original_t> */,
298 response_type_t response_type);
299
300 mDNSlocal dnssec_validation_result_t
301 validate_path_from_ksk_to_zsk(
302 const mDNSu32 request_id,
303 const dnssec_validator_node_t * const _Nonnull parent,
304 const list_t * const _Nonnull zsks /* list_t<dnssec_dnskey_t> */);
305
306 mDNSlocal dnssec_validation_result_t
307 validate_path_from_zsk_to_ds(
308 const mDNSu32 request_id,
309 const dnssec_validator_node_t * const _Nonnull parent,
310 const list_t * const _Nonnull dses /* list_t<dnssec_dses_t> */);
311
312 mDNSlocal dnssec_validation_result_t
313 validate_path_from_zsk_to_nsec(
314 const mDNSu32 request_id,
315 const dnssec_validator_node_t * const _Nonnull parent,
316 const dnssec_validator_node_t * const _Nonnull child);
317
318 mDNSlocal dnssec_validation_result_t
319 validate_path_from_zsk_to_nsec3(
320 const mDNSu32 request_id,
321 const dnssec_validator_node_t * const _Nonnull parent,
322 const dnssec_validator_node_t * const _Nonnull child);
323
324 mDNSlocal dnssec_validation_result_t
325 check_rrsig_validity_with_dnssec_rr(
326 const dnssec_rrsig_t * const _Nonnull rrsig,
327 const dnssec_rr_t * const _Nonnull rr);
328
329 mDNSlocal dnssec_validation_result_t
330 check_rrsig_validity_with_rrs(
331 const dnssec_rrsig_t * const _Nonnull rrsig,
332 const list_t * const _Nonnull list_to_check,
333 response_type_t response_type_in_list,
334 const mDNSu16 record_type_in_list);
335
336 // MARK: reconstruct signed data
337
338 mDNSlocal void *
339 reconstruct_signed_data_with_rrs(
340 const list_t * const _Nonnull rr_set,
341 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
342 const response_type_t response_type,
343 const mDNSu16 record_type,
344 mDNSu32 * const _Nonnull out_signed_data_length);
345
346 mDNSlocal void *
347 reconstruct_signed_data_with_one_dnssec_rr(
348 const dnssec_rr_t * const _Nonnull dnssec_rr,
349 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
350 mDNSu32 * const _Nonnull out_signed_data_length);
351
352 mDNSlocal void *
353 reconstruct_signed_data_internal(
354 const dnssec_rr_t * const rr_array[],
355 const mDNSu8 rr_count,
356 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
357 mDNSu32 * const _Nonnull out_signed_data_length);
358
359 mDNSlocal mStatus
360 calculate_signed_data_length(
361 const dnssec_rr_t * const rr_array[_Nonnull],
362 const mDNSu8 rr_count,
363 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
364 mDNSu32 * const _Nonnull out_length);
365
366 mDNSlocal mDNSs16
367 calculate_name_length_in_signed_data(const mDNSu8 * const _Nonnull name, const mDNSu8 rrsig_labels);
368
369 mDNSlocal mDNSu16
370 calculate_rdata_length_in_signed_data(const dnssec_rr_t * const _Nonnull dnssec_rr);
371
372 mDNSlocal const mDNSu8 *
373 get_wildcard_name(const mDNSu8 * const _Nonnull name, mDNSu8 * const _Nonnull buffer, const mDNSu16 buffer_length);
374
375 mDNSlocal mDNSu32
376 copy_rr_for_signed_data(
377 mDNSu8 * _Nonnull dst,
378 const dnssec_rr_t * const _Nonnull rr,
379 const dnssec_rrsig_t * const _Nonnull rrsig);
380
381 mDNSlocal mDNSu8
382 copy_name_in_rr_for_signed_data(
383 mDNSu8 * const _Nonnull dst,
384 const mDNSu8 * const _Nonnull name,
385 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig);
386
387 mDNSlocal mDNSu16
388 copy_rdata_in_rr(mDNSu8 * const _Nonnull dst, const mDNSu8 * const rdata, const mDNSu16 rdata_length, const mDNSu8 rr_type);
389
390 // MARK: sort function
391
392 mDNSlocal void
393 sort_records_with_algorithm(dnssec_context_t * const _Nonnull context);
394
395 mDNSlocal mDNSs8
396 dnssec_ds_t_comparator(const list_node_t * _Nonnull const left, const list_node_t * _Nonnull const right);
397
398 mDNSlocal mDNSs8
399 dnssec_rrsig_t_comparator(const list_node_t * _Nonnull const left, const list_node_t * _Nonnull const right);
400
401 mDNSlocal void
402 sort_rr_array_canonically(const dnssec_rr_t * rr_array[_Nonnull], const mDNSu8 rr_count);
403
404 mDNSlocal mDNSs8
405 dnssec_rr_t_comparator(const dnssec_rr_t * const _Nonnull left, const dnssec_rr_t * const _Nonnull right);
406
407 mDNSlocal mDNSBool
408 rr_array_dedup(const dnssec_rr_t * rr_array[_Nonnull], const mDNSu8 rr_count);
409
410
411 //======================================================================================================================
412 // MARK: - function definations
413 //======================================================================================================================
414
415
416 // MARK: validate_dnssec
417
418 mDNSexport dnssec_validation_result_t
419 validate_dnssec(dnssec_context_t * const _Nonnull context) {
420 dnssec_validator_node_t child_node[4] = {0}; // 4 is big enough to hold: nsec3_1, nsec3_2, nsec3_3, wildcard
421 dnssec_validator_node_t parent_node[4] = {0}; // the same reason as the above
422 dnssec_validator_node_t * child = child_node;
423 dnssec_validator_node_t * parent = parent_node;
424 mDNSu8 child_size = 0;
425 mDNSu8 parent_size = 0;
426 const mDNSu32 request_id = context->original.original_parameters.request_id;
427
428 dnssec_validator_node_t * temp_validator = mDNSNULL;
429 mDNSu8 temp_size = 0;
430 dnssec_validation_result_t validation_result = dnssec_validation_valid;
431 mDNSBool nsec3_iteration_valid;
432
433 nsec3_iteration_valid = is_nsec3_iteration_valid(context);
434 require_action_quiet(nsec3_iteration_valid, exit, validation_result = dnssec_validation_nsec3_invalid_hash_iteration);
435
436 // sort records with most secure algorithm comes first
437 sort_records_with_algorithm(context);
438
439 // get the original records out
440 validation_result = get_initial_children_to_validate(context, child, &child_size);
441 require_quiet(validation_result == dnssec_validation_valid && child_size != 0, exit);
442
443 // check if the original RRSET is valid
444 validation_result = validate_validator_node(child, child_size);
445 require_quiet(validation_result == dnssec_validation_valid, exit);
446
447 // check if the original RRSET is trusted by our trusted anchor, it is only possbile when the user queryies for
448 // DNSKEY record since trust anchor is used to trust DNSKEY
449 validation_result = check_trust_validator_node(child);
450 if (validation_result == dnssec_validation_trusted) {
451 goto exit;
452 }
453
454 // Check the validation through the entire chain of trust
455 for (list_node_t *zone_node = list_get_first(&context->zone_chain);
456 !list_has_ended(&context->zone_chain, zone_node);
457 zone_node = list_next(zone_node)) {
458
459 // check for every zone
460 dnssec_zone_t * zone = (dnssec_zone_t *)zone_node->data;
461 list_t * dnskeys = &zone->dnskeys_with_rrsig.dnskey_records;
462 list_t * dnskey_rrsigs = &zone->dnskeys_with_rrsig.rrsig_records;
463 list_t * dses = &zone->dses_with_rrsig.u.original.ds_records;
464 list_t * ds_rrsigs = &zone->dses_with_rrsig.u.original.rrsig_records;
465
466 // It is possible that some records in the critical path of trust chain is missing(NSEC/NSEC3) or redirected(CNAME)
467 validation_result = validate_zone_records_type(zone);
468 require_quiet(validation_result == dnssec_validation_valid, exit);
469
470 // Validate the previous records(DS or RR) with Zone Signing Key(ZSK)
471 validation_result = build_trust_from_zsk(request_id, zone, dnskeys, dnskey_rrsigs, child, child_size, parent, &parent_size);
472
473 if (validation_result != dnssec_validation_valid) {
474 goto exit;
475 }
476
477 if (parent_size == 0) {
478 validation_result = dnssec_validation_trusted;
479 goto exit;
480 }
481
482 // validate Zone Signing Key(ZSK) with Key Signing Key(KSK)
483 temp_validator = parent;
484 parent = child;
485 child = temp_validator;
486 temp_size = parent_size;
487 parent_size = child_size;
488 child_size = temp_size;
489 // TODO: test got NSEC/NSEC3 in the middle
490
491 validation_result = build_trust_from_ksk_to_zsk(request_id, zone, dnskeys, dses, ds_rrsigs, child, child_size, parent, &parent_size);
492 if (validation_result != dnssec_validation_valid) {
493 goto exit;
494 }
495
496 // print_ds_validation_progress(parent, parent_size);
497
498 if (parent_size == 0) {
499 validation_result = dnssec_validation_trusted;
500 goto exit;
501 }
502
503 // repeat the validation process until reaching trust anchor
504 temp_validator = parent;
505 parent = child;
506 child = temp_validator;
507 temp_size = parent_size;
508 parent_size = child_size;
509 child_size = temp_size;
510 }
511
512 exit:
513 return validation_result;
514 }
515
516 mDNSlocal dnssec_validation_result_t
517 validate_nsec_response(
518 const mDNSu32 qname_hash,
519 const mDNSu8 * const _Nonnull qname,
520 const mDNSu16 qclass,
521 const mDNSu16 qtype,
522 const nsecs_with_rrsig_t * const _Nonnull nsecs_with_rrsig,
523 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_1,
524 const list_t * _Nullable * _Nonnull out_rrsigs_1,
525 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_2,
526 const list_t * _Nullable * _Nonnull out_rrsigs_2) {
527
528 const list_t * const nsecs = &nsecs_with_rrsig->nsec_and_rrsigs_same_name;
529
530 // dnssec_validation_nsec_no_data
531 if (nsec_proves_no_data(qname_hash, qname, qclass, qtype, nsecs, out_nsec_1, out_rrsigs_1)) {
532 return dnssec_validation_nsec_no_data;
533 }
534
535 // dnssec_validation_nsec_name_error
536 if (nsec_proves_name_error(qname, nsecs, out_nsec_1, out_rrsigs_1, out_nsec_2, out_rrsigs_2)) {
537 return dnssec_validation_nsec_name_error;
538 }
539
540 // dnssec_validation_nsec_wildcard_answer
541 if (nsec_proves_wildcard_answer(qname, qtype, nsecs, &nsecs_with_rrsig->wildcard_answers, &nsecs_with_rrsig->wildcard_rrsigs, out_nsec_1, out_rrsigs_2)) {
542 return dnssec_validation_nsec_wildcard_answer;
543 }
544
545 // dnssec_validation_nsec_wildcard_no_data
546 if (nsec_proves_wildcard_no_data(qname, qclass, qtype, nsecs, out_nsec_1, out_rrsigs_1, out_nsec_2, out_rrsigs_2)) {
547 return dnssec_validation_nsec_wildcard_no_data;
548 }
549
550 return dnssec_validation_nsec_invalid_nsec_result;
551 }
552
553 // MARK: validate_dnssec
554 // According to https://tools.ietf.org/html/rfc5155#section-10.3 , the iteration field of NSEC3 should have an upper bound
555 // to prevent denial-of-service attacks
556 mDNSlocal mDNSBool
557 is_nsec3_iteration_valid(const dnssec_context_t * const context) {
558 mDNSBool valid = mDNStrue;
559 // check original response
560 const originals_with_rrsig_t * const originals_with_rrsig = &context->original.original_result_with_rrsig;
561
562 if (originals_with_rrsig->type == nsec3_response) {
563 const nsec3s_with_rrsig_t * const nsec3s_with_rrsig = &originals_with_rrsig->u.nsec3s_with_rrsig;
564 const list_t * const nsec3_and_rrsigs_same_name = &nsec3s_with_rrsig->nsec3_and_rrsigs_same_name; // list_t<one_nsec3_with_rrsigs_t>
565 const dnssec_zone_t * zone_with_dnskey;
566 const dnskeys_with_rrsig_t * dnskeys_with_rrsig;
567 const list_t * dnskeys;
568
569 require_action_quiet(!list_empty(nsec3_and_rrsigs_same_name), exit, valid = mDNSfalse);
570
571 require_quiet(!list_empty(&context->zone_chain), exit);
572 zone_with_dnskey = (dnssec_zone_t *)list_get_first(&context->zone_chain)->data;
573 dnskeys_with_rrsig = (dnskeys_with_rrsig_t *)&zone_with_dnskey->dnskeys_with_rrsig;
574
575 dnskeys = &dnskeys_with_rrsig->dnskey_records;
576 require_action_quiet(!list_empty(dnskeys), exit, valid = mDNSfalse);
577
578 for (const list_node_t *one_nsec3_node = list_get_first(nsec3_and_rrsigs_same_name);
579 !list_has_ended(nsec3_and_rrsigs_same_name, one_nsec3_node);
580 one_nsec3_node = list_next(one_nsec3_node)) {
581
582 const one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)one_nsec3_node->data;
583 const list_t * const rrsigs = &one_nsec3->rrsig_records; // list_t<dnssec_rrsig_t>
584 const mDNSu16 nsec3_iteration = one_nsec3->nsec3_record.iterations;
585
586 for (const list_node_t * rrsig_node = list_get_first(rrsigs);
587 !list_has_ended(rrsigs, rrsig_node);
588 rrsig_node = list_next(rrsig_node)) {
589
590 const dnssec_rrsig_t * const dnssec_rrsig = (dnssec_rrsig_t *)rrsig_node->data;
591 const mDNSu16 key_tag_from_rrsig = dnssec_rrsig->key_tag;
592
593 for (const list_node_t * dnskey_node = list_get_first(dnskeys);
594 !list_has_ended(dnskeys, dnskey_node);
595 dnskey_node = list_next(dnskey_node)) {
596
597 const dnssec_dnskey_t * const dnssec_dnskey = (dnssec_dnskey_t *)dnskey_node->data;
598 const mDNSu16 key_tag_from_dnskey = dnssec_dnskey->key_tag;
599 mDNSu16 max_iteration;
600
601 if (key_tag_from_rrsig != key_tag_from_dnskey) {
602 continue;
603 }
604
605 max_iteration = get_maximum_nsec3_iteration_for_dnskey_length(dnssec_dnskey->public_key_length);
606 require_action_quiet(nsec3_iteration <= max_iteration, exit, valid = mDNSfalse);
607 }
608 }
609 }
610 }
611
612 exit:
613 return valid;
614 }
615
616 mDNSlocal mDNSu16
617 get_maximum_nsec3_iteration_for_dnskey_length(mDNSu16 key_length) {
618 mDNSu16 max;
619 mDNSs32 rounded_key_length_in_bits = key_length * 8;
620 static const mDNSs32 fixed_key_size[] = {
621 1024, 2048, 4096
622 };
623 static const mDNSs32 max_iteration_for_fixed_key_size[] = {
624 150, 500, 2500
625 };
626 // use "sizeof(fixed_key_size) == sizeof(max_iteration_for_fixed_key_size) ? sizeof(fixed_key_size) / sizeof(mDNSu32) : -1" to check if two array have matched elements.
627 mDNSu32 distance_to_fixed_key_size[sizeof(fixed_key_size) == sizeof(max_iteration_for_fixed_key_size) ? sizeof(fixed_key_size) / sizeof(mDNSu32) : -1];
628
629 // get the closest key size from 102, 2048, 4096
630 for (size_t i = 0; i < sizeof(fixed_key_size) / sizeof(mDNSu32); i++) {
631 distance_to_fixed_key_size[i] = abs(fixed_key_size[i] - rounded_key_length_in_bits);
632 }
633
634 mDNSu32 min_distance = UINT_MAX;
635 size_t min_distance_index = -1;
636 for (size_t i = 0; i < sizeof(fixed_key_size) / sizeof(mDNSu32); i++) {
637 if (min_distance < distance_to_fixed_key_size[i]) {
638 continue;
639 }
640 min_distance = distance_to_fixed_key_size[i];
641 min_distance_index = i;
642 }
643
644 switch (fixed_key_size[min_distance_index]) {
645 case 1024:
646 max = 150;
647 break;
648 case 2048:
649 max = 500;
650 break;
651 case 4096:
652 max = 2500;
653 break;
654 default:
655 max = 0;
656 break;
657 }
658
659 return max;
660 }
661
662 mDNSlocal dnssec_validation_result_t
663 get_initial_children_to_validate(
664 dnssec_context_t * const _Nonnull context,
665 dnssec_validator_node_t * const _Nonnull child,
666 mDNSu8 * const _Nonnull out_child_size) {
667
668 const list_t * original_siblings;
669 mDNSu8 child_size = 0;
670 dnssec_validation_result_t validation_result = dnssec_validation_valid;
671 const response_type_t type = context->original.original_result_with_rrsig.type;
672 const mDNSu8 * qname = context->original.original_parameters.question_name.c;
673 const mDNSu32 qname_hash = DomainNameHashValue((domainname *)qname);
674 const mDNSu16 qclass = context->original.original_parameters.question_class;
675 const mDNSu16 qtype = context->original.original_parameters.question_type;
676 const trust_anchors_t * const orig_trust_anchor = context->original.original_trust_anchor;
677 mDNSu32 request_id = GET_REQUEST_ID(context);
678 mDNSu32 question_id = GET_QUESTION_ID(context);
679
680 switch (type) {
681 case original_response: {
682 // check if the trust anchor installed for the question name already trusts all the answers
683 mDNSBool trusted_original_response = mDNStrue;
684 const list_t * const original_rr_list = &context->original.original_result_with_rrsig.u.original.original_records;
685 if (qtype == kDNSType_DNSKEY && trust_anchor_contains_dnskey(orig_trust_anchor)) {
686 const list_t * const dnskey_trust_anchors = &orig_trust_anchor->dnskey_trust_anchors;
687 dnssec_dnskey_t left;
688
689 for (list_node_t * dnssec_original_node = list_get_first(original_rr_list);
690 !list_has_ended(original_rr_list, dnssec_original_node);
691 dnssec_original_node = list_next(dnssec_original_node)) {
692
693 const dnssec_original_t * const original = (dnssec_original_t *)dnssec_original_node->data;
694 parse_dns_type_dnskey_t(original->dnssec_rr.rdata, original->dnssec_rr.rdata_length,
695 &left.flags, &left.protocol, &left.algorithm, &left.public_key_length, &left.public_key);
696
697 mDNSBool trust_anchor_matches = mDNSfalse;
698 for (const list_node_t * dnskey_node = list_get_first(dnskey_trust_anchors);
699 !list_has_ended(dnskey_trust_anchors, dnskey_node);
700 dnskey_node = list_next(dnskey_node)) {
701 const dnssec_dnskey_t * const right_ptr = (dnssec_dnskey_t *)dnskey_node->data;
702 if (equals_dnssec_dnskey_t(&left, right_ptr)) {
703 trust_anchor_matches = mDNStrue;
704 break;
705 }
706 }
707
708 if (!trust_anchor_matches) {
709 trusted_original_response = mDNSfalse;
710 break;
711 }
712 }
713 } else if (qtype == kDNSType_DS && trust_anchor_contains_ds(orig_trust_anchor)) {
714 const list_t * const ds_trust_anchors = &orig_trust_anchor->ds_trust_anchors;
715 dnssec_ds_t left;
716 mDNSBool is_valid = mDNSfalse;
717
718 for (list_node_t * dnssec_original_node = list_get_first(original_rr_list);
719 !list_has_ended(original_rr_list, dnssec_original_node);
720 dnssec_original_node = list_next(dnssec_original_node)) {
721
722 const dnssec_original_t * const original = (dnssec_original_t *)dnssec_original_node->data;
723 is_valid = parse_dns_type_ds_t(original->dnssec_rr.rdata, original->dnssec_rr.rdata_length,
724 &left.key_tag, &left.algorithm, &left.digest_type, &left.digest_length, &left.digest);
725 verify_action(is_valid,
726 log_debug("[R%u->Q%u] The returned DS records are malformated", request_id, question_id);
727 continue
728 );
729
730 mDNSBool trust_anchor_matches = mDNSfalse;
731 for (const list_node_t * ds_node = list_get_first(ds_trust_anchors);
732 !list_has_ended(ds_trust_anchors, ds_node);
733 ds_node = list_next(ds_node)) {
734 const dnssec_ds_t * const right_ptr = (dnssec_ds_t *)ds_node->data;
735 if (equals_dnssec_ds_t(&left, right_ptr)) {
736 trust_anchor_matches = mDNStrue;
737 break;
738 }
739 }
740
741 if (!trust_anchor_matches) {
742 trusted_original_response = mDNSfalse;
743 break;
744 }
745 }
746 } else {
747 trusted_original_response = mDNSfalse;
748 }
749
750 if (trusted_original_response) {
751 validation_result = dnssec_validation_trusted;
752 goto exit;
753 }
754 } // fall into case cname_response
755 case cname_response: {
756 const list_t * rrsigs; // list_t<dnssec_rrsig_t>
757 if (type == original_response) {
758 original_siblings = &context->original.original_result_with_rrsig.u.original.original_records;
759 rrsigs = &context->original.original_result_with_rrsig.u.original.rrsig_records;
760 } else if (type == cname_response) {
761 original_siblings = &context->original.original_result_with_rrsig.u.cname_with_rrsig.cname_records;
762 rrsigs = &context->original.original_result_with_rrsig.u.cname_with_rrsig.rrsig_records;
763 } else {
764 validation_result = dnssec_validation_invalid_internal_state;
765 goto exit;
766 }
767 initialize_validator_node_with_rr(&child[child_size], qname, original_siblings, rrsigs, type);
768 child_size++;
769 break;
770 }
771 case nsec_response: {
772 // check the meaning of NSEC response: No Name, No Data, Wildcard Answer, Wildcard No Data
773 const dnssec_nsec_t * nsec_to_verify_1 = mDNSNULL;
774 const list_t * rrsigs_to_verify_1 = mDNSNULL;
775 const dnssec_nsec_t * nsec_to_verify_2 = mDNSNULL;
776 const list_t * rrsigs_to_verify_2 = mDNSNULL;
777 nsecs_with_rrsig_t * nsecs_with_rrsig = &context->original.original_result_with_rrsig.u.nsecs_with_rrsig;
778
779 nsecs_with_rrsig->nsec_result = validate_nsec_response(qname_hash, qname, qclass, qtype, nsecs_with_rrsig,
780 &nsec_to_verify_1, &rrsigs_to_verify_1, &nsec_to_verify_2, &rrsigs_to_verify_2);
781
782 require_action_quiet(
783 (nsecs_with_rrsig->nsec_result == dnssec_validation_nsec_no_data
784 || nsecs_with_rrsig->nsec_result == dnssec_validation_nsec_name_error
785 || nsecs_with_rrsig->nsec_result == dnssec_validation_nsec_wildcard_answer
786 || nsecs_with_rrsig->nsec_result == dnssec_validation_nsec_wildcard_no_data)
787 && rrsigs_to_verify_1 != mDNSNULL
788 , exit, validation_result = nsecs_with_rrsig->nsec_result); // When the assertion holds, rrsigs_to_verify_1 must be nonnull.
789
790 initialize_validator_node_with_nsec(&child[child_size], nsec_to_verify_1, qname, rrsigs_to_verify_1);
791 child_size++;
792
793 if (nsec_to_verify_2 != mDNSNULL) {
794 initialize_validator_node_with_nsec(&child[child_size], nsec_to_verify_2, qname, rrsigs_to_verify_2);
795 child_size++;
796 }
797
798 if (!list_empty(&nsecs_with_rrsig->wildcard_answers)) {
799 // and nsecs_with_rrsig->wildcard_rrsigs is not empty either
800 initialize_validator_node_with_rr(&child[child_size], qname, &nsecs_with_rrsig->wildcard_answers,
801 &nsecs_with_rrsig->wildcard_rrsigs, original_response);
802 child_size++;
803 }
804 break;
805 }
806 case nsec3_response: {
807 const dnssec_nsec3_t * nsec3_to_verify_1 = mDNSNULL;
808 const list_t * rrsigs_to_verify_1 = mDNSNULL;
809 const dnssec_nsec3_t * nsec3_to_verify_2 = mDNSNULL;
810 const list_t * rrsigs_to_verify_2 = mDNSNULL;
811 const dnssec_nsec3_t * nsec3_to_verify_3 = mDNSNULL;
812 const list_t * rrsigs_to_verify_3 = mDNSNULL;
813 nsec3s_with_rrsig_t * nsec3s_with_rrsig = &context->original.original_result_with_rrsig.u.nsec3s_with_rrsig;
814
815 nsec3s_with_rrsig->nsec3_result = validate_nsec3_response(qname, qtype, nsec3s_with_rrsig,
816 &nsec3_to_verify_1, &rrsigs_to_verify_1, &nsec3_to_verify_2, &rrsigs_to_verify_2, &nsec3_to_verify_3, &rrsigs_to_verify_3);
817
818 require_action_quiet(
819 nsec3s_with_rrsig->nsec3_result == dnssec_validation_nsec3_no_data_response
820 || nsec3s_with_rrsig->nsec3_result == dnssec_validation_nsec3_no_data_response
821 || nsec3s_with_rrsig->nsec3_result == dnssec_validation_nsec3_no_data_response_opt_out
822 || nsec3s_with_rrsig->nsec3_result == dnssec_validation_nsec3_wildcard_no_data
823 || nsec3s_with_rrsig->nsec3_result == dnssec_validation_nsec3_wildcard_answer_response
824 || nsec3s_with_rrsig->nsec3_result == dnssec_validation_nsec3_name_error
825 , exit, validation_result = nsec3s_with_rrsig->nsec3_result);
826
827 initialize_validator_node_with_nsec3(&child[child_size], nsec3_to_verify_1, qname, rrsigs_to_verify_1);
828 child_size++;
829
830 if (nsec3_to_verify_2 != mDNSNULL) {
831 initialize_validator_node_with_nsec3(&child[child_size], nsec3_to_verify_2, qname, rrsigs_to_verify_2);
832 child_size++;
833 }
834
835 if (nsec3_to_verify_3 != mDNSNULL) {
836 initialize_validator_node_with_nsec3(&child[child_size], nsec3_to_verify_3, qname, rrsigs_to_verify_3);
837 child_size++;
838 }
839
840 if (!list_empty(&nsec3s_with_rrsig->wildcard_answers)) {
841 // and nsecs_with_rrsig->wildcard_rrsigs is not empty either
842 initialize_validator_node_with_rr(&child[child_size], qname, &nsec3s_with_rrsig->wildcard_answers,
843 &nsec3s_with_rrsig->wildcard_rrsigs, rr_validator);
844 child_size++;
845 }
846 break;
847 }
848 default:
849 log_error("DNSSEC validation starts with unknown orginal resource record;");
850 validation_result = dnssec_validation_invalid_internal_state;
851 goto exit;
852 }
853
854 exit:
855 *out_child_size = child_size;
856 return validation_result;
857 }
858
859 mDNSlocal dnssec_validation_result_t
860 validate_nsec3_response(
861 const mDNSu8 * const _Nonnull qname,
862 const mDNSu16 qtype,
863 const nsec3s_with_rrsig_t * const _Nonnull nsec3s_with_rrsig,
864 const dnssec_nsec3_t * _Nullable * _Nonnull out_nsec3_1,
865 const list_t * _Nullable * _Nonnull out_rrsig_1,
866 const dnssec_nsec3_t * _Nullable * _Nonnull out_nsec3_2,
867 const list_t * _Nullable * _Nonnull out_rrsig_2,
868 const dnssec_nsec3_t * _Nullable * _Nonnull out_nsec3_3,
869 const list_t * _Nullable * _Nonnull out_rrsig_3) {
870
871 dnssec_validation_result_t validation_result = dnssec_validation_validating;
872 dnssec_validation_result_t error;
873 const list_t * const nsec3s = &nsec3s_with_rrsig->nsec3_and_rrsigs_same_name;
874 const one_nsec3_with_rrsigs_t * const first_one_nsec3 = (one_nsec3_with_rrsigs_t *)(list_get_first(nsec3s)->data);
875 const dnssec_nsec3_t * const first_dnssec_nsec3 = &first_one_nsec3->nsec3_record;
876 const mDNSu8 hash_algorithm = first_dnssec_nsec3->hash_algorithm;
877 const mDNSu8 * const salt = first_dnssec_nsec3->salt;
878 const mDNSu8 salt_length = first_dnssec_nsec3->salt_length;
879 const mDNSu16 iterations = first_dnssec_nsec3->iterations;
880 mDNSu8 * qname_hash_b32 = mDNSNULL;
881 mDNSu16 qname_length = DOMAIN_NAME_LENGTH(qname);
882 mDNSu8 canonical_name[MAX_DOMAIN_NAME];
883
884 require_action(!list_empty(nsec3s), exit, validation_result = dnssec_validation_bogus;
885 log_default("nsec3 list is empty"));
886
887 require_action(!nsec3_contains_different_hash_iteration_salt(nsec3s), exit, validation_result = dnssec_validation_nsec3_different_hash_iteration_salt;
888 log_default("NSEC3s with different algorithm, salt or iteration in the same response"));
889
890 // check if there is any wildcard response
891 if (!list_empty(&nsec3s_with_rrsig->wildcard_answers)) {
892 // Wildcard Answer Responses
893 const list_t * const wildcard_answers = &nsec3s_with_rrsig->wildcard_answers; // list_t<dnssec_rr_t>
894 const mDNSu8 * closest_encloser_name;
895 mDNSu8 closest_encloser_name_length;
896 const dnssec_nsec3_t * nsec3_closest_encloser_proof;
897 const list_t * rrsig_closest_encloser_proof;
898 const mDNSu8 * next_closer;
899 const dnssec_nsec3_t * nsec3_next_closer_proof;
900 const list_t * rrsig_next_closer_proof;
901
902 error = nsec3_proves_closest_encloser(qname, nsec3s, qname, canonical_name, &nsec3_closest_encloser_proof,
903 &rrsig_closest_encloser_proof, &nsec3_next_closer_proof, &rrsig_next_closer_proof, &closest_encloser_name,
904 &next_closer);
905 require_action(error == dnssec_validation_nsec3_provable_closest_encloser, exit,
906 validation_result = dnssec_validation_bogus;log_default("Cannot find closest encloser;"));
907 closest_encloser_name_length = DOMAIN_NAME_LENGTH(closest_encloser_name);
908
909 // make sure that this closest encloser is the immediate ancestor to the generating wildcard
910 for (list_node_t *node = list_get_first(wildcard_answers); !list_has_ended(wildcard_answers, node); node = list_next(node)) {
911 const dnssec_rr_t * const dnssec_rr = (dnssec_rr_t *)node->data;
912 const mDNSu8 * name = dnssec_rr->name.c;
913
914 mDNSBool matches = memcmp(name + 1 + *name, closest_encloser_name,
915 MIN(DOMAIN_NAME_LENGTH(name), closest_encloser_name_length));
916
917 require_action(matches, exit, validation_result = dnssec_validation_bogus);
918 }
919
920 *out_nsec3_1 = nsec3_closest_encloser_proof;
921 *out_rrsig_1 = rrsig_closest_encloser_proof;
922 *out_nsec3_2 = nsec3_next_closer_proof;
923 *out_rrsig_2 = rrsig_next_closer_proof;
924 validation_result = dnssec_validation_nsec3_wildcard_answer_response;
925
926 goto exit;
927 } else {
928 // check if there is a matching NSEC3 that matches qname
929
930 mDNSu8 qname_hash[MAX_HASH_OUTPUT_SIZE];
931 mDNSu32 qname_hash_length;
932 mDNSu8 qname_hash_b32_length;
933 const dnssec_nsec3_t * nsec3_that_matches_qname = mDNSNULL;
934
935 // get the base32 format of qname hash
936
937 qname_hash_length = get_hash_length_for_nsec3_hash_type(hash_algorithm);
938 mDNSBool calculated = calculate_hash_for_nsec3(qname_hash, sizeof(qname_hash), hash_algorithm, qname, qname_length, salt, salt_length, iterations);
939 require_action(calculated, exit, validation_result = dnssec_validation_invalid_internal_state);
940 qname_hash_b32 = (mDNSu8 *)base_n_encode(DNSSEC_BASE_32_HEX, qname_hash, qname_hash_length);
941 qname_hash_b32_length = strlen((char *)qname_hash_b32);
942
943 for (list_node_t * one_nsec3_node = list_get_first(nsec3s);
944 !list_has_ended(nsec3s, one_nsec3_node);
945 one_nsec3_node = list_next(one_nsec3_node)) {
946
947 const one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)one_nsec3_node->data;
948 const dnssec_nsec3_t * const dnssec_nsec3 = &one_nsec3->nsec3_record;
949 const mDNSu8 * const frist_label_owner_name = dnssec_nsec3->dnssec_rr.name.c + 1;
950 const mDNSu8 first_label_length = *dnssec_nsec3->dnssec_rr.name.c;
951
952 if (compare_canonical_dns_label(qname_hash_b32, qname_hash_b32_length, frist_label_owner_name, first_label_length) == 0) {
953 *out_nsec3_1 = dnssec_nsec3;
954 *out_rrsig_1 = &one_nsec3->rrsig_records;
955 nsec3_that_matches_qname = dnssec_nsec3;
956 break;
957 }
958 }
959
960 if (nsec3_that_matches_qname != mDNSNULL) {
961 // No Data Responses, QTYPE is not DS
962 // No Data Responses, QTYPE is DS
963
964 // An NSEC3 RR that matches QNAME is present.
965 mDNSBool contains_type;
966 contains_type = bit_map_contain_dns_type(nsec3_that_matches_qname->type_bit_maps, nsec3_that_matches_qname->type_bit_maps_length, qtype);
967 require_action(!contains_type, exit, validation_result = dnssec_validation_bogus;
968 log_default("NSEC3 contains DNS type that should not exist;" PUB_S, DNS_TYPE_STR(qtype)));
969
970 contains_type = bit_map_contain_dns_type(nsec3_that_matches_qname->type_bit_maps, nsec3_that_matches_qname->type_bit_maps_length, kDNSType_CNAME);
971 require_action(!contains_type, exit, validation_result = dnssec_validation_bogus;
972 log_default("NSEC3 contains DNS type that should not exist;" PUB_S, DNS_TYPE_STR(kDNSType_CNAME)));
973
974 validation_result = dnssec_validation_nsec3_no_data_response;
975 goto exit;
976 } else {
977 // Wildcard No Data Responses
978 // Name Error Responses
979 // No Data Responses, QTYPE is DS
980 const mDNSu8 * closest_encloser_name;
981 mDNSu8 closest_encloser_name_length;
982 const dnssec_nsec3_t * nsec3_closest_encloser_proof;
983 const list_t * rrsig_closest_encloser_proof;
984 const mDNSu8 * next_closer;
985 const dnssec_nsec3_t * nsec3_next_closer_proof;
986 const list_t * rrsig_next_closer_proof;
987 mDNSu8 wildcard_closest_encloser[MAX_DOMAIN_NAME];
988 mDNSu8 wildcard_length;
989 mDNSu8 * wildcard_hash_b32 = mDNSNULL;
990 mDNSu32 wildcard_hash_b32_length;
991
992 // find closest encloser
993 error = nsec3_proves_closest_encloser(qname, nsec3s, qname, canonical_name, &nsec3_closest_encloser_proof,
994 &rrsig_closest_encloser_proof, &nsec3_next_closer_proof, &rrsig_next_closer_proof,
995 &closest_encloser_name, &next_closer);
996 require_action(error == dnssec_validation_nsec3_provable_closest_encloser, exit,
997 validation_result = dnssec_validation_bogus;log_default("Cannot find closest encloser;"));
998 closest_encloser_name_length = DOMAIN_NAME_LENGTH(closest_encloser_name);
999
1000 *out_nsec3_1 = nsec3_closest_encloser_proof;
1001 *out_rrsig_1 = rrsig_closest_encloser_proof;
1002 *out_nsec3_2 = nsec3_next_closer_proof;
1003 *out_rrsig_2 = rrsig_next_closer_proof;
1004
1005 // check if it is "No Data Responses, QTYPE is DS" case, the "Opt-out" case
1006 if (qtype == kDNSType_DS) {
1007 if ((nsec3_closest_encloser_proof->flags & NSEC3_FLAG_OPT_OUT_BIT)) {
1008 validation_result = dnssec_validation_nsec3_no_data_response_opt_out;
1009 } else {
1010 validation_result = dnssec_validation_bogus;
1011 }
1012 goto exit;
1013 }
1014
1015 require_action(closest_encloser_name_length + 2 <= sizeof(wildcard_closest_encloser), exit,
1016 validation_result = dnssec_validation_bogus; log_error("wildcard closest encloser length is invalid"));
1017
1018 // check if wildcard exists
1019 // get wildcard name
1020 wildcard_closest_encloser[0] = 1;
1021 wildcard_closest_encloser[1] = '*';
1022 memcpy(wildcard_closest_encloser + 2, closest_encloser_name, closest_encloser_name_length);
1023 wildcard_length = DOMAIN_NAME_LENGTH(wildcard_closest_encloser);
1024
1025 wildcard_hash_b32 = calculate_b32_hash_for_nsec3(wildcard_closest_encloser, wildcard_length,
1026 first_dnssec_nsec3->hash_algorithm, first_dnssec_nsec3->salt, first_dnssec_nsec3->salt_length, first_dnssec_nsec3->iterations);
1027 require_action(wildcard_hash_b32 != mDNSNULL, exit,
1028 validation_result = dnssec_validation_no_memory ;log_error("b32_encode failed"));
1029
1030 wildcard_hash_b32_length = strlen((char *)wildcard_hash_b32);
1031
1032 for (list_node_t *one_nsec3_node = list_get_first(nsec3s);
1033 !list_has_ended(nsec3s, one_nsec3_node);
1034 one_nsec3_node = list_next(one_nsec3_node)) {
1035
1036 const one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)one_nsec3_node->data;
1037 const dnssec_nsec3_t * const dnssec_nsec3 = &one_nsec3->nsec3_record;
1038 const mDNSu8 * current = (mDNSu8 *)(dnssec_nsec3->dnssec_rr.name.c + 1);
1039 const mDNSu8 current_length = *(dnssec_nsec3->dnssec_rr.name.c);
1040 const mDNSu8 * next = (mDNSu8 *)(dnssec_nsec3->next_hashed_owner_name_b32);
1041 const mDNSu8 next_length = dnssec_nsec3->next_hashed_owner_name_b32_length;
1042 mDNSBool last_nsec = compare_canonical_dns_label(current, current_length, next, next_length) > 0;
1043
1044 if (compare_canonical_dns_label(current, current_length, wildcard_hash_b32, wildcard_hash_b32_length) == 0) {
1045 // Wildcard No Data Responses
1046 *out_nsec3_2 = dnssec_nsec3;
1047
1048 // check type map
1049 mDNSBool contains_type;
1050 contains_type = bit_map_contain_dns_type(dnssec_nsec3->type_bit_maps, dnssec_nsec3->type_bit_maps_length, qtype);
1051 require_action(!contains_type, for_loop_exit,
1052 validation_result = dnssec_validation_bogus;
1053 log_default("NSEC3 contains DNS type that should not exist;" PUB_S, DNS_TYPE_STR(qtype)));
1054
1055 contains_type = bit_map_contain_dns_type(dnssec_nsec3->type_bit_maps, dnssec_nsec3->type_bit_maps_length, kDNSType_CNAME);
1056 require_action(!contains_type, for_loop_exit,
1057 validation_result = dnssec_validation_bogus;
1058 log_default("NSEC3 contains DNS type that should not exist;" PUB_S, DNS_TYPE_STR(kDNSType_CNAME)));
1059
1060 *out_nsec3_3 = dnssec_nsec3;
1061 *out_rrsig_3 = &one_nsec3->rrsig_records;
1062 validation_result = dnssec_validation_nsec3_wildcard_no_data;
1063
1064 goto for_loop_exit;
1065 }
1066
1067 if (compare_canonical_dns_label(current, current_length, wildcard_hash_b32, wildcard_hash_b32_length) < 0
1068 && (last_nsec || compare_canonical_dns_label(wildcard_hash_b32, wildcard_hash_b32_length, next, next_length) < 0)) {
1069 // Name Error Responses
1070 *out_nsec3_3 = dnssec_nsec3;
1071 *out_rrsig_3 = &one_nsec3->rrsig_records;
1072 validation_result = dnssec_validation_nsec3_name_error;
1073
1074 goto for_loop_exit;
1075 }
1076 }
1077 validation_result = dnssec_validation_bogus;
1078 for_loop_exit:
1079 if (wildcard_hash_b32 != mDNSNULL) {
1080 free(wildcard_hash_b32);
1081 wildcard_hash_b32 = mDNSNULL;
1082 }
1083 }
1084 }
1085
1086 exit:
1087 if (qname_hash_b32 != mDNSNULL) {
1088 free(qname_hash_b32);
1089 }
1090 return validation_result;
1091 }
1092
1093 mDNSexport mDNSu16
1094 calculate_key_tag(const mDNSu8 key[_Nonnull], const mDNSu16 key_len, const mDNSu8 algorithm)
1095 {
1096 if (algorithm == 1) {
1097 // The key tag is defined to be the most significant 16 bits of the least significant 24 bits in the public key modulus.
1098 // However, RSA/MD5 whose algorithm number is 1 is not supported by mDNSResponder, so we will not implement it.
1099 return 0;
1100 }
1101
1102 mDNSu32 key_tag = 0;
1103
1104 for (mDNSu32 i = 0; i < key_len; i++)
1105 {
1106 if (i & 1) key_tag += key[i];
1107 else key_tag += (mDNSu32)(key[i] << 8);
1108 }
1109 key_tag += (key_tag >> 16) & 0xFFFF;
1110 key_tag &= 0xFFFF;
1111
1112 return key_tag;
1113 }
1114
1115 //======================================================================================================================
1116 // Local functions
1117 //======================================================================================================================
1118
1119 //======================================================================================================================
1120 // bit_map_contain_dns_type
1121 //======================================================================================================================
1122
1123 mDNSlocal mDNSBool
1124 bit_map_contain_dns_type(const mDNSu8 * const _Nonnull bit_maps, const mDNSu16 bit_maps_length, const mDNSu16 type) {
1125 const mDNSu8 window_index = type / 256;
1126 const mDNSu8 offset = type % 256;
1127 const mDNSu8 * ptr = bit_maps;
1128 const mDNSu8 * ptr_limit = ptr + bit_maps_length;
1129
1130 for (;ptr < ptr_limit; ptr += 2 + *(ptr + 1)) {
1131 const mDNSu8 current_window_index = *ptr;
1132 const mDNSu8 block_bit_map_length = *(ptr + 1);
1133 const mDNSu32 bit_count = block_bit_map_length * 8;
1134 const mDNSu8 mask = 1 << (7 - (offset % 8));
1135 const mDNSu8 * current_block = ptr + 2;
1136
1137 if (current_window_index != window_index) {
1138 continue;
1139 }
1140
1141 if (offset >= bit_count) {
1142 continue;
1143 }
1144
1145 if ((current_block[offset / 8] & mask) != 0) {
1146 return mDNStrue;
1147 }
1148 }
1149
1150 return mDNSfalse;
1151 }
1152
1153 //======================================================================================================================
1154 // NSEC result validation
1155 //======================================================================================================================
1156
1157 //======================================================================================================================
1158 // nsec_proves_no_data
1159 //======================================================================================================================
1160
1161 mDNSlocal mDNSBool
1162 nsec_proves_no_data(
1163 const mDNSu32 qname_hash,
1164 const mDNSu8 * const _Nonnull qname,
1165 const mDNSu16 qclass,
1166 const mDNSu16 qtype,
1167 const list_t * const _Nonnull nsecs,
1168 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_data,
1169 const list_t * _Nullable * _Nonnull out_rrsigs) {
1170
1171 for (list_node_t *nsec_node = list_get_first(nsecs); !list_has_ended(nsecs, nsec_node); nsec_node = list_next(nsec_node)) {
1172 const one_nsec_with_rrsigs_t * const one_nsec = (one_nsec_with_rrsigs_t *)nsec_node->data;
1173 // have NSEC record
1174 const dnssec_nsec_t * const dnssec_nsec = &one_nsec->nsec_record;
1175
1176 // with same SNAME
1177 if (qname_hash != dnssec_nsec->dnssec_rr.name_hash || !DOMAIN_NAME_EQUALS(qname, dnssec_nsec->exist_domain_name)) {
1178 continue;
1179 }
1180
1181 // with same SCLASS
1182 if (qclass != dnssec_nsec->dnssec_rr.rr_class) {
1183 continue;
1184 }
1185
1186 // does not contain the STYPE
1187 if (bit_map_contain_dns_type(dnssec_nsec->type_bit_maps, dnssec_nsec->type_bit_maps_length, qtype)) {
1188 continue;
1189 }
1190
1191 // proves No Data;
1192 *out_nsec_no_data = dnssec_nsec;
1193 *out_rrsigs = &one_nsec->rrsig_records;
1194 return mDNStrue;
1195 }
1196
1197 return mDNSfalse;
1198 }
1199
1200 //======================================================================================================================
1201 // nsec_proves_name_error
1202 //======================================================================================================================
1203
1204 mDNSlocal mDNSBool
1205 nsec_proves_name_error(
1206 const mDNSu8 * const _Nonnull qname,
1207 const list_t * const _Nonnull nsecs,
1208 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_exact_match,
1209 const list_t * _Nullable * _Nonnull out_rrsigs_no_exact_match,
1210 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_wildcard,
1211 const list_t * _Nullable * _Nonnull out_rrsigs_no_wildcard) {
1212
1213 mDNSBool no_exact_match = mDNSfalse;
1214 mDNSBool no_wildcard_match = mDNSfalse;
1215
1216 for (list_node_t *nsec_node = list_get_first(nsecs); !list_has_ended(nsecs, nsec_node); nsec_node = list_next(nsec_node)) {
1217 const one_nsec_with_rrsigs_t * const one_nsec = (one_nsec_with_rrsigs_t *)nsec_node->data;
1218 // have NSEC record
1219 const dnssec_nsec_t * const dnssec_nsec = &one_nsec->nsec_record;
1220 const mDNSu8 * const prev = dnssec_nsec->exist_domain_name;
1221 const mDNSu8 * const next = dnssec_nsec->next_domain_name;
1222 mDNSs8 name_compare_result;
1223 mDNSBool last_nsec = compare_canonical_dns_name(next, prev) < 0;;
1224
1225 // check if an NSEC RR proving that there is no exact match for <SNAME, SCLASS> exist
1226 while (!no_exact_match) {
1227 // prev < q_name
1228 name_compare_result = compare_canonical_dns_name(qname, prev);
1229 if (name_compare_result <= 0) {
1230 break;
1231 }
1232
1233 // q_name < next
1234 name_compare_result = compare_canonical_dns_name(next, qname);
1235 if (!last_nsec && name_compare_result <= 0) {
1236 break;
1237 }
1238
1239 *out_nsec_no_exact_match = dnssec_nsec;
1240 *out_rrsigs_no_exact_match = &one_nsec->rrsig_records;
1241 no_exact_match = mDNStrue;
1242 }
1243
1244 // check if an NSEC RR proving that the zone contains no RRsets that would match <SNAME, SCLASS>
1245 // via wildcard name expansion exists
1246 while (!no_wildcard_match) {
1247 mDNSu8 buffer[MAX_DOMAIN_NAME];
1248 const mDNSu8 * const wildcard_name = get_wildcard_name(qname, buffer, sizeof(buffer));
1249 if (wildcard_name == mDNSNULL) {
1250 break;
1251 }
1252
1253 // prev < wildcard_name
1254 name_compare_result = compare_canonical_dns_name(wildcard_name, prev);
1255 if (name_compare_result <= 0) {
1256 break;
1257 }
1258
1259 // wildcard_name < next
1260 name_compare_result = compare_canonical_dns_name(next, wildcard_name);
1261 if (!last_nsec && name_compare_result <= 0) {
1262 break;
1263 }
1264
1265 *out_nsec_no_wildcard = dnssec_nsec;
1266 *out_rrsigs_no_wildcard = &one_nsec->rrsig_records;
1267 no_wildcard_match = mDNStrue;
1268 }
1269
1270 if (no_exact_match && no_wildcard_match) {
1271 break;
1272 }
1273 }
1274
1275 return no_exact_match && no_wildcard_match;
1276 }
1277
1278 //======================================================================================================================
1279 // nsec_proves_wildcard_answer
1280 //======================================================================================================================
1281
1282 mDNSlocal mDNSBool
1283 nsec_proves_wildcard_answer(
1284 const mDNSu8 * const _Nonnull qname,
1285 const mDNSu16 qtype,
1286 const list_t * const _Nonnull nsecs,
1287 const list_t * const _Nonnull wildcard_answer,
1288 const list_t * const _Nonnull wildcard_rrsig,
1289 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_exact_match,
1290 const list_t * _Nullable * _Nonnull out_rrsigs_no_exact_match) {
1291
1292 mDNSBool no_exact_match = mDNSfalse;
1293 mDNSBool contains_wildcard_answer = mDNSfalse;
1294 mDNSBool contains_wildcard_rrsig = mDNSfalse;
1295
1296 for (list_node_t *nsec_node = list_get_first(nsecs); !list_has_ended(nsecs, nsec_node); nsec_node = list_next(nsec_node)) {
1297 const one_nsec_with_rrsigs_t * const one_nsec = (one_nsec_with_rrsigs_t *)nsec_node->data;
1298 // have NSEC record
1299 const dnssec_nsec_t * const dnssec_nsec = &one_nsec->nsec_record;
1300 const mDNSu8 * const prev = dnssec_nsec->exist_domain_name;
1301 const mDNSu8 * const next = dnssec_nsec->next_domain_name;
1302 mDNSs8 name_compare_result;
1303 mDNSBool last_nsec = compare_canonical_dns_name(prev, next) > 0;
1304
1305 // prev < q_name
1306 name_compare_result = compare_canonical_dns_name(qname, prev);
1307 if (name_compare_result <= 0) {
1308 continue;
1309 }
1310
1311 // q_name < next
1312 name_compare_result = compare_canonical_dns_name(next, qname);
1313 if (!last_nsec && name_compare_result <= 0) {
1314 continue;
1315 }
1316
1317 *out_nsec_no_exact_match = dnssec_nsec;
1318 *out_rrsigs_no_exact_match = &one_nsec->rrsig_records;
1319 no_exact_match = mDNStrue;
1320 }
1321
1322 // contains wildcard answer
1323 contains_wildcard_answer = !list_empty(wildcard_answer);
1324
1325 // contains wildcard RRSIG
1326 for (list_node_t *rrsig_node = list_get_first(wildcard_rrsig); !list_has_ended(wildcard_rrsig, rrsig_node); rrsig_node = list_next(rrsig_node)) {
1327 const dnssec_rrsig_t * const dnssec_rrsig = (dnssec_rrsig_t *)rrsig_node->data;
1328 // cover the wildcard
1329 if (dnssec_rrsig->type_covered != qtype) {
1330 continue;
1331 }
1332
1333 // label is 1 less than the question name
1334 if (dnssec_rrsig->labels + 1 != get_number_of_labels(dnssec_rrsig->dnssec_rr.name.c)) {
1335 continue;
1336 }
1337
1338 contains_wildcard_rrsig = mDNStrue;
1339 }
1340
1341 return no_exact_match && contains_wildcard_answer && contains_wildcard_rrsig;
1342 }
1343
1344 //======================================================================================================================
1345 // nsec_proves_wildcard_no_data
1346 //======================================================================================================================
1347
1348 mDNSlocal mDNSBool
1349 nsec_proves_wildcard_no_data(
1350 const mDNSu8 * const _Nonnull qname,
1351 const mDNSu16 qclass,
1352 const mDNSu16 qtype,
1353 const list_t * const _Nonnull nsecs,
1354 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_exact_match,
1355 const list_t * _Nullable * _Nonnull out_rrsigs_no_exact_match,
1356 const dnssec_nsec_t * _Nullable * _Nonnull out_nsec_no_matching_stype,
1357 const list_t * _Nullable * _Nonnull out_rrsigs_no_matching_stype){
1358
1359 mDNSBool no_exact_match = mDNSfalse;
1360 mDNSBool no_matching_stype = mDNSfalse;
1361
1362 for (list_node_t *nsec_node = list_get_first(nsecs); !list_has_ended(nsecs, nsec_node); nsec_node = list_next(nsec_node)) {
1363 const one_nsec_with_rrsigs_t * const one_nsec = (one_nsec_with_rrsigs_t *)nsec_node->data;
1364 // have NSEC record
1365 const dnssec_nsec_t * const dnssec_nsec = &one_nsec->nsec_record;
1366 const mDNSu8 * const prev = dnssec_nsec->exist_domain_name;
1367 const mDNSu8 * const next = dnssec_nsec->next_domain_name;
1368 mDNSs8 name_compare_result;
1369 mDNSBool last_nsec = compare_canonical_dns_name(prev, next) > 0;
1370
1371 // check if an NSEC RR proving that there is no exact match for <SNAME, SCLASS> exist
1372 while (!no_exact_match) {
1373 // prev < q_name
1374 name_compare_result = compare_canonical_dns_name(qname, prev);
1375 if (name_compare_result <= 0) {
1376 break;
1377 }
1378
1379 // q_name < next
1380 name_compare_result = compare_canonical_dns_name(next, qname);
1381 if (!last_nsec && name_compare_result <= 0) {
1382 break;
1383 }
1384
1385 *out_nsec_no_exact_match = dnssec_nsec;
1386 *out_rrsigs_no_exact_match = &one_nsec->rrsig_records;
1387 no_exact_match = mDNStrue;
1388 }
1389
1390 // check if an NSEC RR proving that there are no RRsets matching STYPE at the wildcard owner name that matched
1391 // <SNAME, SCLASS> via wildcard expansion, exists
1392 while (!no_matching_stype) {
1393 // with same SNAME
1394 mDNSu8 wildcard_name[256];
1395
1396 if (!DOMAIN_NAME_EQUALS(get_wildcard_name(qname, wildcard_name, sizeof(wildcard_name)), dnssec_nsec->exist_domain_name)) {
1397 break;
1398 }
1399
1400 // with same SCLASS
1401 if (qclass != dnssec_nsec->dnssec_rr.rr_class) {
1402 break;
1403 }
1404
1405 // does not contain the STYPE
1406 if (bit_map_contain_dns_type(dnssec_nsec->type_bit_maps, dnssec_nsec->type_bit_maps_length, qtype)) {
1407 break;
1408 }
1409
1410 *out_nsec_no_matching_stype = dnssec_nsec;
1411 *out_rrsigs_no_matching_stype = &one_nsec->rrsig_records;
1412 no_matching_stype = mDNStrue;
1413 }
1414
1415 if (no_exact_match && no_matching_stype) {
1416 break;
1417 }
1418 }
1419
1420 return no_exact_match && no_matching_stype;
1421 }
1422
1423 //======================================================================================================================
1424 // NSEC3 result validation
1425 //======================================================================================================================
1426
1427 mDNSlocal dnssec_validation_result_t
1428 nsec3_proves_closest_encloser(
1429 const mDNSu8 * const _Nonnull name,
1430 const list_t * const _Nonnull nsec3s,
1431 const mDNSu8 * const _Nonnull zone_name,
1432 mDNSu8 canonical_name[MAX_DOMAIN_NAME],
1433 const dnssec_nsec3_t * _Nullable * const _Nonnull out_nsec3_closest_encloser_proof,
1434 const list_t * _Nullable * const _Nonnull out_rrsig_closest_encloser_proof,
1435 const dnssec_nsec3_t * _Nullable * const _Nonnull out_nsec3_next_closer_proof,
1436 const list_t * _Nullable * const _Nonnull out_rrsig_next_closer_proof,
1437 const mDNSu8 * _Nullable * const _Nonnull out_closest_encloser_name,
1438 const mDNSu8 * _Nullable * const _Nonnull out_next_closer_name) {
1439
1440 dnssec_validation_result_t result = dnssec_validation_validating;
1441 const one_nsec3_with_rrsigs_t * const first_one_nsec3 = (one_nsec3_with_rrsigs_t *)list_get_first(nsec3s)->data;
1442 const dnssec_nsec3_t * const first_dnssec_nsec3 = &first_one_nsec3->nsec3_record;
1443 const mDNSu8 hash_algorithm = first_dnssec_nsec3->hash_algorithm;
1444 const mDNSu16 iterations = first_dnssec_nsec3->iterations;
1445 const mDNSu8 * const salt = first_dnssec_nsec3->salt;
1446 const mDNSu8 salt_length = first_dnssec_nsec3->salt_length;
1447 mDNSu8 checking_flag;
1448 mDNSu16 canonical_name_length;
1449 const mDNSu8 * sname;
1450 mDNSu16 sname_length;
1451 mDNSBool break_loop;
1452
1453 copy_canonical_name(canonical_name, name);
1454 canonical_name_length = DOMAIN_NAME_LENGTH(canonical_name);
1455
1456 sname = canonical_name;
1457 sname_length = canonical_name_length;
1458 checking_flag = mDNSfalse;
1459
1460 while (*sname != 0 && result == dnssec_validation_validating) {
1461 mDNSu8 * const hash_b32 = calculate_b32_hash_for_nsec3(sname, sname_length, hash_algorithm, salt, salt_length, iterations);
1462 require_action(hash_b32 != mDNSNULL, exit, result = dnssec_validation_no_memory);
1463 mDNSu8 hash_b32_length = strlen((char *)hash_b32);
1464 break_loop = mDNSfalse;
1465
1466 for (list_node_t *one_nsec3_node = list_get_first(nsec3s);
1467 !list_has_ended(nsec3s, one_nsec3_node) && !break_loop;
1468 one_nsec3_node = list_next(one_nsec3_node)) {
1469
1470 const one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)one_nsec3_node->data;
1471 const dnssec_nsec3_t * const dnssec_nsec3 = &one_nsec3->nsec3_record;
1472 const mDNSu8 * current = (mDNSu8 *)(dnssec_nsec3->dnssec_rr.name.c + 1);
1473 const mDNSu8 current_length = *(dnssec_nsec3->dnssec_rr.name.c);
1474 const mDNSu8 * next = (mDNSu8 *)(dnssec_nsec3->next_hashed_owner_name_b32);
1475 const mDNSu8 next_length = dnssec_nsec3->next_hashed_owner_name_b32_length;
1476 const mDNSBool last_nsec3 = compare_canonical_dns_label(current, current_length, next, next_length) > 0;
1477
1478 // ignore invalid NSEC3 record
1479 if (ignore_this_nsec3_record(dnssec_nsec3)) {
1480 continue;
1481 }
1482
1483 // If there is an NSEC3 RR in the response that covers SNAME
1484 if (compare_canonical_dns_label(current, current_length, hash_b32, hash_b32_length) < 0
1485 && (last_nsec3 || compare_canonical_dns_label(hash_b32, hash_b32_length, next, next_length) < 0)) { // SNAME is covered by this NSEC3 record.
1486 //, set the flag.
1487 checking_flag = mDNStrue;
1488 *out_nsec3_next_closer_proof = dnssec_nsec3;
1489 *out_rrsig_next_closer_proof = &one_nsec3->rrsig_records;
1490 *out_next_closer_name = sname;
1491 break_loop = mDNStrue;
1492 } else if (compare_canonical_dns_label(current, current_length, hash_b32, hash_b32_length) == 0) {
1493 // If there is a matching NSEC3 RR in the response,
1494 // and the flag was set,
1495 require_action_quiet(checking_flag, exit, result = dnssec_validation_bogus);
1496
1497 // and the nsec3 record comes from a proper zone,
1498 mDNSu8 subdomain = is_a_subdomain_of_b(sname, zone_name);
1499 require_action_quiet(subdomain, exit, result = dnssec_validation_nsec3_nsec3_not_from_the_zone);
1500
1501 // then this NEC3 proves closest encloser
1502 *out_nsec3_closest_encloser_proof = dnssec_nsec3;
1503 *out_rrsig_closest_encloser_proof = &one_nsec3->rrsig_records;
1504 *out_closest_encloser_name = sname;
1505 break_loop = mDNStrue;
1506 result = dnssec_validation_nsec3_provable_closest_encloser;
1507 }
1508 }
1509
1510 free(hash_b32);
1511 sname_length -= 1 + *sname;
1512 sname += 1 + *sname;
1513 if (!break_loop) {
1514 checking_flag = mDNSfalse;
1515 }
1516 }
1517
1518 exit:
1519 return result;
1520 }
1521
1522
1523 //======================================================================================================================
1524 // nsec3_contains_different_hash_iteration_salt
1525 //======================================================================================================================
1526
1527 mDNSlocal mDNSBool
1528 nsec3_contains_different_hash_iteration_salt(const list_t * const nsec3s) {
1529 if (list_empty(nsec3s)) {
1530 return mDNStrue;
1531 }
1532
1533 const one_nsec3_with_rrsigs_t * const first_one_nsec3 = (one_nsec3_with_rrsigs_t *)(list_get_first(nsec3s)->data);
1534 const dnssec_nsec3_t * const first_dnssec_nsec3 = &first_one_nsec3->nsec3_record;
1535
1536 for (list_node_t *one_nsec3_node = list_get_first(nsec3s);
1537 !list_has_ended(nsec3s, one_nsec3_node);
1538 one_nsec3_node = list_next(one_nsec3_node)) {
1539
1540 const one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)one_nsec3_node->data;
1541 const dnssec_nsec3_t * const dnssec_nsec3 = &one_nsec3->nsec3_record;
1542
1543 if (dnssec_nsec3->hash_algorithm != first_dnssec_nsec3->hash_algorithm
1544 || dnssec_nsec3->iterations != first_dnssec_nsec3->iterations
1545 || dnssec_nsec3->salt_length != first_dnssec_nsec3->salt_length
1546 || memcmp(dnssec_nsec3->salt, first_dnssec_nsec3->salt, dnssec_nsec3->salt_length) != 0) {
1547 return mDNStrue;
1548 }
1549 }
1550
1551 return mDNSfalse;
1552 }
1553
1554 //======================================================================================================================
1555 // ignore_this_nsec3_record
1556 //======================================================================================================================
1557
1558 mDNSlocal mDNSBool
1559 ignore_this_nsec3_record(const dnssec_nsec3_t * const _Nonnull dnssec_nsec3) {
1560 // ignore the NSEC3 with unknown hash type, right now we only support SHA1(1)
1561 if (dnssec_nsec3->hash_algorithm != 1) {
1562 return mDNStrue;
1563 }
1564
1565 mDNSu8 flags = dnssec_nsec3->flags;
1566 flags = (flags & (~1));
1567 // ignore the NSEC3 with any flag bits set except for the least significant bit, which is used as Opt-out option
1568 if (flags != 0) {
1569 return mDNStrue;
1570 }
1571
1572 return mDNSfalse;
1573 }
1574
1575 //======================================================================================================================
1576 // build_trust_from_ksk_to_zsk
1577 //======================================================================================================================
1578
1579 mDNSlocal dnssec_validation_result_t
1580 build_trust_from_ksk_to_zsk(
1581 const mDNSu32 request_id,
1582 const dnssec_zone_t * const _Nonnull zone,
1583 const list_t * const _Nonnull dnskeys,
1584 const list_t * const _Nonnull dses,
1585 const list_t * const _Nonnull rrsigs_covering_dnskey,
1586 dnssec_validator_node_t * _Nonnull children,
1587 const mDNSu8 child_size,
1588 dnssec_validator_node_t * _Nonnull parents,
1589 mDNSu8 * const _Nonnull out_parent_size) {
1590
1591 dnssec_validation_result_t result = dnssec_validation_invalid;
1592 dnssec_validation_result_t error;
1593 const mDNSu8 * const zone_name = zone->domain_name.c;
1594 const list_t * const dnskey_trust_anchors = zone->trust_anchor ? &zone->trust_anchor->dnskey_trust_anchors : mDNSNULL;
1595 const list_t * const ds_trust_anchors = zone->trust_anchor ? &zone->trust_anchor->ds_trust_anchors : mDNSNULL;
1596 mDNSu8 parent_size = 0;
1597
1598 for (mDNSu8 i = 0; i < child_size; i++) {
1599 dnssec_validator_node_t * child = &children[i];
1600 const list_t * const rrsigs = child->rrssigs_covering_it;
1601
1602 for (const list_node_t * rrsig_node = list_get_first(rrsigs); !list_has_ended(rrsigs, rrsig_node); rrsig_node = list_next(rrsig_node)) {
1603 const dnssec_rrsig_t * const dnssec_rrsig = (dnssec_rrsig_t *)rrsig_node->data;
1604 const mDNSu16 key_tag_from_rrsig = dnssec_rrsig->key_tag;
1605
1606 verify_action(dnssec_rrsig->type_covered == kDNSType_DNSKEY, continue);
1607
1608 const dnssec_dnskey_t * dnssec_dnskey = mDNSNULL;
1609 const dnssec_ds_t * dnssec_ds = mDNSNULL;
1610 dnssec_validator_node_t * parent = mDNSNULL;
1611 mDNSBool find_trust_anchor = mDNSfalse;
1612
1613 if (dnskey_trust_anchors != mDNSNULL && !list_empty(dnskey_trust_anchors)) {
1614 for (const list_node_t * dnskey_node = list_get_first(dnskey_trust_anchors);
1615 !list_has_ended(dnskey_trust_anchors, dnskey_node);
1616 dnskey_node = list_next(dnskey_node)) {
1617
1618 dnssec_dnskey = (dnssec_dnskey_t *)dnskey_node->data;
1619 const mDNSu16 key_tag_from_dnskey = dnssec_dnskey->key_tag;
1620 mDNSBool entry_point = (DNSKEY_FLAG_SECURITY_ENTRY_POINT & dnssec_dnskey->flags);
1621
1622 if (key_tag_from_rrsig != key_tag_from_dnskey || !entry_point) {
1623 dnssec_dnskey = mDNSNULL;
1624 continue;
1625 }
1626
1627 find_trust_anchor = mDNStrue;
1628 goto initialize_parent;
1629 }
1630 }
1631
1632 if (!find_trust_anchor && ds_trust_anchors != mDNSNULL && !list_empty(ds_trust_anchors)) {
1633 for (const list_node_t * dnskey_node = list_get_first(dnskeys);
1634 !list_has_ended(dnskeys, dnskey_node);
1635 dnskey_node = list_next(dnskey_node)) {
1636
1637 dnssec_dnskey = (dnssec_dnskey_t *)dnskey_node->data;
1638 const mDNSu16 key_tag_from_dnskey = dnssec_dnskey->key_tag;
1639 mDNSBool entry_point = (DNSKEY_FLAG_SECURITY_ENTRY_POINT & dnssec_dnskey->flags);
1640
1641 if (key_tag_from_rrsig != key_tag_from_dnskey || !entry_point) {
1642 dnssec_dnskey = mDNSNULL;
1643 continue;
1644 }
1645
1646 for (const list_node_t * ds_node = list_get_first(ds_trust_anchors);
1647 !list_has_ended(ds_trust_anchors, ds_node);
1648 ds_node = list_next(ds_node)) {
1649
1650 dnssec_ds = (dnssec_ds_t *)ds_node->data;
1651 const mDNSu16 key_tag_from_ds = dnssec_ds->key_tag;
1652
1653 if (key_tag_from_rrsig != key_tag_from_ds) {
1654 dnssec_ds = mDNSNULL;
1655 continue;
1656 }
1657
1658 find_trust_anchor = mDNStrue;
1659 goto initialize_parent;
1660 }
1661 }
1662 }
1663
1664 if (!find_trust_anchor) {
1665 for (const list_node_t * dnskey_node = list_get_first(dnskeys); !list_has_ended(dnskeys, dnskey_node); dnskey_node = list_next(dnskey_node)) {
1666 dnssec_dnskey = (dnssec_dnskey_t *)dnskey_node->data;
1667 const mDNSu16 key_tag_from_dnskey = dnssec_dnskey->key_tag;
1668 mDNSBool entry_point = (DNSKEY_FLAG_SECURITY_ENTRY_POINT & dnssec_dnskey->flags);
1669
1670 if (key_tag_from_rrsig != key_tag_from_dnskey || !entry_point) {
1671 dnssec_dnskey = mDNSNULL;
1672 continue;
1673 }
1674
1675 for (const list_node_t * ds_node = list_get_first(dses);
1676 !list_has_ended(dses, ds_node);
1677 ds_node = list_next(ds_node)) {
1678
1679 dnssec_ds = (dnssec_ds_t *)ds_node->data;
1680 const mDNSu16 key_tag_from_ds = dnssec_ds->key_tag;
1681
1682 if (key_tag_from_rrsig != key_tag_from_ds) {
1683 dnssec_ds = mDNSNULL;
1684 continue;
1685 }
1686
1687 goto initialize_parent;
1688 }
1689 }
1690 }
1691
1692 if (dnssec_dnskey == mDNSNULL && dnssec_ds == mDNSNULL) {
1693 continue;
1694 }
1695
1696 initialize_parent:
1697 parent = &parents[parent_size];
1698 parent_size++;
1699 uninitialize_validator_node(parent);
1700 initialize_validator_node_with_ksk(parent, dnssec_dnskey, dnssec_rrsig, dnssec_ds, zone_name,
1701 dses, rrsigs_covering_dnskey, find_trust_anchor);
1702
1703 break;
1704 }
1705 }
1706
1707 require_action_quiet(parent_size == child_size, exit, result = dnssec_validation_no_matching_key_tag);
1708
1709 error = validate_validator_node(parents, parent_size);
1710 require_action_quiet(error == dnssec_validation_valid, exit, result = error);
1711
1712 error = validate_validator_path_between_parents_and_children(request_id, children, parents, &parent_size);
1713 require_action_quiet(error == dnssec_validation_valid, exit, result = error);
1714
1715 dedup_validator_with_the_same_siblings(parents, &parent_size);
1716
1717 *out_parent_size = parent_size;
1718
1719 result = dnssec_validation_valid;
1720
1721 exit:
1722 return result;
1723 }
1724
1725 //======================================================================================================================
1726 // build_trust_from_zsk
1727 //======================================================================================================================
1728
1729 mDNSlocal dnssec_validation_result_t
1730 build_trust_from_zsk(
1731 const mDNSu32 request_id,
1732 const dnssec_zone_t * const _Nonnull zone,
1733 const list_t * const _Nonnull dnskeys,
1734 const list_t * const _Nonnull rrsigs_covering_dnskeys,
1735 dnssec_validator_node_t * _Nonnull children,
1736 const mDNSu8 child_size,
1737 dnssec_validator_node_t * _Nonnull parents,
1738 mDNSu8 * const _Nonnull out_parent_size) {
1739
1740 dnssec_validation_result_t result = dnssec_validation_invalid;
1741 dnssec_validation_result_t error;
1742 const mDNSu8 * const zone_name = zone->domain_name.c;
1743 const trust_anchors_t * const trust_anchor = zone->trust_anchor;
1744 const list_t * const dnskey_trust_anchors = &trust_anchor->dnskey_trust_anchors;
1745 mDNSBool contain_trust_anchor = trust_anchor_contains_dnskey(zone->trust_anchor);
1746 mDNSu8 parent_size = 0;
1747
1748 for (mDNSu8 i = 0; i < child_size; i++) {
1749 dnssec_validator_node_t * child = &children[i];
1750 const list_t * const rrsigs = child->rrssigs_covering_it;
1751
1752 for (const list_node_t * rrsig_node = list_get_first(rrsigs); !list_has_ended(rrsigs, rrsig_node); rrsig_node = list_next(rrsig_node)) {
1753 const dnssec_rrsig_t * const dnssec_rrsig = (dnssec_rrsig_t *)rrsig_node->data;
1754 const mDNSu16 key_tag_from_rrsig = dnssec_rrsig->key_tag;
1755
1756 if (contain_trust_anchor) {
1757 // has saved dnskey as trust anchor
1758 for (const list_node_t * dnskey_node = list_get_first(dnskey_trust_anchors);
1759 !list_has_ended(dnskey_trust_anchors, dnskey_node);
1760 dnskey_node = list_next(dnskey_node)) {
1761
1762 const dnssec_dnskey_t * const dnssec_dnskey = (dnssec_dnskey_t *)dnskey_node->data;
1763 const mDNSu16 key_tag_from_dnskey = dnssec_dnskey->key_tag;
1764
1765 if (key_tag_from_rrsig != key_tag_from_dnskey) {
1766 continue;
1767 }
1768
1769 dnssec_validator_node_t * const parent = &parents[parent_size];
1770 parent_size++;
1771 uninitialize_validator_node(parent);
1772 initialize_validator_node_with_zsk(parent, dnssec_dnskey, dnssec_rrsig, zone_name, dnskeys, rrsigs_covering_dnskeys, mDNStrue);
1773
1774 goto find_matching_parent;
1775 }
1776 } else {
1777 for (const list_node_t * dnskey_node = list_get_first(dnskeys);
1778 !list_has_ended(dnskeys, dnskey_node);
1779 dnskey_node = list_next(dnskey_node)) {
1780
1781 const dnssec_dnskey_t * const dnssec_dnskey = (dnssec_dnskey_t *)dnskey_node->data;
1782 const mDNSu16 key_tag_from_dnskey = dnssec_dnskey->key_tag;
1783
1784 if (key_tag_from_rrsig != key_tag_from_dnskey) {
1785 continue;
1786 }
1787
1788 dnssec_validator_node_t * const parent = &parents[parent_size];
1789 parent_size++;
1790 uninitialize_validator_node(parent);
1791 initialize_validator_node_with_zsk(parent, dnssec_dnskey, dnssec_rrsig, zone_name, dnskeys, rrsigs_covering_dnskeys, mDNSfalse);
1792
1793 goto find_matching_parent;
1794 }
1795 }
1796 }
1797 find_matching_parent:
1798 continue;
1799 }
1800 if (contain_trust_anchor && parent_size != child_size) {
1801 // trust anchor cannot be used to verify this response, now going back to records retrieval
1802 result = dnssec_validation_trust_anchor_does_not_macth;
1803 goto exit;
1804 }
1805 require_action_quiet(parent_size == child_size, exit, result = dnssec_validation_no_matching_key_tag);
1806
1807 error = validate_validator_node(parents, parent_size);
1808 require_action_quiet(error == dnssec_validation_valid, exit, result = error);
1809
1810 error = validate_validator_path_between_parents_and_children(request_id, children, parents, &parent_size);
1811 require_action_quiet(error == dnssec_validation_valid, exit, result = error);
1812
1813 dedup_validator_with_the_same_siblings(parents, &parent_size);
1814
1815 *out_parent_size = parent_size;
1816
1817 result = dnssec_validation_valid;
1818
1819 exit:
1820 return result;
1821 }
1822
1823 //======================================================================================================================
1824 // initialize_validator_node_with_rr
1825 //======================================================================================================================
1826
1827 mDNSlocal void
1828 initialize_validator_node_with_rr(
1829 dnssec_validator_node_t * const _Nonnull node,
1830 const mDNSu8 * const _Nonnull name,
1831 const list_t * const _Nonnull siblings,
1832 const list_t * const _Nonnull rrsigs_covering_it, // list_t<dnssec_rrsig_t>
1833 response_type_t response_type) { // list_t<dnssec_original_t>
1834
1835 node->type = rr_validator;
1836 node->u.rr.rr_response_type = response_type;
1837 node->name = name;
1838 node->siblings = siblings;
1839 node->rrssigs_covering_it = rrsigs_covering_it;
1840 node->trusted = mDNSfalse;
1841 }
1842
1843 //======================================================================================================================
1844 // initialize_validator_node_with_nsec
1845 //======================================================================================================================
1846
1847 mDNSlocal void
1848 initialize_validator_node_with_nsec(
1849 dnssec_validator_node_t * const _Nonnull node,
1850 const dnssec_nsec_t * _Nullable nsec,
1851 const mDNSu8 * const _Nonnull name,
1852 const list_t * const _Nonnull rrsig_covering_it ) { // list_t<dnssec_rrsig_t>
1853
1854 node->type = nsec_validator;
1855 node->u.nsec.nsec = nsec;
1856 node->name = name;
1857 node->siblings = mDNSNULL;
1858 node->rrssigs_covering_it = rrsig_covering_it;
1859 node->trusted = mDNSfalse;
1860 }
1861
1862 //======================================================================================================================
1863 // initialize_validator_node_with_nsec3
1864 //======================================================================================================================
1865
1866 mDNSlocal void
1867 initialize_validator_node_with_nsec3(
1868 dnssec_validator_node_t * const _Nonnull node,
1869 const dnssec_nsec3_t * _Nullable nsec3,
1870 const mDNSu8 * const _Nonnull name,
1871 const list_t * const _Nonnull rrsig_covering_it) { // list_t<dnssec_rrsig_t>
1872
1873 node->type = nsec3_validator;
1874 node->u.nsec3.nsec3 = nsec3;
1875 node->name = name;
1876 node->siblings = mDNSNULL;
1877 node->rrssigs_covering_it = rrsig_covering_it;
1878 node->trusted = mDNSfalse;
1879 }
1880
1881 //======================================================================================================================
1882 // initialize_validator_node_with_zsk
1883 //======================================================================================================================
1884
1885 mDNSlocal void
1886 initialize_validator_node_with_zsk(
1887 dnssec_validator_node_t * const _Nonnull node,
1888 const dnssec_dnskey_t * const _Nonnull key,
1889 const dnssec_rrsig_t * const _Nonnull sig,
1890 const mDNSu8 * const _Nonnull name,
1891 const list_t * const _Nonnull siblings, // list<dnssec_dnskey_t>
1892 const list_t * const _Nonnull rrsig_covering_it, // list_t<dnssec_rrsig_t>
1893 mDNSBool trusted) {
1894
1895 node->type = zsk_validator;
1896 node->u.zsk.key = key;
1897 node->u.zsk.sig = sig;
1898 node->name = name;
1899 node->siblings = siblings;
1900 node->rrssigs_covering_it = rrsig_covering_it;
1901 node->trusted = trusted;
1902 }
1903
1904 //======================================================================================================================
1905 // initialize_validator_node_with_ksk
1906 //======================================================================================================================
1907
1908 mDNSlocal void
1909 initialize_validator_node_with_ksk(
1910 dnssec_validator_node_t * const _Nonnull node,
1911 const dnssec_dnskey_t * const _Nonnull key,
1912 const dnssec_rrsig_t * const _Nonnull sig,
1913 const dnssec_ds_t * const _Nullable ds,
1914 const mDNSu8 * const _Nonnull name,
1915 const list_t * const _Nonnull siblings, // list<dnssec_ds_t>
1916 const list_t * const _Nonnull rrsig_covering_it, // list_t<dnssec_rrsig_t>
1917 mDNSBool trusted) {
1918
1919 node->type = ksk_validator;
1920 node->u.ksk.key = key;
1921 node->u.ksk.sig = sig;
1922 node->u.ksk.ds = ds;
1923 node->name = name;
1924 node->siblings = siblings;
1925 node->rrssigs_covering_it = rrsig_covering_it;
1926 node->trusted = trusted;
1927 }
1928
1929 //======================================================================================================================
1930 // uninitialize_validator_node
1931 //======================================================================================================================
1932
1933 mDNSlocal void
1934 uninitialize_validator_node(dnssec_validator_node_t * const _Nonnull node) {
1935 bzero(node, sizeof(dnssec_validator_node_t));
1936 }
1937
1938 //======================================================================================================================
1939 // is_validator_node_valid
1940 //======================================================================================================================
1941
1942 mDNSlocal dnssec_validation_result_t
1943 validate_validator_node(const dnssec_validator_node_t * const _Nonnull nodes, const mDNSu8 nodes_count) {
1944
1945 dnssec_validation_result_t result = dnssec_validation_valid;
1946
1947 for (mDNSu8 i = 0; i < nodes_count; i++) {
1948 const dnssec_validator_node_t * const node = &nodes[i];
1949
1950 switch (node->type) {
1951 case rr_validator:
1952 break;
1953 case nsec_validator:
1954 result = validate_nsec(node->u.nsec.nsec);
1955 require_quiet(result == dnssec_validation_valid, exit);
1956 break;
1957 case nsec3_validator:
1958 result = validate_nsec3(node->u.nsec3.nsec3);
1959 require_quiet(result == dnssec_validation_valid, exit);
1960 break;
1961 case zsk_validator:
1962 result = validate_dnskey(node->u.zsk.key, mDNSfalse);
1963 require_quiet(result == dnssec_validation_valid, exit);
1964
1965 result = validate_rrsig(node->u.zsk.sig);
1966 require_quiet(result == dnssec_validation_valid, exit);
1967
1968 require_action(node->u.zsk.key->algorithm == node->u.zsk.sig->algorithm, exit,
1969 result = dnssec_validation_algorithm_number_not_equal);
1970 break;
1971 case ksk_validator:
1972 result = validate_dnskey(node->u.ksk.key, mDNStrue);
1973 require_quiet(result == dnssec_validation_valid, exit);
1974
1975 result = validate_rrsig(node->u.ksk.sig);
1976 require_quiet(result == dnssec_validation_valid, exit);
1977
1978 if (node->u.ksk.ds != mDNSNULL) {
1979 result = validate_ds(node->u.ksk.ds);
1980 require_quiet(result == dnssec_validation_valid, exit);
1981 } else{
1982 require_action_quiet(node->trusted, exit, result = dnssec_validation_invalid_internal_state);
1983 }
1984
1985 if (node->u.ksk.ds != mDNSNULL) {
1986 require_action(node->u.ksk.key->algorithm == node->u.ksk.ds->algorithm, exit,
1987 result = dnssec_validation_algorithm_number_not_equal);
1988 }
1989
1990 require_action(node->u.ksk.key->algorithm == node->u.ksk.sig->algorithm, exit,
1991 result = dnssec_validation_algorithm_number_not_equal);
1992
1993 if (node->u.ksk.ds != mDNSNULL) {
1994 result = check_if_ds_ksk_matches(node->u.ksk.ds, node->u.ksk.key);
1995 require_quiet(result == dnssec_validation_valid, exit);
1996 }
1997 break;
1998 default:
1999 result = dnssec_validation_invalid_internal_state;
2000 break;
2001 }
2002 }
2003
2004 exit:
2005 return result;
2006 }
2007
2008 //======================================================================================================================
2009 // validate_validator_path_between_parents_and_children
2010 //======================================================================================================================
2011
2012 mDNSlocal dnssec_validation_result_t
2013 validate_validator_path_between_parents_and_children(
2014 const mDNSu32 request_id,
2015 dnssec_validator_node_t * _Nonnull children,
2016 dnssec_validator_node_t * _Nonnull parents,
2017 mDNSu8 * const _Nonnull out_parent_size) {
2018
2019 dnssec_validation_result_t result;
2020 dnssec_validation_result_t error;
2021 mDNSu8 parent_size = *out_parent_size;
2022
2023 require_action_quiet(parent_size != 0, exit, result = dnssec_validation_invalid_internal_state);
2024
2025 for (mDNSu8 i = 0; i < parent_size; i++) {
2026 const dnssec_validator_node_t * const child = &children[i];
2027 const dnssec_validator_node_t * const parent = &parents[i];
2028
2029 error = validate_validator_path(request_id, child, parent);
2030 require_action_quiet(error == dnssec_validation_valid, exit, result = error);
2031
2032 if (parent->type == ksk_validator) {
2033 const dnssec_dnskey_t * const ksk = parent->u.ksk.key;
2034 const dnssec_ds_t * const ds = parent->u.ksk.ds;
2035
2036 error = check_trust_validator_node(parent);
2037 if (error == dnssec_validation_trusted) {
2038 if (ds != mDNSNULL) {
2039 // ds trust anchor
2040 log_default("[R%u] " PRI_DM_NAME ": DS (digest_type=%u, tag=%u, trust_anchor) -----> " PRI_DM_NAME ": DNSKEY (KSK, alg=%u, tag=%u, length=%u)",
2041 request_id, DM_NAME_PARAM(&ds->dnssec_rr.name), ds->digest_type, ds->key_tag,
2042 DM_NAME_PARAM(&ksk->dnssec_rr.name), ksk->algorithm, ksk->key_tag, ksk->public_key_length);
2043 } else {
2044 // dnskey trust anchor
2045 log_default("[R%u] " PRI_DM_NAME ": DNSKEY (KSK, alg=%u, tag=%u, length=%u, trust_anchor)",
2046 request_id,
2047 DM_NAME_PARAM(&ksk->dnssec_rr.name), ksk->algorithm, ksk->key_tag, ksk->public_key_length);
2048 }
2049
2050 // parent node is trusted by the policy, no need to verify it
2051 if (i < parent_size - 1) {
2052 children[i] = children[i + 1];
2053 parents[i] = parents[i + 1];
2054 i--;
2055 }
2056 parent_size--;
2057 } else {
2058 log_default("[R%u] " PRI_DM_NAME ": DS (digest_type=%u, tag=%u) -----> " PRI_DM_NAME ": DNSKEY (KSK, alg=%u, tag=%u, length=%u)",
2059 request_id, DM_NAME_PARAM(&ds->dnssec_rr.name), ds->digest_type, ds->key_tag,
2060 DM_NAME_PARAM(&ksk->dnssec_rr.name), ksk->algorithm, ksk->key_tag, ksk->public_key_length);
2061 }
2062 }
2063 }
2064
2065 *out_parent_size = parent_size;
2066 result = dnssec_validation_valid;
2067
2068 exit:
2069 return result;
2070 }
2071
2072 //======================================================================================================================
2073 // validate_validator_path
2074 //======================================================================================================================
2075
2076 mDNSlocal dnssec_validation_result_t
2077 validate_validator_path(
2078 const mDNSu32 request_id,
2079 const dnssec_validator_node_t * const _Nonnull child,
2080 const dnssec_validator_node_t * const _Nonnull parent) {
2081
2082 dnssec_validation_result_t result = dnssec_validation_valid;
2083
2084 if (child->type == zsk_validator && parent->type == ksk_validator) {
2085 result = validate_path_from_ksk_to_zsk(request_id, parent, child->siblings);
2086 } else if (child->type == ksk_validator && parent->type == zsk_validator) {
2087 result = validate_path_from_zsk_to_ds(request_id, parent, child->siblings);
2088 } else if (child->type == rr_validator && parent->type == zsk_validator) {
2089 result = validate_path_from_zsk_to_rr(request_id, parent, child->siblings, child->u.rr.rr_response_type);
2090 } else if (child->type == nsec_validator && parent->type == zsk_validator) {
2091 result = validate_path_from_zsk_to_nsec(request_id, parent, child);
2092 } else if (child->type == nsec3_validator && parent->type == zsk_validator) {
2093 result = validate_path_from_zsk_to_nsec3(request_id, parent, child);
2094 } else {
2095 result = dnssec_validation_path_invalid_node_type;
2096 }
2097
2098 return result;
2099 }
2100
2101
2102 //======================================================================================================================
2103 // check_trust_validator_node
2104 //======================================================================================================================
2105
2106 mDNSlocal dnssec_validation_result_t
2107 check_trust_validator_node(const dnssec_validator_node_t * const _Nonnull node) {
2108 return node->trusted ? dnssec_validation_trusted : dnssec_validation_not_trusted;
2109 }
2110
2111 //======================================================================================================================
2112 // dedup_validator_with_the_same_siblings
2113 //======================================================================================================================
2114
2115 mDNSlocal void
2116 dedup_validator_with_the_same_siblings(
2117 dnssec_validator_node_t * _Nonnull parents,
2118 mDNSu8 * const _Nonnull out_parent_size) {
2119
2120 const dnssec_validator_node_t * temp_parents[4] = {mDNSNULL};
2121 mDNSu8 temp_parent_size = 0;
2122 mDNSu8 parent_size = *out_parent_size;
2123
2124 for (mDNSu8 i = 0; i < parent_size; i++) {
2125 const dnssec_validator_node_t * const parent = &parents[i];
2126 mDNSBool duplicate = mDNSfalse;
2127
2128 for (mDNSu8 j = 0; j < temp_parent_size; j++) {
2129 const dnssec_validator_node_t * const parent_nodup = temp_parents[j];
2130 // if two nodes to be verified have the same siblings to verify, they are the duplicates, since RRSIG signs the entire siblings
2131 if (parent_nodup->siblings == parent->siblings) {
2132 duplicate = mDNStrue;
2133 }
2134 }
2135
2136 if (!duplicate) {
2137 temp_parents[temp_parent_size] = parent;
2138 temp_parent_size++;
2139 }
2140 }
2141
2142 for (mDNSu8 i = 0; i < temp_parent_size; i++) {
2143 parents[i] = *temp_parents[i];
2144 }
2145 parent_size = temp_parent_size;
2146 *out_parent_size = parent_size;
2147 }
2148
2149 //======================================================================================================================
2150 // dedup_validator_with_the_same_siblings
2151 //======================================================================================================================
2152
2153 mDNSlocal void __unused
2154 print_ds_validation_progress(const dnssec_validator_node_t * const _Nonnull nodes, const mDNSu8 nodes_count) {
2155 for (mDNSu8 i = 0; i < nodes_count; i++) {
2156 const dnssec_validator_node_t * const node = &nodes[i];
2157 verify_action(node->type == ksk_validator,
2158 log_error("validator type is not Key Signing Key; type=%u", node->type); continue);
2159
2160 const dnssec_dnskey_t * const ksk = node->u.ksk.key;
2161 const dnssec_ds_t * const ds = node->u.ksk.ds;
2162
2163 log_default(PRI_DM_NAME ": DS (digest_type=%u, tag=%u) ----->" PRI_DM_NAME ": DNSKEY (KSK, alg=%u, tag=%u, length=%u)",
2164 DM_NAME_PARAM(&ds->dnssec_rr.name), ds->digest_type, ds->key_tag,
2165 DM_NAME_PARAM(&ksk->dnssec_rr.name), ksk->algorithm, ksk->key_tag, ksk->public_key_length);
2166
2167 }
2168 }
2169
2170 //======================================================================================================================
2171 // validate_zone_records_type
2172 //======================================================================================================================
2173
2174 mDNSlocal dnssec_validation_result_t
2175 validate_zone_records_type(const dnssec_zone_t * const _Nonnull zone) {
2176 dnssec_validation_result_t result = dnssec_validation_valid;
2177
2178 if (zone->dnskey_request_started && zone->ds_request_started) {
2179 // the most common case where zone does not have any trust anchor.
2180 require_action_quiet(zone->dses_with_rrsig.type == original_response, exit, result = dnssec_validation_non_dnskey_ds_record_chain);
2181 } else if (!zone->dnskey_request_started && zone->ds_request_started) {
2182 // This is impossible because if dnskey request is not started that means we have trust anchor for DNSKEY, and there
2183 // is no need to send DS query, thus ds_request_started could not be true
2184 result = dnssec_validation_invalid_internal_state;
2185 goto exit;
2186 } else if (zone->dnskey_request_started && !zone->ds_request_started) {
2187 // It means the system has DS trust anchor installed, thus there is no need to query for DS record, only DNSKEY
2188 // record is required, and we must have DS trust anchor
2189 require_action_quiet(zone->trust_anchor != mDNSNULL && !list_empty(&zone->trust_anchor->ds_trust_anchors), exit, result = dnssec_validation_invalid_internal_state);
2190 } else { // !zone->dnskey_request_started && !zone->ds_request_started
2191 // The system has DNSKEY trust anchor, and there is no need to query for DNSKEY or DS record at all.
2192 // we must have DNSKEY trust anchor
2193 require_action_quiet(zone->trust_anchor != mDNSNULL && !list_empty(&zone->trust_anchor->dnskey_trust_anchors), exit, result = dnssec_validation_invalid_internal_state);
2194 }
2195
2196 exit:
2197 return result;
2198 }
2199
2200 //======================================================================================================================
2201 // validate_ds
2202 //======================================================================================================================
2203
2204 mDNSlocal dnssec_validation_result_t
2205 validate_ds(const dnssec_ds_t * const _Nonnull ds) {
2206 dnssec_validation_result_t result = dnssec_validation_valid;
2207 mDNSs16 digest_priority;
2208 mDNSs16 algorithm_priority;
2209 // TODO: print dnssec_ds_t when failing to pass validation
2210
2211 // check digest type
2212 digest_priority = get_priority_of_ds_digest(ds->digest_type);
2213 require_action(digest_priority != -1, exit, result = dnssec_validation_ds_digest_not_supported;
2214 log_default("Unsupported or invalid DS digest type; digest_type=%u", ds->digest_type));
2215
2216 // check algorithm type
2217 algorithm_priority = get_priority_of_dnskey_algorithm(ds->algorithm);
2218 require_action(algorithm_priority != -1, exit, result = dnssec_validation_dnskey_algorithm_not_supported;
2219 log_default("Unsupported or invalid DNSKEY algorithm type; algorithm=%u", ds->algorithm));
2220 exit:
2221 return result;
2222 }
2223
2224 //======================================================================================================================
2225 // validate_dnskey
2226 //======================================================================================================================
2227
2228 mDNSlocal dnssec_validation_result_t
2229 validate_dnskey(const dnssec_dnskey_t * const _Nonnull dnskey, mDNSBool security_entry_point) {
2230 dnssec_validation_result_t result = dnssec_validation_valid;
2231 mDNSs16 algorithm_priority;
2232
2233 // check zone key flag
2234 require_action((dnskey->flags & DNSKEY_FLAG_ZONE_KEY) != 0, exit, result = dnssec_validation_dnskey_invalid_flags;
2235 log_default("Not a DNSSEC DNSKEY in DNSKEY; flags=%x", dnskey->flags));
2236
2237 // check the security entry point flag
2238 require_action(!security_entry_point || (dnskey->flags & DNSKEY_FLAG_SECURITY_ENTRY_POINT) != 0, exit,
2239 result = dnssec_validation_dnskey_invalid_flags);
2240
2241 // check protocol
2242 require_action(dnskey->protocol == 3, exit, result = dnssec_validation_dnskey_wrong_protocol;
2243 log_default("Not a DNSSEC Protocol in DNSKEY; protocol=%u", dnskey->protocol));
2244
2245 // check DNSKEY algorithm
2246 algorithm_priority = get_priority_of_dnskey_algorithm(dnskey->algorithm);
2247 require_action(algorithm_priority != -1, exit, result = dnssec_validation_dnskey_algorithm_not_supported;
2248 log_default("Unsupported or invalid DNSKEY algorithm type in DNSKEY; algorithm=%u", dnskey->algorithm));
2249
2250 exit:
2251 return result;
2252 }
2253
2254 //======================================================================================================================
2255 // validate_rrsig
2256 //======================================================================================================================
2257
2258 mDNSlocal dnssec_validation_result_t
2259 validate_rrsig(const dnssec_rrsig_t * const _Nonnull rrsig) {
2260 dnssec_validation_result_t result = dnssec_validation_valid;
2261 mDNSs16 algorithm_priority;
2262 int64_t now;
2263 mDNSu32 now_u32;
2264 // TODO: print dnssec_rrsig_t when failing to pass validation
2265
2266 // check DNSKEY algorithm
2267 algorithm_priority = get_priority_of_dnskey_algorithm(rrsig->algorithm);
2268 require_action(algorithm_priority != -1, exit, result = dnssec_validation_dnskey_algorithm_not_supported;
2269 log_default("Unsupported or invalid DNSKEY algorithm type in RRSIG; algorithm=%u", rrsig->algorithm));
2270
2271 // TODO: check the label field for RRSIG
2272
2273 // check inception and expiration time
2274 now = time(mDNSNULL);
2275 require_action(now <= UINT32_MAX, exit, result = dnssec_validation_invalid_internal_state;
2276 log_fault("the value of time(NULL) is now greater than UINT32_MAX"));
2277
2278 now_u32 = (mDNSu32)now;
2279 require_action(now_u32 >= rrsig->signature_inception, exit, result = dnssec_validation_rrsig_use_before_inception;
2280 log_default("RRSIG incpetion time is greater than the current time; inception_time=%u, now=%d", rrsig->signature_inception, now_u32));
2281
2282 require_action(now_u32 <= rrsig->signature_expiration, exit, result = dnssec_validation_rrsig_use_after_expiration;
2283 log_default("RRSIG expiration time is less than the current time; expiration_time=%u, now=%d", rrsig->signature_expiration, now_u32));
2284
2285 exit:
2286 return result;
2287 }
2288
2289 //======================================================================================================================
2290 // validate_nsec
2291 //======================================================================================================================
2292
2293 mDNSlocal dnssec_validation_result_t
2294 validate_nsec(const dnssec_nsec_t * const _Nonnull nsec) {
2295 (void) nsec;
2296
2297 return dnssec_validation_valid;
2298 }
2299
2300 //======================================================================================================================
2301 // validate_nsec3
2302 //======================================================================================================================
2303
2304 mDNSlocal dnssec_validation_result_t
2305 validate_nsec3(const dnssec_nsec3_t * const _Nonnull nsec3) {
2306 dnssec_validation_result_t result = dnssec_validation_valid;
2307 // check if hash algorithm is supported
2308 switch (nsec3->hash_algorithm) {
2309 case 1: // only SHA-1 is supported
2310 break;
2311 default:
2312 result = dnssec_validation_nsec3_unsupported_hash_algorithm;
2313 goto exit;
2314 }
2315
2316 // check flags, only Opt-Out flag is defined, all undefined flags should be zero
2317 require_action((nsec3->flags & (~NSEC3_FLAG_SET)) == 0, exit, result = dnssec_validation_nsec3_unsupported_flag);
2318
2319 exit:
2320 return result;
2321 }
2322
2323 //======================================================================================================================
2324 // check_if_ds_ksk_matches
2325 //======================================================================================================================
2326
2327 mDNSlocal dnssec_validation_result_t
2328 check_if_ds_ksk_matches(const dnssec_ds_t * const _Nonnull ds, const dnssec_dnskey_t * const _Nonnull ksk) {
2329 // reconstruct the data that will be hashed
2330 dnssec_validation_result_t result = dnssec_validation_valid;
2331 mDNSBool matches;
2332 const mDNSu8 * const owner_name = ksk->dnssec_rr.name.c;
2333 const mDNSu16 owner_name_length = DOMAIN_NAME_LENGTH(owner_name);
2334 const mDNSu8 * const dnskey_rdata = ksk->dnssec_rr.rdata;
2335 const mDNSu16 rdata_length = ksk->dnssec_rr.rdata_length;
2336 mDNSu8 digest_buffer[MAX_HASH_OUTPUT_SIZE];
2337 mDNSu32 digest_size;
2338 digest_type_t digest_type;
2339 const mDNSu32 data_to_be_hashed_length = owner_name_length + rdata_length;
2340 mDNSu8 * const data_to_be_hashed = malloc(data_to_be_hashed_length);
2341 require_action(data_to_be_hashed != mDNSNULL, exit, result = dnssec_validation_no_memory);
2342
2343 memcpy(data_to_be_hashed, owner_name, owner_name_length);
2344 memcpy(data_to_be_hashed + owner_name_length, dnskey_rdata, rdata_length);
2345
2346 switch (ds->digest_type) {
2347 case DS_DIGEST_SHA_1:
2348 digest_type = DIGEST_SHA_1;
2349 break;
2350 case DS_DIGEST_SHA_256:
2351 digest_type = DIGEST_SHA_256;
2352 break;
2353 case DS_DIGEST_SHA_384:
2354 digest_type = DIGEST_SHA_384;
2355 break;
2356 default:
2357 result = dnssec_validation_ds_digest_not_supported;
2358 goto exit;
2359 }
2360 digest_size = get_digest_length_for_ds_digest_type(ds->digest_type);
2361 mDNSBool calculated = calculate_digest_for_data(data_to_be_hashed, data_to_be_hashed_length, digest_type, digest_buffer, sizeof(digest_buffer));
2362 require_action_quiet(calculated, exit, result = dnssec_validation_invalid_internal_state);
2363 require_action(digest_size == ds->digest_length, exit, result = dnssec_validation_bogus);
2364
2365 matches = (memcmp(digest_buffer, ds->digest, digest_size) == 0);
2366
2367 require_action(matches, exit, result = dnssec_validation_bogus);
2368
2369 exit:
2370 if (data_to_be_hashed != mDNSNULL) {
2371 free(data_to_be_hashed);
2372 }
2373 return result;
2374 }
2375
2376 mDNSlocal dnssec_validation_result_t
2377 validate_path_from_zsk_to_rr(
2378 const mDNSu32 request_id,
2379 const dnssec_validator_node_t * const _Nonnull parent,
2380 const list_t * const _Nonnull originals /* list_t<dnssec_original_t> or list_t<dnssec_cname_t> */,
2381 response_type_t response_type) {
2382
2383 dnssec_validation_result_t result = dnssec_validation_valid;
2384 mDNSu8 * signed_data = mDNSNULL;
2385 mDNSu32 signed_data_length;
2386 mDNSBool is_signed_data_valid;
2387
2388 result = check_rrsig_validity_with_rrs(parent->u.zsk.sig, originals, response_type, kDNSQType_ANY);
2389 require_action(result == dnssec_validation_valid, exit, log_default("RRSIG is not valid for validation"));
2390
2391 signed_data = reconstruct_signed_data_with_rrs(originals, parent->u.zsk.sig, response_type, kDNSQType_ANY, &signed_data_length);
2392 require_action(signed_data != mDNSNULL, exit, result = dnssec_validation_no_memory;
2393 log_default("No enough memory to allocate for signed data;"));
2394
2395 is_signed_data_valid = validate_signed_data_with_rrsig_and_dnskey(request_id, signed_data, signed_data_length, parent->u.zsk.sig, parent->u.zsk.key);
2396
2397 result = is_signed_data_valid ? dnssec_validation_valid : dnssec_validation_invalid;
2398
2399 exit:
2400 if (signed_data != mDNSNULL) {
2401 free(signed_data);
2402 signed_data = mDNSNULL;
2403 }
2404 return result;
2405 }
2406
2407 mDNSlocal dnssec_validation_result_t
2408 validate_path_from_ksk_to_zsk(
2409 const mDNSu32 request_id,
2410 const dnssec_validator_node_t * const _Nonnull parent,
2411 const list_t * const _Nonnull zsks /* list_t<dnssec_dnskey_t> */) {
2412
2413 dnssec_validation_result_t result = dnssec_validation_valid;
2414 mDNSu8 * signed_data = mDNSNULL;
2415 mDNSu32 signed_data_length;
2416 mDNSBool is_signed_data_valid;
2417
2418 // TODO: original_response could be nsec nsec3
2419 result = check_rrsig_validity_with_rrs(parent->u.ksk.sig, zsks, original_response, kDNSType_DNSKEY);
2420 require_quiet(result == dnssec_validation_valid, exit);
2421
2422 signed_data = reconstruct_signed_data_with_rrs(zsks, parent->u.ksk.sig, original_response, kDNSType_DNSKEY, &signed_data_length);
2423 require_action(signed_data != mDNSNULL, exit, result = dnssec_validation_no_memory;
2424 log_default("No enough memory to allocate for signed data;"));
2425
2426 is_signed_data_valid = validate_signed_data_with_rrsig_and_dnskey(request_id, signed_data, signed_data_length, parent->u.ksk.sig, parent->u.ksk.key);
2427 result = is_signed_data_valid ? dnssec_validation_valid : dnssec_validation_invalid;
2428
2429 exit:
2430 if (signed_data != mDNSNULL) {
2431 free(signed_data);
2432 signed_data = mDNSNULL;
2433 }
2434 return result;
2435 }
2436
2437 mDNSlocal dnssec_validation_result_t
2438 validate_path_from_zsk_to_ds(
2439 const mDNSu32 request_id,
2440 const dnssec_validator_node_t * const _Nonnull parent,
2441 const list_t * const _Nonnull dses /* list_t<dnssec_ds_t> */) {
2442
2443 dnssec_validation_result_t result = dnssec_validation_valid;
2444 mDNSu8 * signed_data = mDNSNULL;
2445 mDNSu32 signed_data_length;
2446 mDNSBool is_signed_data_valid;
2447
2448 // TODO: original_response could be nsec nsec3
2449 result = check_rrsig_validity_with_rrs(parent->u.zsk.sig, dses, original_response, kDNSType_DS);
2450 require_quiet(result == dnssec_validation_valid, exit);
2451
2452 signed_data = reconstruct_signed_data_with_rrs(dses, parent->u.zsk.sig, original_response, kDNSType_DS, &signed_data_length);
2453 require_action(signed_data != mDNSNULL, exit, result = dnssec_validation_no_memory;
2454 log_default("No enough memory to allocate for signed data;"));
2455
2456 is_signed_data_valid = validate_signed_data_with_rrsig_and_dnskey(request_id, signed_data, signed_data_length, parent->u.zsk.sig, parent->u.zsk.key);
2457 result = is_signed_data_valid ? dnssec_validation_valid : dnssec_validation_invalid;
2458
2459 exit:
2460 if (signed_data != mDNSNULL) {
2461 free(signed_data);
2462 signed_data = mDNSNULL;
2463 }
2464 return result;
2465
2466 }
2467
2468 mDNSlocal dnssec_validation_result_t
2469 validate_path_from_zsk_to_nsec(
2470 const mDNSu32 request_id,
2471 const dnssec_validator_node_t * const _Nonnull parent,
2472 const dnssec_validator_node_t * const _Nonnull child) {
2473
2474 dnssec_validation_result_t result;
2475 dnssec_validation_result_t error;
2476 mDNSu8 * signed_data = mDNSNULL;
2477 mDNSu32 signed_data_length;
2478 mDNSBool is_signed_data_valid;
2479
2480 error = check_rrsig_validity_with_dnssec_rr(parent->u.zsk.sig, &child->u.nsec.nsec->dnssec_rr);
2481 require_action(error == dnssec_validation_valid, exit, result = error; log_default("RRSIG is invalid"));
2482
2483 signed_data = reconstruct_signed_data_with_one_dnssec_rr(&child->u.nsec.nsec->dnssec_rr, parent->u.zsk.sig, &signed_data_length);
2484 require_action(signed_data != mDNSNULL, exit, result = dnssec_validation_no_memory;
2485 log_error("No enough memory to allocate for signed data;"));
2486
2487 is_signed_data_valid = validate_signed_data_with_rrsig_and_dnskey(request_id, signed_data, signed_data_length, parent->u.zsk.sig, parent->u.zsk.key);
2488 result = is_signed_data_valid ? dnssec_validation_valid: dnssec_validation_invalid;
2489
2490 exit:
2491 if (signed_data != mDNSNULL) {
2492 free(signed_data);
2493 signed_data = mDNSNULL;
2494 }
2495 return result;
2496 }
2497
2498 mDNSlocal dnssec_validation_result_t
2499 validate_path_from_zsk_to_nsec3(
2500 const mDNSu32 request_id,
2501 const dnssec_validator_node_t * const _Nonnull parent,
2502 const dnssec_validator_node_t * const _Nonnull child) {
2503
2504 dnssec_validation_result_t result;
2505 dnssec_validation_result_t error;
2506 mDNSu8 * signed_data = mDNSNULL;
2507 mDNSu32 signed_data_length;
2508 mDNSBool is_signed_data_valid;
2509
2510 error = check_rrsig_validity_with_dnssec_rr(parent->u.zsk.sig, &child->u.nsec3.nsec3->dnssec_rr);
2511 require_action(error == dnssec_validation_valid, exit, result = error; log_default("RRSIG is invalid"));
2512
2513 signed_data = reconstruct_signed_data_with_one_dnssec_rr(&child->u.nsec3.nsec3->dnssec_rr, parent->u.zsk.sig, &signed_data_length);
2514 require_action(signed_data != mDNSNULL, exit, result = dnssec_validation_no_memory;
2515 log_error("No enough memory to allocate for signed data;"));
2516
2517 is_signed_data_valid = validate_signed_data_with_rrsig_and_dnskey(request_id, signed_data, signed_data_length, parent->u.zsk.sig, parent->u.zsk.key);
2518 result = is_signed_data_valid ? dnssec_validation_valid: dnssec_validation_invalid;
2519
2520 exit:
2521 if (signed_data != mDNSNULL) {
2522 free(signed_data);
2523 signed_data = mDNSNULL;
2524 }
2525 return result;
2526 }
2527
2528 //======================================================================================================================
2529 // check_rrsig_validity_with_rr
2530 //======================================================================================================================
2531
2532 mDNSlocal dnssec_validation_result_t
2533 check_rrsig_validity_with_dnssec_rr(
2534 const dnssec_rrsig_t * const _Nonnull rrsig,
2535 const dnssec_rr_t * const _Nonnull rr) {
2536
2537 dnssec_validation_result_t result = dnssec_validation_valid;
2538 const mDNSu8 * const owner_name = rrsig->dnssec_rr.name.c;
2539 const mDNSu32 owner_name_hash = rrsig->dnssec_rr.name_hash;
2540 const mDNSu16 class = rrsig->dnssec_rr.rr_class;
2541 const mDNSu8 * const signer_name = rrsig->signer_name;
2542 const mDNSu16 type_covered = rrsig->type_covered;
2543 const mDNSu8 labels_rrsig = rrsig->labels;
2544 mDNSu8 labels_rr;
2545
2546 // The RRSIG RR and the RRset MUST have the same owner name,
2547 require_action(owner_name_hash == rr->name_hash, exit, result = dnssec_validation_path_unmatched_owner_name;
2548 log_default("The owner names of RRSIG and records do not match; RRSIG=" PRI_DM_NAME ", RR=" PRI_DM_NAME,
2549 DM_NAME_PARAM((const domainname * const)owner_name), DM_NAME_PARAM(&rr->name)));
2550 require_action(DOMAIN_NAME_EQUALS(owner_name, rr->name.c), exit, result = dnssec_validation_path_unmatched_owner_name;
2551 log_default("The owner names of RRSIG and records do not match; RRSIG=" PRI_DM_NAME ", RR=" PRI_DM_NAME,
2552 DM_NAME_PARAM((const domainname * const)owner_name), DM_NAME_PARAM(&rr->name)));
2553
2554 // and the same class.
2555 require_action(class == rr->rr_class, exit, result = dnssec_validation_path_unmatched_class;
2556 log_default("The classes of RRSIG and records do not match; RRSIG=%u, RR=%u", class, rr->rr_class));
2557
2558 // TODO: The RRSIG RR's Signer's Name field MUST be the name of the zone that contains the RRset
2559 (void) signer_name;
2560
2561 // The RRSIG RR's Type Covered field MUST equal the RRset's type.
2562 require_action(type_covered == rr->rr_type, exit, result = dnssec_validation_path_unmatched_type_covered;
2563 log_default("The RRSIG does not cover the current record; RRSIG=" PUB_S ", RR=" PUB_S,
2564 DNS_TYPE_STR(type_covered), DNS_TYPE_STR(rr->rr_type)));
2565
2566 // The number of labels in the RRset owner name MUST be greater than or equal to the value in the RRSIG RR's Labels field.
2567 labels_rr = get_number_of_labels(rr->name.c);
2568 require_action(labels_rrsig <= labels_rr, exit, result = dnssec_validation_path_invalid_label_count;
2569 log_default("the RRSIG's label is not less than or equal to the number of labels in RR's owner's name; RRSIG=%u, RR=%u",
2570 labels_rrsig, labels_rr));
2571
2572 exit:
2573 return result;
2574 }
2575
2576 //======================================================================================================================
2577 // check_rrsig_validity_with_dnssec_rrs
2578 //======================================================================================================================
2579
2580 mDNSlocal dnssec_validation_result_t
2581 check_rrsig_validity_with_rrs(
2582 const dnssec_rrsig_t * const _Nonnull rrsig,
2583 const list_t * const _Nonnull list_to_check,
2584 response_type_t response_type_in_list,
2585 const mDNSu16 record_type_in_list) {
2586
2587 dnssec_validation_result_t result = dnssec_validation_valid;
2588 const dnssec_rr_t * rr;
2589
2590 for (list_node_t *node = list_get_first(list_to_check); !list_has_ended(list_to_check, node); node = list_next(node)) {
2591 // get correct node from the list
2592 switch (response_type_in_list) {
2593 case original_response:
2594 {
2595 if (record_type_in_list == kDNSQType_ANY) {
2596 const dnssec_original_t * const original = (dnssec_original_t *)node->data;
2597 rr = &original->dnssec_rr;
2598 } else if (record_type_in_list == kDNSType_DNSKEY) {
2599 const dnssec_dnskey_t * const dnskey = (dnssec_dnskey_t *)node->data;
2600 rr = &dnskey->dnssec_rr;
2601 } else if (record_type_in_list == kDNSType_DS) {
2602 const dnssec_ds_t * const ds = (dnssec_ds_t *)node->data;
2603 rr = &ds->dnssec_rr;
2604 } else {
2605 result = dnssec_validation_path_invalid_node_type;
2606 goto exit;
2607 }
2608 break;
2609 }
2610 case cname_response:
2611 {
2612 const dnssec_cname_t * const cname = (dnssec_cname_t *)node->data;
2613 rr = &cname->dnssec_rr;
2614 }
2615 break;
2616 case nsec_response:
2617 {
2618 if (record_type_in_list == kDNSQType_ANY) {
2619 rr = (dnssec_rr_t *)node->data;
2620 } else if (record_type_in_list == kDNSType_NSEC) {
2621 const dnssec_nsec_t * const nsec = (dnssec_nsec_t *)node->data;
2622 rr = &nsec->dnssec_rr;
2623 } else {
2624 result = dnssec_validation_path_invalid_node_type;
2625 goto exit;
2626 }
2627 break;
2628 }
2629 case nsec3_response:
2630 {
2631 const dnssec_nsec3_t * const nsec3 = (dnssec_nsec3_t *)node->data;
2632 rr = &nsec3->dnssec_rr;
2633 }
2634 break;
2635 default:
2636 {
2637 result = dnssec_validation_path_invalid_node_type;
2638 goto exit;
2639 }
2640 }
2641
2642 result = check_rrsig_validity_with_dnssec_rr(rrsig, rr);
2643 require_quiet(result == dnssec_validation_valid, exit);
2644 }
2645
2646 exit:
2647 return result;
2648 }
2649
2650 //======================================================================================================================
2651 // reconstruct_signed_data_with_dnssec_rrs
2652 //======================================================================================================================
2653
2654 mDNSlocal void *
2655 reconstruct_signed_data_with_rrs(
2656 const list_t * const _Nonnull rr_set,
2657 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
2658 const response_type_t response_type,
2659 const mDNSu16 record_type,
2660 mDNSu32 * const _Nonnull out_signed_data_length) {
2661
2662 mDNSu8 rr_count = 0;
2663 const dnssec_rr_t * rr_array[256]; // The maximum number of RR in one RRSET should be no more than 256
2664
2665 // sort RRset in canonical order
2666 for (list_node_t *node = list_get_first(rr_set); !list_has_ended(rr_set, node); node = list_next(node)) {
2667 dnssec_rr_t *rr;
2668
2669 switch (response_type) {
2670 case original_response:
2671 if (record_type == kDNSQType_ANY) {
2672 rr = &((dnssec_original_t *)node->data)->dnssec_rr;
2673 } else if (record_type == kDNSType_DNSKEY) {
2674 rr = &((dnssec_dnskey_t *)node->data)->dnssec_rr;
2675 } else if (record_type == kDNSType_DS) {
2676 rr = &((dnssec_ds_t *)node->data)->dnssec_rr;
2677 } else {
2678 // It should never happen.
2679 log_error("incorrect DNSSEC data type");
2680 goto exit;
2681 }
2682 break;
2683 case cname_response:
2684 rr = &((dnssec_cname_t *)node->data)->dnssec_rr;
2685 break;
2686 case nsec_response: {
2687 if (record_type == kDNSQType_ANY) {
2688 rr = (dnssec_rr_t *)node->data;
2689 } else if (record_type == kDNSType_NSEC) {
2690 rr = &((dnssec_nsec_t *)node->data)->dnssec_rr;
2691 } else {
2692 goto exit;
2693 }
2694 break;
2695 }
2696 case nsec3_response:
2697 rr = &((dnssec_nsec3_t *)node->data)->dnssec_rr;
2698 break;
2699 default:
2700 // It should never happen.
2701 log_error("signed data has unknown_response type");
2702 goto exit;
2703 }
2704
2705 rr_array[rr_count] = rr;
2706 rr_count++;
2707 }
2708 sort_rr_array_canonically(rr_array, rr_count);
2709
2710 // deduplicate RRs in RRSet
2711 rr_array_dedup(rr_array, rr_count);
2712
2713 return reconstruct_signed_data_internal(rr_array, rr_count, dnssec_rrsig, out_signed_data_length);
2714
2715 exit:
2716 return mDNSNULL;
2717 }
2718
2719 //======================================================================================================================
2720 // reconstruct_signed_data_with_one_dnssec_rr
2721 //======================================================================================================================
2722
2723 mDNSlocal void *
2724 reconstruct_signed_data_with_one_dnssec_rr(
2725 const dnssec_rr_t * const _Nonnull dnssec_rr,
2726 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
2727 mDNSu32 * const _Nonnull out_signed_data_length) {
2728
2729 mDNSu8 rr_count = 0;
2730 const dnssec_rr_t *rr_array[1];
2731
2732 rr_array[0] = dnssec_rr;
2733 rr_count = 1;
2734
2735 return reconstruct_signed_data_internal(rr_array, rr_count, dnssec_rrsig, out_signed_data_length);
2736 }
2737
2738 //======================================================================================================================
2739 // reconstruct_signed_data_internal
2740 //======================================================================================================================
2741
2742 mDNSlocal void *
2743 reconstruct_signed_data_internal(
2744 const dnssec_rr_t * const rr_array[],
2745 const mDNSu8 rr_count,
2746 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
2747 mDNSu32 * const _Nonnull out_signed_data_length) {
2748
2749 mStatus error = mStatus_NoError;
2750 mDNSu32 signed_data_length = 0;
2751 mDNSu8 * signed_data = mDNSNULL;
2752 mDNSu8 * data_ptr = mDNSNULL;
2753 mDNSu8 * data_limit = mDNSNULL;
2754 mDNSu32 number_bytes_copied = 0;
2755
2756 // calculate correct signed data length taking duplicates, domain name decompression and wildcard expansion into consideration
2757 error = calculate_signed_data_length(rr_array, rr_count, dnssec_rrsig, &signed_data_length);
2758 require_quiet(error == mStatus_NoError, exit);
2759
2760 // allocate memory for the signed data
2761 signed_data = malloc(signed_data_length);
2762 require_action(signed_data != mDNSNULL, exit, error = mStatus_NoMemoryErr; log_fault("malloc failed; error_description='%s'", strerror(errno)));
2763
2764 data_ptr = signed_data;
2765 data_limit = data_ptr + signed_data_length;
2766
2767 // signed_data += RRSIG_RDATA
2768 memcpy(data_ptr, dnssec_rrsig->dnssec_rr.rdata, offsetof(dns_type_rrsig_t, signer_name));
2769 data_ptr += offsetof(dns_type_rrsig_t, signer_name);
2770
2771 // signed_data += RRSIG_RDATA(signer's name)
2772 data_ptr += copy_canonical_name(data_ptr, dnssec_rrsig->signer_name);
2773
2774 for (mDNSu8 i = 0; i < rr_count; i++) {
2775 const dnssec_rr_t * const rr = rr_array[i];
2776 if (rr == mDNSNULL) { // the current record is a duplicate one
2777 continue;
2778 }
2779
2780 // signed_data+= RR(i)
2781 data_ptr += copy_rr_for_signed_data(data_ptr, rr, dnssec_rrsig);
2782 }
2783
2784 *out_signed_data_length = signed_data_length;
2785 number_bytes_copied = data_ptr - signed_data;
2786 require_action(number_bytes_copied == signed_data_length, exit, error = mStatus_UnknownErr;
2787 log_error("reconstruct_signed_data failed, number of bytes copied is not equal to the size of memory allocated; copied=%u, allocated=%u",
2788 number_bytes_copied, signed_data_length));
2789 require_quiet(data_ptr == data_limit, exit);
2790
2791 exit:
2792 if (error != mStatus_NoError) {
2793 if (signed_data != mDNSNULL) {
2794 free(signed_data);
2795 signed_data = mDNSNULL;
2796 }
2797 }
2798 return signed_data;
2799 }
2800
2801 //======================================================================================================================
2802 // calculate_signed_data_length
2803 //======================================================================================================================
2804
2805 mDNSlocal mStatus
2806 calculate_signed_data_length(
2807 const dnssec_rr_t * const rr_array[_Nonnull],
2808 const mDNSu8 rr_count,
2809 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig,
2810 mDNSu32 * const _Nonnull out_length) {
2811
2812 mStatus error = mStatus_NoError;
2813 mDNSu32 signed_data_length = 0;
2814
2815 // signed_data += RRSIG_RDATA(before signer's name) + signer's name
2816 signed_data_length += offsetof(dns_type_rrsig_t, signer_name) + canonical_form_name_length(dnssec_rrsig->signer_name);
2817
2818 // signed_data += RR(x)
2819 for (mDNSu8 i = 0; i < rr_count; i++) {
2820 const dnssec_rr_t * const rr = rr_array[i];
2821 mDNSu32 rr_length = 0;
2822 mDNSs16 name_length = 0;
2823 if (rr == mDNSNULL) { // It is a duplicate records, now skips it.
2824 continue;
2825 }
2826
2827 name_length = calculate_name_length_in_signed_data(rr->name.c, dnssec_rrsig->labels);
2828 require_action(name_length != -1, exit, error = mStatus_Invalid;
2829 log_default("rrsig label count is invalid, cannot be used to validate records;"));
2830
2831 // RR(i) += name
2832 rr_length += name_length;
2833
2834 // RR(i) += type + class + OrigTTL + RDATA length
2835 rr_length += sizeof(rr->rr_type) + sizeof(rr->rr_class) + sizeof(dnssec_rrsig->original_TTL) + sizeof(rr->rdata_length);
2836
2837 // RR(i) += RDATA
2838 rr_length += calculate_rdata_length_in_signed_data(rr);
2839
2840 signed_data_length += rr_length;
2841 }
2842
2843 *out_length = signed_data_length;
2844 exit:
2845 return error;
2846 }
2847
2848 //======================================================================================================================
2849 // calculate_name_length_in_signed_data
2850 //======================================================================================================================
2851
2852 // length is calculated based on RFC 4035 Section 5.3.2. Reconstructing the Signed Data
2853 mDNSlocal mDNSs16
2854 calculate_name_length_in_signed_data(const mDNSu8 * const _Nonnull name, const mDNSu8 rrsig_labels) {
2855 // assume that the domainname* is already fully qualified
2856 mDNSu8 name_labels = get_number_of_labels(name);
2857 if (name_labels == rrsig_labels) {
2858 return DOMAIN_NAME_LENGTH(name);
2859 } else if (name_labels > rrsig_labels) {
2860 // wild card case, ignore this case for now
2861 return DOMAIN_NAME_LENGTH(name);
2862 } else {
2863 // name_labels < rrsig_labels
2864 return -1;
2865 }
2866 }
2867
2868 //======================================================================================================================
2869 // calculate_rdata_length_in_signed_data
2870 //======================================================================================================================
2871
2872 // ref: https://tools.ietf.org/html/rfc4034#section-6.2
2873 mDNSlocal mDNSu16
2874 calculate_rdata_length_in_signed_data(const dnssec_rr_t * const _Nonnull dnssec_rr) {
2875 // assumption:
2876 // 1. All the name in the rr is fully expanded and fully qualified.
2877 // 2. There is no wildcard name.
2878
2879 return dnssec_rr->rdata_length;
2880 }
2881
2882 //======================================================================================================================
2883 // copy_canonical_name
2884 //======================================================================================================================
2885 mDNSlocal const mDNSu8 *
2886 get_wildcard_name(const mDNSu8 * const _Nonnull name, mDNSu8 * const _Nonnull buffer, const mDNSu16 buffer_length) {
2887 const mDNSu8 * ptr = name;
2888 const mDNSu16 name_length = DOMAIN_NAME_LENGTH(ptr);
2889 const mDNSu8 * const ptr_limit = ptr + name_length;
2890 mDNSu8 * buffer_ptr = buffer;
2891
2892 verify_action(name_length <= buffer_length , return mDNSNULL);
2893
2894 while (ptr < ptr_limit) {
2895 const mDNSu8 * const label = ptr + 1;
2896 const mDNSu8 label_length = *ptr;
2897 if (ptr == name) {
2898 buffer_ptr[0] = 1;
2899 buffer_ptr[1] = '*';
2900 } else {
2901 buffer_ptr[0] = label_length;
2902 memcpy(buffer_ptr + 1, label, label_length);
2903 }
2904
2905 ptr += 1 + ptr[0];
2906 buffer_ptr += 1 + buffer_ptr[0];
2907 }
2908
2909 return buffer;
2910 }
2911
2912 //======================================================================================================================
2913 // copy_rr_for_signed_data
2914 //======================================================================================================================
2915
2916 mDNSlocal mDNSu32
2917 copy_rr_for_signed_data(
2918 mDNSu8 * _Nonnull dst,
2919 const dnssec_rr_t * const _Nonnull rr,
2920 const dnssec_rrsig_t * const _Nonnull rrsig) {
2921
2922 mDNSu16 canonical_rdata_length;
2923 mDNSu8 * const original_dst = dst;
2924
2925 // RR(i) += name
2926 dst += copy_name_in_rr_for_signed_data(dst, rr->name.c, rrsig);
2927
2928 // RR(i) += type
2929 mDNSu16 rr_type_net = htons(rr->rr_type);
2930 memcpy(dst, &rr_type_net, sizeof(rr_type_net));
2931 dst += sizeof(rr_type_net);
2932
2933 // RR(i) += class
2934 mDNSu16 rr_class_net = htons(rr->rr_class);
2935 memcpy(dst, &rr_class_net, sizeof(rr_class_net));
2936 dst += sizeof(rr_class_net);
2937
2938 // RR(i) += Original TTL
2939 mDNSu32 original_ttl_net = htonl(rrsig->original_TTL);
2940 memcpy(dst, &original_ttl_net, sizeof(original_ttl_net));
2941 dst += sizeof(original_ttl_net);
2942
2943 // RR(i) += RDATA length (canonical form of RDATA)
2944 canonical_rdata_length = calculate_rdata_length_in_signed_data(rr);
2945 mDNSu16 canonical_rdata_length_net = ntohs(canonical_rdata_length);
2946 memcpy(dst, &canonical_rdata_length_net, sizeof(canonical_rdata_length_net));
2947 dst += sizeof(canonical_rdata_length_net);
2948
2949 // RR(i) += RDATA (canonical form)
2950 dst += copy_rdata_in_rr(dst, rr->rdata, rr->rdata_length, rr->rr_type);
2951
2952 return dst - original_dst;
2953 }
2954
2955 //======================================================================================================================
2956 // copy_name_in_rr_for_signed_data
2957 //======================================================================================================================
2958
2959 mDNSlocal mDNSu8
2960 copy_name_in_rr_for_signed_data(
2961 mDNSu8 * const _Nonnull dst,
2962 const mDNSu8 * const _Nonnull name,
2963 const dnssec_rrsig_t * const _Nonnull dnssec_rrsig) {
2964
2965 mDNSu8 name_labels = get_number_of_labels(name);
2966 mDNSu8 rrsig_labels = dnssec_rrsig->labels;
2967 mDNSu8 bytes_write;
2968
2969 if (name_labels == rrsig_labels) {
2970 bytes_write = copy_canonical_name(dst, name);
2971 } else {
2972 // name_labels > rrsig_labels
2973 // It is impossible to have "name_labels < rrsig_labels", since the function calculate_signed_data_length
2974 // already checks the validity of the records.
2975 // TODO: wildcard domain name.
2976 bytes_write = 0;
2977 }
2978
2979 return bytes_write;
2980 }
2981
2982 //======================================================================================================================
2983 // copy_rdata_in_rr
2984 //======================================================================================================================
2985
2986 // The rdata is in the canonical form. ref: https://tools.ietf.org/html/rfc4034#section-6.2
2987 mDNSlocal mDNSu16
2988 copy_rdata_in_rr(mDNSu8 * const _Nonnull dst, const mDNSu8 * const rdata, const mDNSu16 rdata_length, const mDNSu8 rr_type) {
2989 // TODO: First assume all the rdata is already in canonical form.
2990 (void) rr_type;
2991
2992 memcpy(dst, rdata, rdata_length);
2993
2994 return rdata_length;
2995 }
2996
2997 //======================================================================================================================
2998 // sort function
2999 //======================================================================================================================
3000
3001 //======================================================================================================================
3002 // sort_records_with_algorithm
3003 //======================================================================================================================
3004
3005 mDNSlocal void
3006 sort_records_with_algorithm(dnssec_context_t * const _Nonnull context) {
3007 list_t * rrsigs;
3008 originals_with_rrsig_t * originals_with_rrsig = &context->original.original_result_with_rrsig;
3009 response_type_t type;
3010
3011 type = originals_with_rrsig->type;
3012 // sort RRSIG in original response
3013 switch (type) {
3014 case original_response:
3015 case cname_response:
3016 if (type == original_response) {
3017 rrsigs = &originals_with_rrsig->u.original.rrsig_records;
3018 } else if (type == cname_response) {
3019 rrsigs = &originals_with_rrsig->u.cname_with_rrsig.rrsig_records;
3020 } else {
3021 goto invalid_type_exit;
3022 }
3023 list_sort(rrsigs, &dnssec_rrsig_t_comparator);
3024 break;
3025 case nsec_response:
3026 case nsec3_response:
3027 if (type == nsec_response) {
3028 list_t *nsec_list = &originals_with_rrsig->u.nsecs_with_rrsig.nsec_and_rrsigs_same_name;
3029 for (list_node_t *nsec_node = list_get_first(nsec_list); !list_has_ended(nsec_list, nsec_node); nsec_node = list_next(nsec_node)) {
3030 one_nsec_with_rrsigs_t * const one_nsec = (one_nsec_with_rrsigs_t *)nsec_node->data;
3031 list_sort(&one_nsec->rrsig_records, &dnssec_rrsig_t_comparator);
3032 }
3033 } else if (type == nsec3_response) {
3034 list_t *nsec3_list = &originals_with_rrsig->u.nsec3s_with_rrsig.nsec3_and_rrsigs_same_name;
3035 for (list_node_t *nsec3_node = list_get_first(nsec3_list); !list_has_ended(nsec3_list, nsec3_node); nsec3_node = list_next(nsec3_node)) {
3036 one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)nsec3_node->data;
3037 list_sort(&one_nsec3->rrsig_records, &dnssec_rrsig_t_comparator);
3038 }
3039 } else {
3040 goto invalid_type_exit;
3041 }
3042 break;
3043 default:
3044 goto invalid_type_exit;
3045 }
3046
3047
3048 // sort RRSIG and DS in zone records
3049 for (list_node_t *node = list_get_first(&context->zone_chain); !list_has_ended(&context->zone_chain, node); node = list_next(node)) {
3050 dnssec_zone_t * zone = (dnssec_zone_t *)node->data;
3051 dnskeys_with_rrsig_t * dnskeys_with_rrsig = &zone->dnskeys_with_rrsig;
3052 dses_with_rrsig_t * dses_with_rrsig = &zone->dses_with_rrsig;
3053
3054 // sort DNSKEY RRSIG
3055 if (zone->dnskey_request_started) {
3056 list_sort(&dnskeys_with_rrsig->rrsig_records, &dnssec_rrsig_t_comparator);
3057 }
3058
3059 if (zone->ds_request_started)
3060 {
3061 // sort DS RRSIG
3062 type = dses_with_rrsig->type;
3063 switch (type) {
3064 case original_response:
3065 list_sort(&dses_with_rrsig->u.original.rrsig_records, &dnssec_rrsig_t_comparator);
3066 break;
3067 case nsec_response:
3068 case nsec3_response:
3069 if (type == nsec_response) {
3070 list_t *nsec_list = &dses_with_rrsig->u.nsecs_with_rrsig.nsec_and_rrsigs_same_name;
3071 for (list_node_t *nsec_node = list_get_first(nsec_list); !list_has_ended(nsec_list, nsec_node); nsec_node = list_next(nsec_node)) {
3072 one_nsec_with_rrsigs_t * const one_nsec = (one_nsec_with_rrsigs_t *)nsec_node->data;
3073 list_sort(&one_nsec->rrsig_records, &dnssec_rrsig_t_comparator);
3074 }
3075 } else if (type == nsec3_response) {
3076 list_t *nsec3_list = &dses_with_rrsig->u.nsec3s_with_rrsig.nsec3_and_rrsigs_same_name;
3077 for (list_node_t *nsec3_node = list_get_first(nsec3_list); !list_has_ended(nsec3_list, nsec3_node); nsec3_node = list_next(nsec3_node)) {
3078 one_nsec3_with_rrsigs_t * const one_nsec3 = (one_nsec3_with_rrsigs_t *)nsec3_node->data;
3079 list_sort(&one_nsec3->rrsig_records, &dnssec_rrsig_t_comparator);
3080 }
3081 } else {
3082 goto invalid_type_exit;
3083 }
3084 break;
3085 default:
3086 goto invalid_type_exit;
3087 }
3088 }
3089 }
3090
3091 return;
3092 invalid_type_exit:
3093 log_error("Invalid original response type; type=%d", type);
3094 return;
3095 }
3096
3097 //======================================================================================================================
3098 // dnssec_ds_t_comparator
3099 //======================================================================================================================
3100 mDNSlocal mDNSs8 __unused
3101 dnssec_ds_t_comparator(const list_node_t * _Nonnull const left, const list_node_t * _Nonnull const right) {
3102 mDNSs8 result;
3103 dnssec_ds_t * left_ds = (dnssec_ds_t *)left->data;
3104 dnssec_ds_t * right_ds = (dnssec_ds_t *)right->data;
3105 mDNSs16 left_priority = get_priority_of_ds_digest(left_ds->digest_type);
3106 mDNSs16 right_priority = get_priority_of_ds_digest(right_ds->digest_type);
3107
3108 if (left_priority < right_priority) {
3109 result = -1;
3110 } else if (left_priority > right_priority) {
3111 result = 1;
3112 } else {
3113 // left_priority == right_priority
3114 result = 0;
3115 }
3116
3117 return result;
3118 }
3119
3120 //======================================================================================================================
3121 // dnssec_rrsig_t_comparator
3122 //======================================================================================================================
3123
3124 mDNSlocal mDNSs8
3125 dnssec_rrsig_t_comparator(const list_node_t * _Nonnull const left, const list_node_t * _Nonnull const right) {
3126 mDNSs8 result;
3127 dnssec_rrsig_t *left_rrsig = (dnssec_rrsig_t *)left->data;
3128 dnssec_rrsig_t *right_rrsig = (dnssec_rrsig_t *)right->data;
3129 mDNSs16 left_priority = get_priority_of_dnskey_algorithm(left_rrsig->algorithm);
3130 mDNSs16 right_priority = get_priority_of_dnskey_algorithm(right_rrsig->algorithm);
3131
3132 if (left_priority < right_priority) {
3133 result = 1;
3134 } else if (left_priority > right_priority) {
3135 result = -1;
3136 } else {
3137 // left_priority == right_priority
3138 result = 0;
3139 }
3140
3141 return result;
3142 }
3143
3144 //======================================================================================================================
3145 // sort_rr_array
3146 //======================================================================================================================
3147
3148 mDNSlocal void
3149 sort_rr_array_canonically(const dnssec_rr_t * rr_array[_Nonnull], const mDNSu8 rr_count) {
3150 // insertion sort is good for partially sorted array
3151 for (mDNSs32 j, i = 1; i < rr_count; i++) {
3152 const dnssec_rr_t * dnssec_rr_to_insert = rr_array[i];
3153 j = i - 1;
3154
3155 while (j >= 0 && dnssec_rr_t_comparator(dnssec_rr_to_insert, rr_array[j]) == -1) {
3156 rr_array[j + 1] = rr_array[j];
3157 j--;
3158 }
3159 rr_array[j + 1] = dnssec_rr_to_insert;
3160 }
3161 }
3162
3163 //======================================================================================================================
3164 // sort_rr_array
3165 //======================================================================================================================
3166
3167 mDNSlocal mDNSs8
3168 dnssec_rr_t_comparator(const dnssec_rr_t * const _Nonnull left, const dnssec_rr_t * const _Nonnull right) {
3169 mDNSu16 left_length = left->rdata_length;
3170 mDNSu16 right_length = right->rdata_length;
3171 mDNSu16 min_length = MIN(left_length, right_length);
3172 mDNSs32 memcmp_result = memcmp(left->rdata, right->rdata, min_length);
3173 mDNSs8 result;
3174 if (memcmp_result < 0) {
3175 result = -1;
3176 } else if (memcmp_result > 0) {
3177 result = 1;
3178 } else {
3179 // memcmp_result == 0
3180 if (left_length > right_length) {
3181 result = 1;
3182 } else if (left_length < right_length) {
3183 result = -1;
3184 } else {
3185 // left_length == right_length
3186 log_error("two RR are canonically equal;");
3187 result = 0;
3188 }
3189 }
3190 return result;
3191 }
3192
3193 //======================================================================================================================
3194 // rr_array_dedup
3195 //======================================================================================================================
3196
3197 mDNSlocal mDNSBool
3198 rr_array_dedup(const dnssec_rr_t * rr_array[_Nonnull], const mDNSu8 rr_count) {
3199 mDNSBool duplicate = mDNSfalse;
3200 for (int i = 0, n = (int)rr_count - 1; i < n; i++) {
3201 const dnssec_rr_t *prev = rr_array[i];
3202 const dnssec_rr_t *next = rr_array[i + 1];
3203 if (equal_dnssec_rr_t(prev, next)) {
3204 rr_array[i] = mDNSNULL;
3205 duplicate = mDNStrue;
3206 }
3207 }
3208 return duplicate;
3209 }
3210
3211 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)