5 // Copyright (c) 2020 Apple Inc. All rights reserved.
8 #include "mDNSEmbeddedAPI.h"
9 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
11 #include <CommonCrypto/CommonDigestSPI.h>
12 #include <Security/Security.h>
13 #include <Security/SecKeyPriv.h>
14 #include "dnssec_v2_crypto.h"
15 #include "dnssec_v2_helper.h"
16 #include "dnssec_v2_log.h"
21 mDNSu8
* const _Nonnull public_key
,
22 const mDNSu16 key_length
,
23 uint8_t ** const _Nonnull out_modulus
,
24 signed long * const _Nonnull out_modulus_length
,
25 uint8_t ** const _Nonnull out_exponent
,
26 signed long * const _Nonnull out_exponent_length
);
29 print_validation_progress(const mDNSu32 request_id
, const dnssec_dnskey_t
* const dnskey
, const dnssec_rrsig_t
* const rrsig
);
31 // The array index means the algorithm number, the array element value means the prefered order to use when there is
32 // multiple algorithms avaliable, the order is determined by "The most secure, the better", 0 is the lowest priority.
34 //======================================================================================================================
35 // get_priority_of_ds_digest
36 //======================================================================================================================
39 get_priority_of_ds_digest(mDNSu8 digest
) {
40 // ref 1: https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
41 // ref 2: https://tools.ietf.org/html/draft-ietf-dnsop-algorithm-update-10
46 // Algorithm Number 1 SHA-1 MUST
49 case DS_DIGEST_SHA_256
:
50 // Algorithm Number 2 SHA-256 MUST
53 case DS_DIGEST_SHA_384
:
54 // Algorithm Number 4 SHA-384 RECOMMENDED
58 // Algorithm Number 0 Reserved
59 // Algorithm Number 3 GOST R 34.11-94 NOT SUPPORTED
60 // Algorithm Number 5-255 Unassigned
68 //======================================================================================================================
69 // get_priority_of_dnskey_algorithm
70 //======================================================================================================================
73 get_priority_of_dnskey_algorithm(mDNSu8 algorithm
) {
74 // ref 1: https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml
75 // ref 2: https://tools.ietf.org/html/draft-ietf-dnsop-algorithm-update-10
80 case DNSKEY_ALGORITHM_RSASHA1
:
81 // Algorithm Number 5 RSA/SHA-1 MUST
84 case DNSKEY_ALGORITHM_RSASHA1_NSEC3_SHA1
:
85 // Algorithm Number 7 RSASHA1-NSEC3-SHA1 MUST
88 case DNSKEY_ALGORITHM_RSASHA256
:
89 // Algorithm Number 8 RSA/SHA-256 MUST
92 case DNSKEY_ALGORITHM_RSASHA512
:
93 // Algorithm Number 10 RSA/SHA-512 MUST
96 case DNSKEY_ALGORITHM_ECDSAP256SHA256
:
97 // Algorithm Number 13 ECDSA Curve P-256 with SHA-256 RECOMMENDED
100 case DNSKEY_ALGORITHM_ECDSAP384SHA384
:
101 // Algorithm Number 14 ECDSA Curve P-384 with SHA-384 RECOMMENDED
105 // Algorithm Number 0 Delete N/A
106 // Algorithm Number 1 RSA/MD5 MUST NOT
107 // Algorithm Number 2 Diffie-Hellman NOT SUPPORTED
108 // Algorithm Number 3 DSA/SHA1 MUST NOT
109 // Algorithm Number 4 Reserved
110 // Algorithm Number 6 DSA-NSEC3-SHA1 MUST NOT
111 // Algorithm Number 9 Reserved
112 // Algorithm Number 11 Reserved
113 // Algorithm Number 12 GOST R 34.10-2001 MAY
114 // Algorithm Number 15 Ed25519 RECOMMENDED, but NOT SUPPORTED
115 // Algorithm Number 16 Ed448 RECOMMENDED, but NOT SUPPORTED
116 // Algorithm Number 17-122 Unassigned
117 // Algorithm Number 123-251 Reserved
118 // Algorithm Number 252 Reserved for Indirect Keys
119 // Algorithm Number 253 private algorithm
120 // Algorithm Number 254 private algorithm OID
121 // Algorithm Number 255 Reserved
129 //======================================================================================================================
130 // validate_signed_data_with_rrsig_and_dnskey
131 // the main function doing signature validation
132 //======================================================================================================================
135 validate_signed_data_with_rrsig_and_dnskey(
136 const mDNSu32 request_id
,
137 const mDNSu8
* const _Nonnull signed_data
,
138 const mDNSu32 signed_data_length
,
139 const dnssec_rrsig_t
* const _Nonnull rrsig
,
140 const dnssec_dnskey_t
* const _Nonnull dnskey
) {
142 mDNSBool valid
= mDNSfalse
;
143 const mDNSu8
* data_or_digest_be_signed
= mDNSNULL
;
144 mDNSu32 data_or_digest_be_signed_length
;
145 SecKeyAlgorithm verify_algorithm
;
146 const void * public_key_type
;
147 CFErrorRef cf_error
= mDNSNULL
;
148 CFDataRef data_to_verify_CFData
= mDNSNULL
;
149 CFDataRef sig_to_match_CFData
= mDNSNULL
;
150 SecKeyRef key
= mDNSNULL
;
151 digest_type_t digest_type
= DIGEST_UNSUPPORTED
;
153 // choose different signature validation algorithm and public key
154 switch (dnskey
->algorithm
) {
155 case DNSKEY_ALGORITHM_RSASHA1
:
156 verify_algorithm
= kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
;
157 public_key_type
= kSecAttrKeyTypeRSA
;
159 case DNSKEY_ALGORITHM_RSASHA1_NSEC3_SHA1
:
160 verify_algorithm
= kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
;
161 public_key_type
= kSecAttrKeyTypeRSA
;
163 case DNSKEY_ALGORITHM_RSASHA256
:
164 verify_algorithm
= kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256
;
165 public_key_type
= kSecAttrKeyTypeRSA
;
167 case DNSKEY_ALGORITHM_RSASHA512
:
168 verify_algorithm
= kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512
;
169 public_key_type
= kSecAttrKeyTypeRSA
;
171 case DNSKEY_ALGORITHM_ECDSAP256SHA256
:
172 verify_algorithm
= kSecKeyAlgorithmECDSASignatureRFC4754
;
173 public_key_type
= kSecAttrKeyTypeECSECPrimeRandom
;
174 digest_type
= DIGEST_SHA_256
;
175 data_or_digest_be_signed_length
= 32;
177 case DNSKEY_ALGORITHM_ECDSAP384SHA384
:
178 verify_algorithm
= kSecKeyAlgorithmECDSASignatureRFC4754
;
179 public_key_type
= kSecAttrKeyTypeECSECPrimeRandom
;
180 digest_type
= DIGEST_SHA_384
;
181 data_or_digest_be_signed_length
= 48;
184 log_error("Unsupported DNSKEY algorithm; algorithm=%d", dnskey
->algorithm
);
188 // public key creation for RSA and ECDSA is different
189 if (public_key_type
== kSecAttrKeyTypeRSA
) {
191 // The format of public key is not the standard PEM DER ASN.1 PKCS#1 RSA Public key format, so we need to parse
192 // the modulus and exponent explicitly.
193 SecRSAPublicKeyParams params
;
194 parse_rsa_pubkey(dnskey
->public_key
, dnskey
->public_key_length
, ¶ms
.modulus
, ¶ms
.modulusLength
, ¶ms
.exponent
, ¶ms
.exponentLength
);
195 key
= SecKeyCreateRSAPublicKey(kCFAllocatorDefault
, (const uint8_t *)¶ms
, sizeof(params
), kSecKeyEncodingRSAPublicParams
);
196 require_quiet(key
!= mDNSNULL
, exit
);
198 data_or_digest_be_signed
= signed_data
;
199 data_or_digest_be_signed_length
= signed_data_length
;
200 // RSA uses original data to verify record.
201 } else if (public_key_type
== kSecAttrKeyTypeECSECPrimeRandom
) {
203 const void * public_key_options_key
[] = {kSecAttrKeyType
, kSecAttrKeyClass
};
204 const void * public_key_options_values
[] = {kSecAttrKeyTypeECSECPrimeRandom
, kSecAttrKeyClassPublic
};
205 CFDataRef public_key_CFData
= mDNSNULL
;
206 CFDictionaryRef public_key_options
= mDNSNULL
;
207 CFNumberRef key_size_CFNumber
= mDNSNULL
;
208 mDNSu8
* ecdsa_key_bytes_encoding
= mDNSNULL
;
209 mDNSu32 ecdsa_key_length
= dnskey
->public_key_length
+ 1;
210 mDNSu8 data_digest
[MAX_HASH_OUTPUT_SIZE
];
212 // create security framework readable public key format
213 ecdsa_key_bytes_encoding
= malloc(ecdsa_key_length
);
214 require_quiet(ecdsa_key_bytes_encoding
!= mDNSNULL
, ecdsa_exit
);
216 ecdsa_key_bytes_encoding
[0] = 4;
217 memcpy(ecdsa_key_bytes_encoding
+ 1, dnskey
->public_key
, dnskey
->public_key_length
);
219 public_key_CFData
= CFDataCreate(kCFAllocatorDefault
, ecdsa_key_bytes_encoding
, ecdsa_key_length
);
220 require_quiet(public_key_CFData
!= NULL
, ecdsa_exit
);
222 public_key_options
= CFDictionaryCreate(kCFAllocatorDefault
, public_key_options_key
,
223 public_key_options_values
, sizeof(public_key_options_key
) / sizeof(void *),
224 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
225 require_quiet(public_key_options
!= NULL
, ecdsa_exit
);
227 // create the public key
228 key
= SecKeyCreateWithData(public_key_CFData
, public_key_options
, &cf_error
);
229 require_action(key
!= mDNSNULL
, ecdsa_exit
, log_error("SecKeyCreateWithData failed: %@", CFErrorCopyDescription(cf_error
)));
231 // ECDSA uses digest to verify record.
232 mDNSBool calculated
= calculate_digest_for_data(signed_data
, signed_data_length
, digest_type
, data_digest
, sizeof(data_digest
));
233 require_action(calculated
, ecdsa_exit
, log_error("calculate_digest_for_data failed to return the digest;"));
234 data_or_digest_be_signed
= data_digest
;
235 // data_be_signed_length is set in the previous switch statement.
238 if (public_key_CFData
!= NULL
) CFRelease(public_key_CFData
);
239 if (public_key_options
!= NULL
) CFRelease(public_key_options
);
240 if (key_size_CFNumber
!= NULL
) CFRelease(key_size_CFNumber
);
241 if (cf_error
!= NULL
) {
245 if (ecdsa_key_bytes_encoding
!= mDNSNULL
) free(ecdsa_key_bytes_encoding
);
250 require_quiet(key
!= mDNSNULL
, exit
);
252 // create data and signature to verify
253 data_to_verify_CFData
= CFDataCreate(kCFAllocatorDefault
, data_or_digest_be_signed
, data_or_digest_be_signed_length
);
254 sig_to_match_CFData
= CFDataCreate(kCFAllocatorDefault
, rrsig
->signature
, rrsig
->signature_length
);
256 Boolean matches
= SecKeyVerifySignature(key
, verify_algorithm
, data_to_verify_CFData
, sig_to_match_CFData
, &cf_error
);
258 print_validation_progress(request_id
, dnskey
, rrsig
);
260 log_default("SecKeyVerifySignature error: %@", CFErrorCopyDescription(cf_error
));
263 valid
= matches
? mDNStrue
: mDNSfalse
;
266 if (key
!= mDNSNULL
) CFRelease(key
);
267 if (data_to_verify_CFData
!= mDNSNULL
) CFRelease(data_to_verify_CFData
);
268 if (sig_to_match_CFData
!= mDNSNULL
) CFRelease(sig_to_match_CFData
);
269 if (cf_error
!= mDNSNULL
) CFRelease(cf_error
);
274 //======================================================================================================================
276 //======================================================================================================================
278 //======================================================================================================================
279 // calculate_digest_for_data
280 // get the corresponding digest
281 //======================================================================================================================
284 calculate_digest_for_data(
285 const mDNSu8
* const _Nonnull data
,
286 const mDNSu32 data_length
,
287 const digest_type_t digest_type
,
288 mDNSu8
* const _Nonnull digest_buffer
,
289 mDNSu32 buffer_size
) {
291 CCDigestAlgorithm cc_digest_algorithm
;
292 CCDigestCtx cc_digest_context
;
293 mDNSBool calculated
= mDNSfalse
;
295 switch (digest_type
) {
296 case DIGEST_SHA_1
: // SHA-1
297 require_quiet(buffer_size
>= SHA1_OUTPUT_SIZE
, exit
); // SHA-1 produces 20 bytes
298 #pragma clang diagnostic push // ignore the deprecation warning for SHA-1, since NSEC3 now only uses SHA-1 to get the digest.
299 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
300 cc_digest_algorithm
= kCCDigestSHA1
;
301 #pragma clang diagnostic pop
303 case DIGEST_SHA_256
: // SHA-256
304 require_quiet(buffer_size
>= SHA256_OUTPUT_SIZE
, exit
); // SHA-256 produces 256-bit(32-byte) digest
305 cc_digest_algorithm
= kCCDigestSHA256
;
307 case DIGEST_SHA_384
: // SHA-384
308 require_quiet(buffer_size
>= SHA384_OUTPUT_SIZE
, exit
); // SHA-384 produces 384-bit(48-byte) digest
309 cc_digest_algorithm
= kCCDigestSHA384
;
311 case DIGEST_SHA_512
: // SHA-512
312 require_quiet(buffer_size
>= SHA512_OUTPUT_SIZE
, exit
); // SHA-512 produces 512-bit(64-byte) digest
313 cc_digest_algorithm
= kCCDigestSHA512
;
319 CCDigestInit(cc_digest_algorithm
, &cc_digest_context
);
320 CCDigestUpdate(&cc_digest_context
, data
, data_length
);
321 CCDigestFinal(&cc_digest_context
, digest_buffer
);
322 calculated
= mDNStrue
;
328 //======================================================================================================================
329 // calculate_b32_hash_for_nsec3
330 // get Base32 encoding from the digest of riginal data
331 //======================================================================================================================
333 mDNSexport mDNSu8
* _Nullable
334 calculate_b32_hash_for_nsec3(
335 const mDNSu8
* const _Nonnull name
,
336 const mDNSu16 name_length
,
337 const mDNSu8 hash_type
,
338 const mDNSu8
* const _Nullable salt
,
339 const mDNSu32 salt_length
,
340 const mDNSu16 iterations
) {
342 mDNSu8 name_hash
[MAX_HASH_OUTPUT_SIZE
];
343 mDNSu32 name_hash_length
;
344 mDNSu8
*name_hash_b32
= mDNSNULL
;
346 name_hash_length
= get_hash_length_for_nsec3_hash_type(hash_type
);
348 mDNSBool calculated
= calculate_hash_for_nsec3(name_hash
, sizeof(name_hash
), hash_type
, name
, name_length
, salt
, salt_length
, iterations
);
349 require_quiet(calculated
, exit
);
351 name_hash_b32
= (mDNSu8
*)base_n_encode(DNSSEC_BASE_32_HEX
, name_hash
, name_hash_length
);
352 require_quiet(name_hash_b32
!= mDNSNULL
, exit
);
355 return name_hash_b32
;
358 //======================================================================================================================
359 // calculate_hash_for_nsec3
360 // get the hash value for nsec3 which includes salt and multiple iteration
361 //======================================================================================================================
364 calculate_hash_for_nsec3(
365 mDNSu8
* const _Nonnull hash_buffer
,
366 const mDNSu32 buffer_size
,
367 const mDNSu8 hash_type
,
368 const mDNSu8
* const _Nonnull name
,
369 const mDNSu16 name_length
,
370 const mDNSu8
* const _Nullable salt
,
371 const mDNSu32 salt_length
,
372 const mDNSu16 iterations
) {
374 // data_to_be_hashed will be used to generate the hash, it should be big enough to hold 1) first hash iteration: name | salt, 2) the remaining iteration: hash_result_from_the_last_iteration | salt.
375 mDNSu8 data_to_be_hashed
[MAX(MAX_HASH_OUTPUT_SIZE
, MAX_DOMAIN_NAME
) + 256];
378 digest_type_t digest_type
;
379 mDNSBool calculated
= mDNSfalse
;
381 memcpy(data_to_be_hashed
, name
, name_length
);
382 memcpy(data_to_be_hashed
+ name_length
, salt
, salt_length
);
383 data_length
= name_length
+ salt_length
;
385 // choose correct hash algorithm to get digest
387 case NSEC3_HASH_ALGORITHM_SHA_1
:
388 digest_type
= DIGEST_SHA_1
;
394 calculated
= calculate_digest_for_data(data_to_be_hashed
, data_length
, digest_type
, hash_buffer
, buffer_size
);
395 require_quiet(calculated
, exit
);
398 for (mDNSs32 i
= 0; i
< iterations
; i
++) {
399 memcpy(data_to_be_hashed
, hash_buffer
, hash_length
);
400 memcpy(data_to_be_hashed
+ hash_length
, salt
, salt_length
);
401 data_length
= hash_length
+ salt_length
;
403 calculated
= calculate_digest_for_data(data_to_be_hashed
, data_length
, hash_type
, hash_buffer
, buffer_size
);
404 require_quiet(calculated
, exit
);
407 calculated
= mDNStrue
;
412 //======================================================================================================================
413 // get_hash_length_for_nsec3_hash_type
414 //======================================================================================================================
417 get_hash_length_for_nsec3_hash_type(const nsec3_hash_algorithm_type_t nsec3_hash_type
) {
418 digest_type_t digest_type
;
420 switch (nsec3_hash_type
) {
421 case NSEC3_HASH_ALGORITHM_SHA_1
:
422 digest_type
= DIGEST_SHA_1
;
425 digest_type
= DIGEST_UNSUPPORTED
;
429 return get_digest_length_for_digest_type(digest_type
);
432 //======================================================================================================================
433 // get_digest_length_for_digest_type
434 //======================================================================================================================
437 get_digest_length_for_ds_digest_type(const ds_digest_type_t ds_digest_type
) {
438 digest_type_t digest_type
;
440 switch (ds_digest_type
) {
441 case DS_DIGEST_SHA_1
:
442 digest_type
= DIGEST_SHA_1
;
444 case DS_DIGEST_SHA_256
:
445 digest_type
= DIGEST_SHA_256
;
447 case DS_DIGEST_SHA_384
:
448 digest_type
= DIGEST_SHA_384
;
451 digest_type
= DIGEST_UNSUPPORTED
;
455 return get_digest_length_for_digest_type(digest_type
);
458 //======================================================================================================================
459 // get_digest_length_for_digest_type
460 //======================================================================================================================
463 get_digest_length_for_digest_type(const digest_type_t digest_type
) {
464 mDNSu32 digest_length
;
466 switch (digest_type
) {
468 digest_length
= SHA1_OUTPUT_SIZE
;
471 digest_length
= SHA256_OUTPUT_SIZE
;
474 digest_length
= SHA384_OUTPUT_SIZE
;
477 digest_length
= SHA512_OUTPUT_SIZE
;
484 return digest_length
;
487 //======================================================================================================================
489 // parse RSA key according to https://tools.ietf.org/html/rfc3110
490 //======================================================================================================================
494 mDNSu8
* const _Nonnull public_key
,
495 const mDNSu16 key_length
,
496 uint8_t ** const _Nonnull out_modulus
,
497 signed long * const _Nonnull out_modulus_length
,
498 uint8_t ** const _Nonnull out_exponent
,
499 signed long * const _Nonnull out_exponent_length
) {
501 mDNSu8 exponent_length_length
;
502 if (public_key
[0] != 0) {
503 *out_exponent_length
= public_key
[0];
504 exponent_length_length
= 1;
506 *out_exponent_length
= (((uint32_t)public_key
[1] << 8) | (uint32_t)public_key
[2]);
507 exponent_length_length
= 3;
510 *out_exponent
= public_key
+ exponent_length_length
;
512 *out_modulus_length
= key_length
- (*out_exponent_length
+ exponent_length_length
);
514 *out_modulus
= public_key
+ exponent_length_length
+ *out_exponent_length
;
517 //======================================================================================================================
518 // Canonical order and form
519 //======================================================================================================================
521 //======================================================================================================================
522 // canonical_form_name_length
523 //======================================================================================================================
526 canonical_form_name_length(const mDNSu8
* const _Nonnull name
) {
527 // assume that domainname* is already in canonical form
528 return DOMAIN_NAME_LENGTH(name
);
531 //======================================================================================================================
532 // compare_canonical_dns_name
533 // compare the domain name from the right most label, and compare label by label
534 //======================================================================================================================
537 compare_canonical_dns_name(const mDNSu8
* const _Nonnull left
, const mDNSu8
* const _Nonnull right
) {
538 const mDNSu16 left_len
= DOMAIN_NAME_LENGTH(left
);
539 const mDNSu8
* left_limit
= left
+ left_len
- 1;
540 const mDNSu16 right_len
= DOMAIN_NAME_LENGTH(right
);
541 const mDNSu8
* right_limit
= right
+ right_len
- 1;
544 const mDNSu8
* left_label_length_ptrs
[256];
545 mDNSu32 left_ptrs_size
= 0;
546 const mDNSu8
* right_label_length_ptrs
[256];
547 mDNSu32 right_ptrs_size
= 0;
549 // load the start of each label into an array
550 for (const mDNSu8
* left_ptr
= left
; left_ptr
< left_limit
; left_ptr
+= 1 + *left_ptr
) {
551 left_label_length_ptrs
[left_ptrs_size
++] = left_ptr
;
552 require_action(left_ptrs_size
< sizeof(left_label_length_ptrs
), exit
,
553 result
= 0; log_error("domain name has more than 255 labels, returning 0"));
556 for (const mDNSu8
* right_ptr
= right
; right_ptr
< right_limit
; right_ptr
+= 1 + *right_ptr
) {
557 right_label_length_ptrs
[right_ptrs_size
++] = right_ptr
;
558 require_action(right_ptrs_size
< sizeof(right_label_length_ptrs
), exit
,
559 result
= 0; log_error("domain name has more than 255 labels, returning 0"));
563 while (left_ptrs_size
> 0 && right_ptrs_size
> 0) {
564 const mDNSu8
* left_ptr
= left_label_length_ptrs
[left_ptrs_size
- 1];
565 const mDNSu8
* right_ptr
= right_label_length_ptrs
[right_ptrs_size
- 1];
566 const mDNSu8 left_label_length
= *left_ptr
;
567 const mDNSu8 right_label_length
= *right_ptr
;
569 mDNSs8 compare_label
= compare_canonical_dns_label(left_ptr
+ 1, left_label_length
, right_ptr
+ 1, right_label_length
);
570 require_action_quiet(compare_label
== 0, exit
, result
= compare_label
);
578 if (left_ptrs_size
== 0 && right_ptrs_size
== 0) {
580 } else if (left_ptrs_size
== 0) {
582 } else if (right_ptrs_size
== 0) {
585 log_error("Impossible case here");
593 //======================================================================================================================
594 // copy_canonical_name
595 // copy domain name to canonical form
596 //======================================================================================================================
599 copy_canonical_name(mDNSu8
* const _Nonnull dst
, const mDNSu8
* const _Nonnull name
) {
600 // assume that "name" is already fully expanded.
601 mDNSu16 name_length
= DOMAIN_NAME_LENGTH(name
);
602 mDNSu8
*ptr
= mDNSNULL
;
603 mDNSu32 bytes_convert
= 0;
605 require_action_quiet(name_length
> 0 && name_length
<= MAX_DOMAIN_NAME
, exit
, bytes_convert
= 0;
606 log_error("name is a malformed DNS name"));
607 memcpy(dst
, name
, name_length
);
609 for (ptr
= dst
; *ptr
!= 0; ptr
+= *ptr
+ 1) {
610 mDNSu8 label_length
= *ptr
;
611 mDNSu8
* label_end
= ptr
+ label_length
;
612 for (mDNSu8
*ch_ptr
= ptr
+ 1; ch_ptr
<= label_end
; ch_ptr
++) {
614 if (IS_UPPER_CASE(ch
)) {
615 *ch_ptr
= TO_LOWER_CASE(ch
);
620 bytes_convert
= ptr
+ 1 - dst
;
621 verify_action(bytes_convert
== name_length
,
622 log_error("convert more bytes than the actual name length; written=%u, name_length=%u", bytes_convert
, name_length
);
626 return bytes_convert
;
629 //======================================================================================================================
630 // compare_canonical_dns_label
631 //======================================================================================================================
634 compare_canonical_dns_label(
635 const mDNSu8
* _Nonnull left_label
,
636 const mDNSu8 left_label_length
,
637 const mDNSu8
* _Nonnull right_label
,
638 const mDNSu8 right_label_length
) {
640 mDNSu8 length_limit
= MIN(left_label_length
, right_label_length
);
642 for (mDNSu8 i
= 0; i
< length_limit
; i
++) {
643 mDNSu8 left_ch
= to_lowercase_if_char(*left_label
);
644 mDNSu8 right_ch
= to_lowercase_if_char(*right_label
);
645 if (left_ch
< right_ch
) return -1;
646 else if (left_ch
> right_ch
) return 1;
651 if (left_label_length
< right_label_length
) {
653 } else if (left_label_length
> right_label_length
) {
656 // left_label_length == right_label_length
663 copy_canonical_name_ut(mDNSu8
* const _Nonnull dst
, const mDNSu8
* const _Nonnull name
) {
664 return copy_canonical_name(dst
, name
);
669 print_validation_progress(const mDNSu32 request_id
, const dnssec_dnskey_t
* const dnskey
, const dnssec_rrsig_t
* const rrsig
) {
670 log_default("[R%u] "PRI_DM_NAME
": DNSKEY (alg=%u, tag=%u, length=%u) -----> " PRI_DM_NAME
": " PUB_S
, request_id
,
671 DM_NAME_PARAM(&dnskey
->dnssec_rr
.name
), dnskey
->algorithm
, dnskey
->key_tag
, dnskey
->public_key_length
,
672 DM_NAME_PARAM(&rrsig
->dnssec_rr
.name
), DNS_TYPE_STR(rrsig
->type_covered
));
675 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)