1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "dns-domain.h"
7 #include "gcrypt-util.h"
9 #include "memory-util.h"
10 #include "memstream-util.h"
11 #include "openssl-util.h"
12 #include "resolved-dns-dnssec.h"
13 #include "resolved-dns-packet.h"
14 #include "sort-util.h"
15 #include "string-table.h"
17 #if PREFER_OPENSSL && OPENSSL_VERSION_MAJOR >= 3
18 # pragma GCC diagnostic push
19 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
20 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA
*, RSA_free
, NULL
);
21 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY
*, EC_KEY_free
, NULL
);
22 # pragma GCC diagnostic pop
25 #define VERIFY_RRS_MAX 256
26 #define MAX_KEY_SIZE (32*1024)
28 /* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
29 #define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
31 /* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value, but
32 * RFC9276 § 3.2 says that we should reduce the acceptable iteration count */
33 #define NSEC3_ITERATIONS_MAX 100
36 * The DNSSEC Chain of trust:
38 * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone
39 * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree
40 * DS RRs are protected like normal RRs
43 * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
46 uint16_t dnssec_keytag(DnsResourceRecord
*dnskey
, bool mask_revoke
) {
50 /* The algorithm from RFC 4034, Appendix B. */
53 assert(dnskey
->key
->type
== DNS_TYPE_DNSKEY
);
55 f
= (uint32_t) dnskey
->dnskey
.flags
;
58 f
&= ~DNSKEY_FLAG_REVOKE
;
60 sum
= f
+ ((((uint32_t) dnskey
->dnskey
.protocol
) << 8) + (uint32_t) dnskey
->dnskey
.algorithm
);
62 p
= dnskey
->dnskey
.key
;
64 for (size_t i
= 0; i
< dnskey
->dnskey
.key_size
; i
++)
65 sum
+= (i
& 1) == 0 ? (uint32_t) p
[i
] << 8 : (uint32_t) p
[i
];
67 sum
+= (sum
>> 16) & UINT32_C(0xFFFF);
69 return sum
& UINT32_C(0xFFFF);
72 #if HAVE_OPENSSL_OR_GCRYPT
74 static int rr_compare(DnsResourceRecord
* const *a
, DnsResourceRecord
* const *b
) {
75 const DnsResourceRecord
*x
= *a
, *y
= *b
;
79 /* Let's order the RRs according to RFC 4034, Section 6.3 */
82 assert(x
->wire_format
);
84 assert(y
->wire_format
);
86 m
= MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(x
), DNS_RESOURCE_RECORD_RDATA_SIZE(y
));
88 r
= memcmp(DNS_RESOURCE_RECORD_RDATA(x
), DNS_RESOURCE_RECORD_RDATA(y
), m
);
92 return CMP(DNS_RESOURCE_RECORD_RDATA_SIZE(x
), DNS_RESOURCE_RECORD_RDATA_SIZE(y
));
95 static int dnssec_rsa_verify_raw(
96 hash_algorithm_t hash_algorithm
,
97 const void *signature
, size_t signature_size
,
98 const void *data
, size_t data_size
,
99 const void *exponent
, size_t exponent_size
,
100 const void *modulus
, size_t modulus_size
) {
104 # pragma GCC diagnostic push
105 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
106 _cleanup_(RSA_freep
) RSA
*rpubkey
= NULL
;
107 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*epubkey
= NULL
;
108 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= NULL
;
109 _cleanup_(BN_freep
) BIGNUM
*e
= NULL
, *m
= NULL
;
111 assert(hash_algorithm
);
113 e
= BN_bin2bn(exponent
, exponent_size
, NULL
);
117 m
= BN_bin2bn(modulus
, modulus_size
, NULL
);
125 if (RSA_set0_key(rpubkey
, m
, e
, NULL
) <= 0)
129 assert((size_t) RSA_size(rpubkey
) == signature_size
);
131 epubkey
= EVP_PKEY_new();
135 if (EVP_PKEY_assign_RSA(epubkey
, RSAPublicKey_dup(rpubkey
)) <= 0)
138 ctx
= EVP_PKEY_CTX_new(epubkey
, NULL
);
142 if (EVP_PKEY_verify_init(ctx
) <= 0)
145 if (EVP_PKEY_CTX_set_rsa_padding(ctx
, RSA_PKCS1_PADDING
) <= 0)
148 if (EVP_PKEY_CTX_set_signature_md(ctx
, hash_algorithm
) <= 0)
151 r
= EVP_PKEY_verify(ctx
, signature
, signature_size
, data
, data_size
);
153 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
154 "Signature verification failed: 0x%lx", ERR_get_error());
156 # pragma GCC diagnostic pop
158 gcry_sexp_t public_key_sexp
= NULL
, data_sexp
= NULL
, signature_sexp
= NULL
;
159 gcry_mpi_t n
= NULL
, e
= NULL
, s
= NULL
;
162 assert(hash_algorithm
);
164 ge
= gcry_mpi_scan(&s
, GCRYMPI_FMT_USG
, signature
, signature_size
, NULL
);
170 ge
= gcry_mpi_scan(&e
, GCRYMPI_FMT_USG
, exponent
, exponent_size
, NULL
);
176 ge
= gcry_mpi_scan(&n
, GCRYMPI_FMT_USG
, modulus
, modulus_size
, NULL
);
182 ge
= gcry_sexp_build(&signature_sexp
,
184 "(sig-val (rsa (s %m)))",
192 ge
= gcry_sexp_build(&data_sexp
,
194 "(data (flags pkcs1) (hash %s %b))",
203 ge
= gcry_sexp_build(&public_key_sexp
,
205 "(public-key (rsa (n %m) (e %m)))",
213 ge
= gcry_pk_verify(signature_sexp
, data_sexp
, public_key_sexp
);
214 if (gpg_err_code(ge
) == GPG_ERR_BAD_SIGNATURE
)
217 r
= log_debug_errno(SYNTHETIC_ERRNO(EIO
),
218 "RSA signature check failed: %s", gpg_strerror(ge
));
231 gcry_sexp_release(public_key_sexp
);
233 gcry_sexp_release(signature_sexp
);
235 gcry_sexp_release(data_sexp
);
240 static int dnssec_rsa_verify(
241 hash_algorithm_t hash_algorithm
,
242 const void *hash
, size_t hash_size
,
243 DnsResourceRecord
*rrsig
,
244 DnsResourceRecord
*dnskey
) {
246 size_t exponent_size
, modulus_size
;
247 void *exponent
, *modulus
;
249 assert(hash_algorithm
);
251 assert(hash_size
> 0);
255 if (*(uint8_t*) dnskey
->dnskey
.key
== 0) {
256 /* exponent is > 255 bytes long */
258 exponent
= (uint8_t*) dnskey
->dnskey
.key
+ 3;
260 ((size_t) (((uint8_t*) dnskey
->dnskey
.key
)[1]) << 8) |
261 ((size_t) ((uint8_t*) dnskey
->dnskey
.key
)[2]);
263 if (exponent_size
< 256)
266 if (3 + exponent_size
>= dnskey
->dnskey
.key_size
)
269 modulus
= (uint8_t*) dnskey
->dnskey
.key
+ 3 + exponent_size
;
270 modulus_size
= dnskey
->dnskey
.key_size
- 3 - exponent_size
;
273 /* exponent is <= 255 bytes long */
275 exponent
= (uint8_t*) dnskey
->dnskey
.key
+ 1;
276 exponent_size
= (size_t) ((uint8_t*) dnskey
->dnskey
.key
)[0];
278 if (exponent_size
<= 0)
281 if (1 + exponent_size
>= dnskey
->dnskey
.key_size
)
284 modulus
= (uint8_t*) dnskey
->dnskey
.key
+ 1 + exponent_size
;
285 modulus_size
= dnskey
->dnskey
.key_size
- 1 - exponent_size
;
288 return dnssec_rsa_verify_raw(
290 rrsig
->rrsig
.signature
, rrsig
->rrsig
.signature_size
,
292 exponent
, exponent_size
,
293 modulus
, modulus_size
);
296 static int dnssec_ecdsa_verify_raw(
297 hash_algorithm_t hash_algorithm
,
298 elliptic_curve_t curve
,
299 const void *signature_r
, size_t signature_r_size
,
300 const void *signature_s
, size_t signature_s_size
,
301 const void *data
, size_t data_size
,
302 const void *key
, size_t key_size
) {
306 # pragma GCC diagnostic push
307 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
308 _cleanup_(EC_GROUP_freep
) EC_GROUP
*ec_group
= NULL
;
309 _cleanup_(EC_POINT_freep
) EC_POINT
*p
= NULL
;
310 _cleanup_(EC_KEY_freep
) EC_KEY
*eckey
= NULL
;
311 _cleanup_(BN_CTX_freep
) BN_CTX
*bctx
= NULL
;
312 _cleanup_(BN_freep
) BIGNUM
*r
= NULL
, *s
= NULL
;
313 _cleanup_(ECDSA_SIG_freep
) ECDSA_SIG
*sig
= NULL
;
315 assert(hash_algorithm
);
317 ec_group
= EC_GROUP_new_by_curve_name(curve
);
321 p
= EC_POINT_new(ec_group
);
329 if (EC_POINT_oct2point(ec_group
, p
, key
, key_size
, bctx
) <= 0)
332 eckey
= EC_KEY_new();
336 if (EC_KEY_set_group(eckey
, ec_group
) <= 0)
339 if (EC_KEY_set_public_key(eckey
, p
) <= 0)
340 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
341 "EC_POINT_bn2point failed: 0x%lx", ERR_get_error());
343 assert(EC_KEY_check_key(eckey
) == 1);
345 r
= BN_bin2bn(signature_r
, signature_r_size
, NULL
);
349 s
= BN_bin2bn(signature_s
, signature_s_size
, NULL
);
353 /* TODO: We should eventually use the EVP API once it supports ECDSA signature verification */
355 sig
= ECDSA_SIG_new();
359 if (ECDSA_SIG_set0(sig
, r
, s
) <= 0)
363 k
= ECDSA_do_verify(data
, data_size
, sig
, eckey
);
365 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
366 "Signature verification failed: 0x%lx", ERR_get_error());
368 # pragma GCC diagnostic pop
370 gcry_sexp_t public_key_sexp
= NULL
, data_sexp
= NULL
, signature_sexp
= NULL
;
371 gcry_mpi_t q
= NULL
, r
= NULL
, s
= NULL
;
374 assert(hash_algorithm
);
376 ge
= gcry_mpi_scan(&r
, GCRYMPI_FMT_USG
, signature_r
, signature_r_size
, NULL
);
382 ge
= gcry_mpi_scan(&s
, GCRYMPI_FMT_USG
, signature_s
, signature_s_size
, NULL
);
388 ge
= gcry_mpi_scan(&q
, GCRYMPI_FMT_USG
, key
, key_size
, NULL
);
394 ge
= gcry_sexp_build(&signature_sexp
,
396 "(sig-val (ecdsa (r %m) (s %m)))",
404 ge
= gcry_sexp_build(&data_sexp
,
406 "(data (flags rfc6979) (hash %s %b))",
415 ge
= gcry_sexp_build(&public_key_sexp
,
417 "(public-key (ecc (curve %s) (q %m)))",
425 ge
= gcry_pk_verify(signature_sexp
, data_sexp
, public_key_sexp
);
426 if (gpg_err_code(ge
) == GPG_ERR_BAD_SIGNATURE
)
429 log_debug("ECDSA signature check failed: %s", gpg_strerror(ge
));
442 gcry_sexp_release(public_key_sexp
);
444 gcry_sexp_release(signature_sexp
);
446 gcry_sexp_release(data_sexp
);
451 static int dnssec_ecdsa_verify(
452 hash_algorithm_t hash_algorithm
,
454 const void *hash
, size_t hash_size
,
455 DnsResourceRecord
*rrsig
,
456 DnsResourceRecord
*dnskey
) {
458 elliptic_curve_t curve
;
467 if (algorithm
== DNSSEC_ALGORITHM_ECDSAP256SHA256
) {
468 curve
= OPENSSL_OR_GCRYPT(NID_X9_62_prime256v1
, "NIST P-256"); /* NIST P-256 */
470 } else if (algorithm
== DNSSEC_ALGORITHM_ECDSAP384SHA384
) {
471 curve
= OPENSSL_OR_GCRYPT(NID_secp384r1
, "NIST P-384"); /* NIST P-384 */
476 if (dnskey
->dnskey
.key_size
!= key_size
* 2)
479 if (rrsig
->rrsig
.signature_size
!= key_size
* 2)
482 q
= newa(uint8_t, key_size
*2 + 1);
483 q
[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
484 memcpy(q
+1, dnskey
->dnskey
.key
, key_size
*2);
486 return dnssec_ecdsa_verify_raw(
489 rrsig
->rrsig
.signature
, key_size
,
490 (uint8_t*) rrsig
->rrsig
.signature
+ key_size
, key_size
,
495 static int dnssec_eddsa_verify_raw(
496 elliptic_curve_t curve
,
497 const uint8_t *signature
, size_t signature_size
,
498 const uint8_t *data
, size_t data_size
,
499 const uint8_t *key
, size_t key_size
) {
502 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*evkey
= NULL
;
503 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*pctx
= NULL
;
504 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
*ctx
= NULL
;
507 assert(curve
== NID_ED25519
);
508 assert(signature_size
== key_size
* 2);
510 uint8_t *q
= newa(uint8_t, signature_size
+ 1);
511 q
[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
512 memcpy(q
+1, signature
, signature_size
);
514 evkey
= EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519
, NULL
, key
, key_size
);
516 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
517 "EVP_PKEY_new_raw_public_key failed: 0x%lx", ERR_get_error());
519 pctx
= EVP_PKEY_CTX_new(evkey
, NULL
);
523 ctx
= EVP_MD_CTX_new();
527 /* This prevents EVP_DigestVerifyInit from managing pctx and complicating our free logic. */
528 EVP_MD_CTX_set_pkey_ctx(ctx
, pctx
);
530 /* One might be tempted to use EVP_PKEY_verify_init, but see Ed25519(7ssl). */
531 if (EVP_DigestVerifyInit(ctx
, &pctx
, NULL
, NULL
, evkey
) <= 0)
534 r
= EVP_DigestVerify(ctx
, signature
, signature_size
, data
, data_size
);
536 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
537 "Signature verification failed: 0x%lx", ERR_get_error());
541 #elif GCRYPT_VERSION_NUMBER >= 0x010600
542 gcry_sexp_t public_key_sexp
= NULL
, data_sexp
= NULL
, signature_sexp
= NULL
;
546 assert(signature_size
== key_size
* 2);
548 ge
= gcry_sexp_build(&signature_sexp
,
550 "(sig-val (eddsa (r %b) (s %b)))",
554 signature
+ key_size
);
560 ge
= gcry_sexp_build(&data_sexp
,
562 "(data (flags eddsa) (hash-algo sha512) (value %b))",
570 ge
= gcry_sexp_build(&public_key_sexp
,
572 "(public-key (ecc (curve %s) (flags eddsa) (q %b)))",
581 ge
= gcry_pk_verify(signature_sexp
, data_sexp
, public_key_sexp
);
582 if (gpg_err_code(ge
) == GPG_ERR_BAD_SIGNATURE
)
585 k
= log_debug_errno(SYNTHETIC_ERRNO(EIO
),
586 "EdDSA signature check failed: %s", gpg_strerror(ge
));
591 gcry_sexp_release(public_key_sexp
);
593 gcry_sexp_release(signature_sexp
);
595 gcry_sexp_release(data_sexp
);
603 static int dnssec_eddsa_verify(
605 const void *data
, size_t data_size
,
606 DnsResourceRecord
*rrsig
,
607 DnsResourceRecord
*dnskey
) {
608 elliptic_curve_t curve
;
611 if (algorithm
== DNSSEC_ALGORITHM_ED25519
) {
612 curve
= OPENSSL_OR_GCRYPT(NID_ED25519
, "Ed25519");
617 if (dnskey
->dnskey
.key_size
!= key_size
)
620 if (rrsig
->rrsig
.signature_size
!= key_size
* 2)
623 return dnssec_eddsa_verify_raw(
625 rrsig
->rrsig
.signature
, rrsig
->rrsig
.signature_size
,
627 dnskey
->dnskey
.key
, key_size
);
630 static int md_add_uint8(hash_context_t ctx
, uint8_t v
) {
632 return EVP_DigestUpdate(ctx
, &v
, sizeof(v
));
634 gcry_md_write(ctx
, &v
, sizeof(v
));
639 static int md_add_uint16(hash_context_t ctx
, uint16_t v
) {
642 return EVP_DigestUpdate(ctx
, &v
, sizeof(v
));
644 gcry_md_write(ctx
, &v
, sizeof(v
));
649 static void fwrite_uint8(FILE *fp
, uint8_t v
) {
650 fwrite(&v
, sizeof(v
), 1, fp
);
653 static void fwrite_uint16(FILE *fp
, uint16_t v
) {
655 fwrite(&v
, sizeof(v
), 1, fp
);
658 static void fwrite_uint32(FILE *fp
, uint32_t v
) {
660 fwrite(&v
, sizeof(v
), 1, fp
);
663 static int dnssec_rrsig_prepare(DnsResourceRecord
*rrsig
) {
664 int n_key_labels
, n_signer_labels
;
668 /* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source
669 * and .n_skip_labels_signer fields so that we can use them later on. */
672 assert(rrsig
->key
->type
== DNS_TYPE_RRSIG
);
674 /* Check if this RRSIG RR is already prepared */
675 if (rrsig
->n_skip_labels_source
!= UINT8_MAX
)
678 if (rrsig
->rrsig
.inception
> rrsig
->rrsig
.expiration
)
681 name
= dns_resource_key_name(rrsig
->key
);
683 n_key_labels
= dns_name_count_labels(name
);
684 if (n_key_labels
< 0)
686 if (rrsig
->rrsig
.labels
> n_key_labels
)
689 n_signer_labels
= dns_name_count_labels(rrsig
->rrsig
.signer
);
690 if (n_signer_labels
< 0)
691 return n_signer_labels
;
692 if (n_signer_labels
> rrsig
->rrsig
.labels
)
695 r
= dns_name_skip(name
, n_key_labels
- n_signer_labels
, &name
);
701 /* Check if the signer is really a suffix of us */
702 r
= dns_name_equal(name
, rrsig
->rrsig
.signer
);
708 assert(n_key_labels
< UINT8_MAX
); /* UINT8_MAX/-1 means unsigned. */
709 rrsig
->n_skip_labels_source
= n_key_labels
- rrsig
->rrsig
.labels
;
710 rrsig
->n_skip_labels_signer
= n_key_labels
- n_signer_labels
;
715 static int dnssec_rrsig_expired(DnsResourceRecord
*rrsig
, usec_t realtime
) {
716 usec_t expiration
, inception
, skew
;
719 assert(rrsig
->key
->type
== DNS_TYPE_RRSIG
);
721 if (realtime
== USEC_INFINITY
)
722 realtime
= now(CLOCK_REALTIME
);
724 expiration
= rrsig
->rrsig
.expiration
* USEC_PER_SEC
;
725 inception
= rrsig
->rrsig
.inception
* USEC_PER_SEC
;
727 /* Consider inverted validity intervals as expired */
728 if (inception
> expiration
)
731 /* Permit a certain amount of clock skew of 10% of the valid
732 * time range. This takes inspiration from unbound's
734 skew
= (expiration
- inception
) / 10;
738 if (inception
< skew
)
743 if (expiration
+ skew
< expiration
)
744 expiration
= USEC_INFINITY
;
748 return realtime
< inception
|| realtime
> expiration
;
751 static hash_md_t
algorithm_to_implementation_id(uint8_t algorithm
) {
753 /* Translates a DNSSEC signature algorithm into an openssl/gcrypt digest identifier.
755 * Note that we implement all algorithms listed as "Must implement" and "Recommended to Implement" in
756 * RFC6944. We don't implement any algorithms that are listed as "Optional" or "Must Not Implement".
757 * Specifically, we do not implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and GOST-ECC. */
761 case DNSSEC_ALGORITHM_RSASHA1
:
762 case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
:
763 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1
);
765 case DNSSEC_ALGORITHM_RSASHA256
:
766 case DNSSEC_ALGORITHM_ECDSAP256SHA256
:
767 return OPENSSL_OR_GCRYPT(EVP_sha256(), GCRY_MD_SHA256
);
769 case DNSSEC_ALGORITHM_ECDSAP384SHA384
:
770 return OPENSSL_OR_GCRYPT(EVP_sha384(), GCRY_MD_SHA384
);
772 case DNSSEC_ALGORITHM_RSASHA512
:
773 return OPENSSL_OR_GCRYPT(EVP_sha512(), GCRY_MD_SHA512
);
776 return OPENSSL_OR_GCRYPT(NULL
, -EOPNOTSUPP
);
780 static void dnssec_fix_rrset_ttl(
781 DnsResourceRecord
*list
[],
783 DnsResourceRecord
*rrsig
) {
789 for (unsigned k
= 0; k
< n
; k
++) {
790 DnsResourceRecord
*rr
= list
[k
];
792 /* Pick the TTL as the minimum of the RR's TTL, the
793 * RR's original TTL according to the RRSIG and the
794 * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
795 rr
->ttl
= MIN3(rr
->ttl
, rrsig
->rrsig
.original_ttl
, rrsig
->ttl
);
796 rr
->expiry
= rrsig
->rrsig
.expiration
* USEC_PER_SEC
;
798 /* Copy over information about the signer and wildcard source of synthesis */
799 rr
->n_skip_labels_source
= rrsig
->n_skip_labels_source
;
800 rr
->n_skip_labels_signer
= rrsig
->n_skip_labels_signer
;
803 rrsig
->expiry
= rrsig
->rrsig
.expiration
* USEC_PER_SEC
;
806 static int dnssec_rrset_serialize_sig(
807 DnsResourceRecord
*rrsig
,
809 DnsResourceRecord
**list
,
813 size_t *ret_sig_size
) {
815 _cleanup_(memstream_done
) MemStream m
= {};
816 uint8_t wire_format_name
[DNS_WIRE_FORMAT_HOSTNAME_MAX
];
817 DnsResourceRecord
*rr
;
823 assert(list
|| list_len
== 0);
824 assert(ret_sig_data
);
825 assert(ret_sig_size
);
827 f
= memstream_init(&m
);
831 fwrite_uint16(f
, rrsig
->rrsig
.type_covered
);
832 fwrite_uint8(f
, rrsig
->rrsig
.algorithm
);
833 fwrite_uint8(f
, rrsig
->rrsig
.labels
);
834 fwrite_uint32(f
, rrsig
->rrsig
.original_ttl
);
835 fwrite_uint32(f
, rrsig
->rrsig
.expiration
);
836 fwrite_uint32(f
, rrsig
->rrsig
.inception
);
837 fwrite_uint16(f
, rrsig
->rrsig
.key_tag
);
839 r
= dns_name_to_wire_format(rrsig
->rrsig
.signer
, wire_format_name
, sizeof(wire_format_name
), true);
842 fwrite(wire_format_name
, 1, r
, f
);
844 /* Convert the source of synthesis into wire format */
845 r
= dns_name_to_wire_format(source
, wire_format_name
, sizeof(wire_format_name
), true);
849 for (size_t k
= 0; k
< list_len
; k
++) {
854 /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */
856 fwrite((uint8_t[]) { 1, '*'}, sizeof(uint8_t), 2, f
);
857 fwrite(wire_format_name
, 1, r
, f
);
859 fwrite_uint16(f
, rr
->key
->type
);
860 fwrite_uint16(f
, rr
->key
->class);
861 fwrite_uint32(f
, rrsig
->rrsig
.original_ttl
);
863 l
= DNS_RESOURCE_RECORD_RDATA_SIZE(rr
);
866 fwrite_uint16(f
, (uint16_t) l
);
867 fwrite(DNS_RESOURCE_RECORD_RDATA(rr
), 1, l
, f
);
870 return memstream_finalize(&m
, ret_sig_data
, ret_sig_size
);
873 static int dnssec_rrset_verify_sig(
874 DnsResourceRecord
*rrsig
,
875 DnsResourceRecord
*dnskey
,
876 const char *sig_data
,
882 assert(sig_size
> 0);
884 hash_md_t md_algorithm
;
887 uint8_t hash
[EVP_MAX_MD_SIZE
];
890 _cleanup_(gcry_md_closep
) gcry_md_hd_t md
= NULL
;
895 r
= initialize_libgcrypt(false);
900 switch (rrsig
->rrsig
.algorithm
) {
901 case DNSSEC_ALGORITHM_ED25519
:
902 #if PREFER_OPENSSL || GCRYPT_VERSION_NUMBER >= 0x010600
903 return dnssec_eddsa_verify(
904 rrsig
->rrsig
.algorithm
,
909 case DNSSEC_ALGORITHM_ED448
:
912 /* OK, the RRs are now in canonical order. Let's calculate the digest */
913 md_algorithm
= algorithm_to_implementation_id(rrsig
->rrsig
.algorithm
);
918 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
922 if (EVP_DigestInit_ex(ctx
, md_algorithm
, NULL
) <= 0)
925 if (EVP_DigestUpdate(ctx
, sig_data
, sig_size
) <= 0)
928 if (EVP_DigestFinal_ex(ctx
, hash
, &hash_size
) <= 0)
931 assert(hash_size
> 0);
934 if (md_algorithm
< 0)
937 gcry_error_t err
= gcry_md_open(&md
, md_algorithm
, 0);
938 if (gcry_err_code(err
) != GPG_ERR_NO_ERROR
|| !md
)
941 hash_size
= gcry_md_get_algo_dlen(md_algorithm
);
942 assert(hash_size
> 0);
944 gcry_md_write(md
, sig_data
, sig_size
);
946 hash
= gcry_md_read(md
, 0);
952 switch (rrsig
->rrsig
.algorithm
) {
954 case DNSSEC_ALGORITHM_RSASHA1
:
955 case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
:
956 case DNSSEC_ALGORITHM_RSASHA256
:
957 case DNSSEC_ALGORITHM_RSASHA512
:
958 return dnssec_rsa_verify(
959 OPENSSL_OR_GCRYPT(md_algorithm
, gcry_md_algo_name(md_algorithm
)),
964 case DNSSEC_ALGORITHM_ECDSAP256SHA256
:
965 case DNSSEC_ALGORITHM_ECDSAP384SHA384
:
966 return dnssec_ecdsa_verify(
967 OPENSSL_OR_GCRYPT(md_algorithm
, gcry_md_algo_name(md_algorithm
)),
968 rrsig
->rrsig
.algorithm
,
974 assert_not_reached();
978 int dnssec_verify_rrset(
980 const DnsResourceKey
*key
,
981 DnsResourceRecord
*rrsig
,
982 DnsResourceRecord
*dnskey
,
984 DnssecResult
*result
) {
986 DnsResourceRecord
**list
, *rr
;
987 const char *source
, *name
;
988 _cleanup_free_
char *sig_data
= NULL
;
989 size_t sig_size
= 0; /* avoid false maybe-uninitialized warning */
998 assert(rrsig
->key
->type
== DNS_TYPE_RRSIG
);
999 assert(dnskey
->key
->type
== DNS_TYPE_DNSKEY
);
1001 /* Verifies that the RRSet matches the specified "key" in "a",
1002 * using the signature "rrsig" and the key "dnskey". It's
1003 * assumed that RRSIG and DNSKEY match. */
1005 r
= dnssec_rrsig_prepare(rrsig
);
1007 *result
= DNSSEC_INVALID
;
1013 r
= dnssec_rrsig_expired(rrsig
, realtime
);
1017 *result
= DNSSEC_SIGNATURE_EXPIRED
;
1021 name
= dns_resource_key_name(key
);
1023 /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
1024 if (dns_type_apex_only(rrsig
->rrsig
.type_covered
)) {
1025 r
= dns_name_equal(rrsig
->rrsig
.signer
, name
);
1029 *result
= DNSSEC_INVALID
;
1034 /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */
1035 if (rrsig
->rrsig
.type_covered
== DNS_TYPE_DS
) {
1036 r
= dns_name_equal(rrsig
->rrsig
.signer
, name
);
1040 *result
= DNSSEC_INVALID
;
1045 /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
1046 r
= dns_name_suffix(name
, rrsig
->rrsig
.labels
, &source
);
1049 if (r
> 0 && !dns_type_may_wildcard(rrsig
->rrsig
.type_covered
)) {
1050 /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */
1051 *result
= DNSSEC_INVALID
;
1055 /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really
1056 * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */
1057 r
= dns_name_startswith(name
, "*");
1067 /* Collect all relevant RRs in a single array, so that we can look at the RRset */
1068 list
= newa(DnsResourceRecord
*, dns_answer_size(a
));
1070 DNS_ANSWER_FOREACH(rr
, a
) {
1071 r
= dns_resource_key_equal(key
, rr
->key
);
1077 /* We need the wire format for ordering, and digest calculation */
1078 r
= dns_resource_record_to_wire_format(rr
, true);
1084 if (n
> VERIFY_RRS_MAX
)
1091 /* Bring the RRs into canonical order */
1092 typesafe_qsort(list
, n
, rr_compare
);
1094 r
= dnssec_rrset_serialize_sig(rrsig
, source
, list
, n
, wildcard
,
1095 &sig_data
, &sig_size
);
1099 r
= dnssec_rrset_verify_sig(rrsig
, dnskey
, sig_data
, sig_size
);
1100 if (r
== -EOPNOTSUPP
) {
1101 *result
= DNSSEC_UNSUPPORTED_ALGORITHM
;
1107 /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */
1109 dnssec_fix_rrset_ttl(list
, n
, rrsig
);
1112 *result
= DNSSEC_INVALID
;
1114 *result
= DNSSEC_VALIDATED_WILDCARD
;
1116 *result
= DNSSEC_VALIDATED
;
1121 int dnssec_rrsig_match_dnskey(DnsResourceRecord
*rrsig
, DnsResourceRecord
*dnskey
, bool revoked_ok
) {
1126 /* Checks if the specified DNSKEY RR matches the key used for
1127 * the signature in the specified RRSIG RR */
1129 if (rrsig
->key
->type
!= DNS_TYPE_RRSIG
)
1132 if (dnskey
->key
->type
!= DNS_TYPE_DNSKEY
)
1134 if (dnskey
->key
->class != rrsig
->key
->class)
1136 if ((dnskey
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
) == 0)
1138 if (!revoked_ok
&& (dnskey
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
))
1140 if (dnskey
->dnskey
.protocol
!= 3)
1142 if (dnskey
->dnskey
.algorithm
!= rrsig
->rrsig
.algorithm
)
1145 if (dnssec_keytag(dnskey
, false) != rrsig
->rrsig
.key_tag
)
1148 return dns_name_equal(dns_resource_key_name(dnskey
->key
), rrsig
->rrsig
.signer
);
1151 int dnssec_key_match_rrsig(const DnsResourceKey
*key
, DnsResourceRecord
*rrsig
) {
1155 /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
1157 if (rrsig
->key
->type
!= DNS_TYPE_RRSIG
)
1159 if (rrsig
->key
->class != key
->class)
1161 if (rrsig
->rrsig
.type_covered
!= key
->type
)
1164 return dns_name_equal(dns_resource_key_name(rrsig
->key
), dns_resource_key_name(key
));
1167 int dnssec_verify_rrset_search(
1169 const DnsResourceKey
*key
,
1170 DnsAnswer
*validated_dnskeys
,
1172 DnssecResult
*result
,
1173 DnsResourceRecord
**ret_rrsig
) {
1175 bool found_rrsig
= false, found_invalid
= false, found_expired_rrsig
= false, found_unsupported_algorithm
= false;
1176 unsigned nvalidations
= 0;
1177 DnsResourceRecord
*rrsig
;
1183 /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
1185 if (dns_answer_isempty(a
))
1188 /* Iterate through each RRSIG RR. */
1189 DNS_ANSWER_FOREACH(rrsig
, a
) {
1190 DnsResourceRecord
*dnskey
;
1191 DnsAnswerFlags flags
;
1193 /* Is this an RRSIG RR that applies to RRs matching our key? */
1194 r
= dnssec_key_match_rrsig(key
, rrsig
);
1202 /* Look for a matching key */
1203 DNS_ANSWER_FOREACH_FLAGS(dnskey
, flags
, validated_dnskeys
) {
1204 DnssecResult one_result
;
1206 if ((flags
& DNS_ANSWER_AUTHENTICATED
) == 0)
1209 /* Is this a DNSKEY RR that matches they key of our RRSIG? */
1210 r
= dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false);
1216 /* Take the time here, if it isn't set yet, so
1217 * that we do all validations with the same
1219 if (realtime
== USEC_INFINITY
)
1220 realtime
= now(CLOCK_REALTIME
);
1222 /* Have we seen an unreasonable number of invalid signatures? */
1223 if (nvalidations
> DNSSEC_INVALID_MAX
) {
1226 *result
= DNSSEC_TOO_MANY_VALIDATIONS
;
1227 return (int) nvalidations
;
1230 /* Yay, we found a matching RRSIG with a matching
1231 * DNSKEY, awesome. Now let's verify all entries of
1232 * the RRSet against the RRSIG and DNSKEY
1235 r
= dnssec_verify_rrset(a
, key
, rrsig
, dnskey
, realtime
, &one_result
);
1241 switch (one_result
) {
1243 case DNSSEC_VALIDATED
:
1244 case DNSSEC_VALIDATED_WILDCARD
:
1245 /* Yay, the RR has been validated,
1246 * return immediately, but fix up the expiry */
1250 *result
= one_result
;
1251 return (int) nvalidations
;
1253 case DNSSEC_INVALID
:
1254 /* If the signature is invalid, let's try another
1255 key and/or signature. After all they
1256 key_tags and stuff are not unique, and
1257 might be shared by multiple keys. */
1258 found_invalid
= true;
1261 case DNSSEC_UNSUPPORTED_ALGORITHM
:
1262 /* If the key algorithm is
1263 unsupported, try another
1264 RRSIG/DNSKEY pair, but remember we
1265 encountered this, so that we can
1266 return a proper error when we
1267 encounter nothing better. */
1268 found_unsupported_algorithm
= true;
1271 case DNSSEC_SIGNATURE_EXPIRED
:
1272 /* If the signature is expired, try
1273 another one, but remember it, so
1274 that we can return this */
1275 found_expired_rrsig
= true;
1279 assert_not_reached();
1284 if (found_expired_rrsig
)
1285 *result
= DNSSEC_SIGNATURE_EXPIRED
;
1286 else if (found_unsupported_algorithm
)
1287 *result
= DNSSEC_UNSUPPORTED_ALGORITHM
;
1288 else if (found_invalid
)
1289 *result
= DNSSEC_INVALID
;
1290 else if (found_rrsig
)
1291 *result
= DNSSEC_MISSING_KEY
;
1293 *result
= DNSSEC_NO_SIGNATURE
;
1298 return (int) nvalidations
;
1301 int dnssec_has_rrsig(DnsAnswer
*a
, const DnsResourceKey
*key
) {
1302 DnsResourceRecord
*rr
;
1305 /* Checks whether there's at least one RRSIG in 'a' that protects RRs of the specified key */
1307 DNS_ANSWER_FOREACH(rr
, a
) {
1308 r
= dnssec_key_match_rrsig(key
, rr
);
1318 static hash_md_t
digest_to_hash_md(uint8_t algorithm
) {
1320 /* Translates a DNSSEC digest algorithm into an openssl/gcrypt digest identifier */
1322 switch (algorithm
) {
1324 case DNSSEC_DIGEST_SHA1
:
1325 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1
);
1327 case DNSSEC_DIGEST_SHA256
:
1328 return OPENSSL_OR_GCRYPT(EVP_sha256(), GCRY_MD_SHA256
);
1330 case DNSSEC_DIGEST_SHA384
:
1331 return OPENSSL_OR_GCRYPT(EVP_sha384(), GCRY_MD_SHA384
);
1334 return OPENSSL_OR_GCRYPT(NULL
, -EOPNOTSUPP
);
1338 int dnssec_verify_dnskey_by_ds(DnsResourceRecord
*dnskey
, DnsResourceRecord
*ds
, bool mask_revoke
) {
1339 uint8_t wire_format
[DNS_WIRE_FORMAT_HOSTNAME_MAX
];
1340 size_t encoded_length
;
1346 /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
1348 if (dnskey
->key
->type
!= DNS_TYPE_DNSKEY
)
1350 if (ds
->key
->type
!= DNS_TYPE_DS
)
1352 if ((dnskey
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
) == 0)
1353 return -EKEYREJECTED
;
1354 if (!mask_revoke
&& (dnskey
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
))
1355 return -EKEYREJECTED
;
1356 if (dnskey
->dnskey
.protocol
!= 3)
1357 return -EKEYREJECTED
;
1359 if (dnskey
->dnskey
.algorithm
!= ds
->ds
.algorithm
)
1361 if (dnssec_keytag(dnskey
, mask_revoke
) != ds
->ds
.key_tag
)
1364 r
= dns_name_to_wire_format(dns_resource_key_name(dnskey
->key
), wire_format
, sizeof wire_format
, true);
1369 hash_md_t md_algorithm
= digest_to_hash_md(ds
->ds
.digest_type
);
1375 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
*ctx
= NULL
;
1376 uint8_t result
[EVP_MAX_MD_SIZE
];
1378 unsigned hash_size
= EVP_MD_size(md_algorithm
);
1379 assert(hash_size
> 0);
1381 if (ds
->ds
.digest_size
!= hash_size
)
1384 ctx
= EVP_MD_CTX_new();
1388 if (EVP_DigestInit_ex(ctx
, md_algorithm
, NULL
) <= 0)
1391 if (EVP_DigestUpdate(ctx
, wire_format
, encoded_length
) <= 0)
1395 md_add_uint16(ctx
, dnskey
->dnskey
.flags
& ~DNSKEY_FLAG_REVOKE
);
1397 md_add_uint16(ctx
, dnskey
->dnskey
.flags
);
1399 r
= md_add_uint8(ctx
, dnskey
->dnskey
.protocol
);
1402 r
= md_add_uint8(ctx
, dnskey
->dnskey
.algorithm
);
1405 if (EVP_DigestUpdate(ctx
, dnskey
->dnskey
.key
, dnskey
->dnskey
.key_size
) <= 0)
1408 if (EVP_DigestFinal_ex(ctx
, result
, NULL
) <= 0)
1412 if (md_algorithm
< 0)
1415 r
= initialize_libgcrypt(false);
1419 _cleanup_(gcry_md_closep
) gcry_md_hd_t md
= NULL
;
1421 size_t hash_size
= gcry_md_get_algo_dlen(md_algorithm
);
1422 assert(hash_size
> 0);
1424 if (ds
->ds
.digest_size
!= hash_size
)
1427 gcry_error_t err
= gcry_md_open(&md
, md_algorithm
, 0);
1428 if (gcry_err_code(err
) != GPG_ERR_NO_ERROR
|| !md
)
1431 gcry_md_write(md
, wire_format
, encoded_length
);
1433 md_add_uint16(md
, dnskey
->dnskey
.flags
& ~DNSKEY_FLAG_REVOKE
);
1435 md_add_uint16(md
, dnskey
->dnskey
.flags
);
1436 md_add_uint8(md
, dnskey
->dnskey
.protocol
);
1437 md_add_uint8(md
, dnskey
->dnskey
.algorithm
);
1438 gcry_md_write(md
, dnskey
->dnskey
.key
, dnskey
->dnskey
.key_size
);
1440 void *result
= gcry_md_read(md
, 0);
1445 return memcmp(result
, ds
->ds
.digest
, ds
->ds
.digest_size
) == 0;
1448 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord
*dnskey
, DnsAnswer
*validated_ds
) {
1449 DnsResourceRecord
*ds
;
1450 DnsAnswerFlags flags
;
1455 if (dnskey
->key
->type
!= DNS_TYPE_DNSKEY
)
1458 DNS_ANSWER_FOREACH_FLAGS(ds
, flags
, validated_ds
) {
1460 if ((flags
& DNS_ANSWER_AUTHENTICATED
) == 0)
1463 if (ds
->key
->type
!= DNS_TYPE_DS
)
1465 if (ds
->key
->class != dnskey
->key
->class)
1468 r
= dns_name_equal(dns_resource_key_name(dnskey
->key
), dns_resource_key_name(ds
->key
));
1474 r
= dnssec_verify_dnskey_by_ds(dnskey
, ds
, false);
1475 if (IN_SET(r
, -EKEYREJECTED
, -EOPNOTSUPP
))
1476 return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */
1486 static hash_md_t
nsec3_hash_to_hash_md(uint8_t algorithm
) {
1488 /* Translates a DNSSEC NSEC3 hash algorithm into an openssl/gcrypt digest identifier */
1490 switch (algorithm
) {
1492 case NSEC3_ALGORITHM_SHA1
:
1493 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1
);
1496 return OPENSSL_OR_GCRYPT(NULL
, -EOPNOTSUPP
);
1500 int dnssec_nsec3_hash(DnsResourceRecord
*nsec3
, const char *name
, void *ret
) {
1501 uint8_t wire_format
[DNS_WIRE_FORMAT_HOSTNAME_MAX
];
1508 if (nsec3
->key
->type
!= DNS_TYPE_NSEC3
)
1511 if (nsec3
->nsec3
.iterations
> NSEC3_ITERATIONS_MAX
)
1512 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1513 "Ignoring NSEC3 RR %s with excessive number of iterations.",
1514 dns_resource_record_to_string(nsec3
));
1516 hash_md_t algorithm
= nsec3_hash_to_hash_md(nsec3
->nsec3
.algorithm
);
1521 size_t hash_size
= EVP_MD_size(algorithm
);
1522 assert(hash_size
> 0);
1524 if (nsec3
->nsec3
.next_hashed_name_size
!= hash_size
)
1527 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
1531 if (EVP_DigestInit_ex(ctx
, algorithm
, NULL
) <= 0)
1534 r
= dns_name_to_wire_format(name
, wire_format
, sizeof(wire_format
), true);
1538 if (EVP_DigestUpdate(ctx
, wire_format
, r
) <= 0)
1540 if (EVP_DigestUpdate(ctx
, nsec3
->nsec3
.salt
, nsec3
->nsec3
.salt_size
) <= 0)
1543 uint8_t result
[EVP_MAX_MD_SIZE
];
1544 if (EVP_DigestFinal_ex(ctx
, result
, NULL
) <= 0)
1547 for (unsigned k
= 0; k
< nsec3
->nsec3
.iterations
; k
++) {
1548 if (EVP_DigestInit_ex(ctx
, algorithm
, NULL
) <= 0)
1550 if (EVP_DigestUpdate(ctx
, result
, hash_size
) <= 0)
1552 if (EVP_DigestUpdate(ctx
, nsec3
->nsec3
.salt
, nsec3
->nsec3
.salt_size
) <= 0)
1555 if (EVP_DigestFinal_ex(ctx
, result
, NULL
) <= 0)
1562 r
= initialize_libgcrypt(false);
1566 size_t encoded_length
;
1567 unsigned hash_size
= gcry_md_get_algo_dlen(algorithm
);
1568 assert(hash_size
> 0);
1570 if (nsec3
->nsec3
.next_hashed_name_size
!= hash_size
)
1573 r
= dns_name_to_wire_format(name
, wire_format
, sizeof(wire_format
), true);
1578 _cleanup_(gcry_md_closep
) gcry_md_hd_t md
= NULL
;
1579 gcry_error_t err
= gcry_md_open(&md
, algorithm
, 0);
1580 if (gcry_err_code(err
) != GPG_ERR_NO_ERROR
|| !md
)
1583 gcry_md_write(md
, wire_format
, encoded_length
);
1584 gcry_md_write(md
, nsec3
->nsec3
.salt
, nsec3
->nsec3
.salt_size
);
1586 void *result
= gcry_md_read(md
, 0);
1590 for (unsigned k
= 0; k
< nsec3
->nsec3
.iterations
; k
++) {
1591 uint8_t tmp
[hash_size
];
1592 memcpy(tmp
, result
, hash_size
);
1595 gcry_md_write(md
, tmp
, hash_size
);
1596 gcry_md_write(md
, nsec3
->nsec3
.salt
, nsec3
->nsec3
.salt_size
);
1598 result
= gcry_md_read(md
, 0);
1604 memcpy(ret
, result
, hash_size
);
1605 return (int) hash_size
;
1608 static int nsec3_is_good(DnsResourceRecord
*rr
, DnsResourceRecord
*nsec3
) {
1614 if (rr
->key
->type
!= DNS_TYPE_NSEC3
)
1617 /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
1618 if (!IN_SET(rr
->nsec3
.flags
, 0, 1))
1621 /* Ignore NSEC3 RRs whose algorithm we don't know */
1623 if (!nsec3_hash_to_hash_md(rr
->nsec3
.algorithm
))
1626 if (nsec3_hash_to_hash_md(rr
->nsec3
.algorithm
) < 0)
1630 /* Ignore NSEC3 RRs with an excessive number of required iterations */
1631 if (rr
->nsec3
.iterations
> NSEC3_ITERATIONS_MAX
)
1634 /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this
1635 * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */
1636 if (!IN_SET(rr
->n_skip_labels_source
, 0, UINT8_MAX
))
1638 /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */
1639 if (!IN_SET(rr
->n_skip_labels_signer
, 1, UINT8_MAX
))
1645 /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
1647 if (nsec3
== rr
) /* Shortcut */
1650 if (rr
->key
->class != nsec3
->key
->class)
1652 if (rr
->nsec3
.algorithm
!= nsec3
->nsec3
.algorithm
)
1654 if (rr
->nsec3
.iterations
!= nsec3
->nsec3
.iterations
)
1656 if (rr
->nsec3
.salt_size
!= nsec3
->nsec3
.salt_size
)
1658 if (memcmp_safe(rr
->nsec3
.salt
, nsec3
->nsec3
.salt
, rr
->nsec3
.salt_size
) != 0)
1661 a
= dns_resource_key_name(rr
->key
);
1662 r
= dns_name_parent(&a
); /* strip off hash */
1666 b
= dns_resource_key_name(nsec3
->key
);
1667 r
= dns_name_parent(&b
); /* strip off hash */
1671 /* Make sure both have the same parent */
1672 return dns_name_equal(a
, b
);
1675 static int nsec3_hashed_domain_format(const uint8_t *hashed
, size_t hashed_size
, const char *zone
, char **ret
) {
1676 _cleanup_free_
char *l
= NULL
;
1680 assert(hashed_size
> 0);
1684 l
= base32hexmem(hashed
, hashed_size
, false);
1688 j
= strjoin(l
, ".", zone
);
1693 return (int) hashed_size
;
1696 static int nsec3_hashed_domain_make(DnsResourceRecord
*nsec3
, const char *domain
, const char *zone
, char **ret
) {
1697 uint8_t hashed
[DNSSEC_HASH_SIZE_MAX
];
1705 hashed_size
= dnssec_nsec3_hash(nsec3
, domain
, hashed
);
1706 if (hashed_size
< 0)
1709 return nsec3_hashed_domain_format(hashed
, (size_t) hashed_size
, zone
, ret
);
1712 /* See RFC 5155, Section 8
1713 * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest
1714 * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there
1715 * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that
1716 * matches the wildcard domain.
1718 * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or
1719 * that there is no proof either way. The latter is the case if a proof of non-existence of a given
1720 * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records
1721 * to conclude anything we indicate this by returning NO_RR. */
1722 static int dnssec_test_nsec3(DnsAnswer
*answer
, DnsResourceKey
*key
, DnssecNsecResult
*result
, bool *authenticated
, uint32_t *ttl
) {
1723 _cleanup_free_
char *next_closer_domain
= NULL
, *wildcard_domain
= NULL
;
1724 const char *zone
, *p
, *pp
= NULL
, *wildcard
;
1725 DnsResourceRecord
*rr
, *enclosure_rr
, *zone_rr
, *wildcard_rr
= NULL
;
1726 DnsAnswerFlags flags
;
1728 bool a
, no_closer
= false, no_wildcard
= false, optout
= false;
1733 /* First step, find the zone name and the NSEC3 parameters of the zone.
1734 * it is sufficient to look for the longest common suffix we find with
1735 * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
1736 * records from a given zone in a response must use the same
1738 zone
= dns_resource_key_name(key
);
1740 DNS_ANSWER_FOREACH_FLAGS(zone_rr
, flags
, answer
) {
1741 r
= nsec3_is_good(zone_rr
, NULL
);
1747 r
= dns_name_equal_skip(dns_resource_key_name(zone_rr
->key
), 1, zone
);
1754 /* Strip one label from the front */
1755 r
= dns_name_parent(&zone
);
1762 *result
= DNSSEC_NSEC_NO_RR
;
1766 /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
1767 p
= dns_resource_key_name(key
);
1769 _cleanup_free_
char *hashed_domain
= NULL
;
1771 hashed_size
= nsec3_hashed_domain_make(zone_rr
, p
, zone
, &hashed_domain
);
1772 if (hashed_size
== -EOPNOTSUPP
) {
1773 *result
= DNSSEC_NSEC_UNSUPPORTED_ALGORITHM
;
1776 if (hashed_size
< 0)
1779 DNS_ANSWER_FOREACH_FLAGS(enclosure_rr
, flags
, answer
) {
1781 r
= nsec3_is_good(enclosure_rr
, zone_rr
);
1787 if (enclosure_rr
->nsec3
.next_hashed_name_size
!= (size_t) hashed_size
)
1790 r
= dns_name_equal(dns_resource_key_name(enclosure_rr
->key
), hashed_domain
);
1794 a
= flags
& DNS_ANSWER_AUTHENTICATED
;
1795 goto found_closest_encloser
;
1799 /* We didn't find the closest encloser with this name,
1800 * but let's remember this domain name, it might be
1801 * the next closer name */
1805 /* Strip one label from the front */
1806 r
= dns_name_parent(&p
);
1813 *result
= DNSSEC_NSEC_NO_RR
;
1816 found_closest_encloser
:
1817 /* We found a closest encloser in 'p'; next closer is 'pp' */
1820 /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR
1821 * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are
1822 * appropriately set. */
1824 if (key
->type
== DNS_TYPE_DS
) {
1825 if (bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_SOA
))
1828 if (bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_NS
) &&
1829 !bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_SOA
))
1833 /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
1834 if (bitmap_isset(enclosure_rr
->nsec3
.types
, key
->type
))
1835 *result
= DNSSEC_NSEC_FOUND
;
1836 else if (bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_CNAME
))
1837 *result
= DNSSEC_NSEC_CNAME
;
1839 *result
= DNSSEC_NSEC_NODATA
;
1844 *ttl
= enclosure_rr
->ttl
;
1849 /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
1850 if (bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_DNAME
))
1853 /* Ensure that this data is from the delegated domain
1854 * (i.e. originates from the "lower" DNS server), and isn't
1855 * just glue records (i.e. doesn't originate from the "upper"
1857 if (bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_NS
) &&
1858 !bitmap_isset(enclosure_rr
->nsec3
.types
, DNS_TYPE_SOA
))
1861 /* Prove that there is no next closer and whether or not there is a wildcard domain. */
1863 wildcard
= strjoina("*.", p
);
1864 r
= nsec3_hashed_domain_make(enclosure_rr
, wildcard
, zone
, &wildcard_domain
);
1867 if (r
!= hashed_size
)
1870 r
= nsec3_hashed_domain_make(enclosure_rr
, pp
, zone
, &next_closer_domain
);
1873 if (r
!= hashed_size
)
1876 DNS_ANSWER_FOREACH_FLAGS(rr
, flags
, answer
) {
1877 _cleanup_free_
char *next_hashed_domain
= NULL
;
1879 r
= nsec3_is_good(rr
, zone_rr
);
1885 r
= nsec3_hashed_domain_format(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, zone
, &next_hashed_domain
);
1889 r
= dns_name_between(dns_resource_key_name(rr
->key
), next_closer_domain
, next_hashed_domain
);
1893 if (rr
->nsec3
.flags
& 1)
1896 a
= a
&& (flags
& DNS_ANSWER_AUTHENTICATED
);
1901 r
= dns_name_equal(dns_resource_key_name(rr
->key
), wildcard_domain
);
1905 a
= a
&& (flags
& DNS_ANSWER_AUTHENTICATED
);
1910 r
= dns_name_between(dns_resource_key_name(rr
->key
), wildcard_domain
, next_hashed_domain
);
1914 if (rr
->nsec3
.flags
& 1)
1915 /* This only makes sense if we have a wildcard delegation, which is
1916 * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on
1917 * this not happening, so hence cannot simply conclude NXDOMAIN as
1921 a
= a
&& (flags
& DNS_ANSWER_AUTHENTICATED
);
1927 if (wildcard_rr
&& no_wildcard
)
1931 *result
= DNSSEC_NSEC_NO_RR
;
1936 /* A wildcard exists that matches our query. */
1938 /* This is not specified in any RFC to the best of my knowledge, but
1939 * if the next closer enclosure is covered by an opt-out NSEC3 RR
1940 * it means that we cannot prove that the source of synthesis is
1941 * correct, as there may be a closer match. */
1942 *result
= DNSSEC_NSEC_OPTOUT
;
1943 else if (bitmap_isset(wildcard_rr
->nsec3
.types
, key
->type
))
1944 *result
= DNSSEC_NSEC_FOUND
;
1945 else if (bitmap_isset(wildcard_rr
->nsec3
.types
, DNS_TYPE_CNAME
))
1946 *result
= DNSSEC_NSEC_CNAME
;
1948 *result
= DNSSEC_NSEC_NODATA
;
1951 /* The RFC only specifies that we have to care for optout for NODATA for
1952 * DS records. However, children of an insecure opt-out delegation should
1953 * also be considered opt-out, rather than verified NXDOMAIN.
1954 * Note that we do not require a proof of wildcard non-existence if the
1955 * next closer domain is covered by an opt-out, as that would not provide
1956 * any additional information. */
1957 *result
= DNSSEC_NSEC_OPTOUT
;
1958 else if (no_wildcard
)
1959 *result
= DNSSEC_NSEC_NXDOMAIN
;
1961 *result
= DNSSEC_NSEC_NO_RR
;
1971 *ttl
= enclosure_rr
->ttl
;
1976 static int dnssec_nsec_wildcard_equal(DnsResourceRecord
*rr
, const char *name
) {
1977 char label
[DNS_LABEL_MAX
+1];
1982 assert(rr
->key
->type
== DNS_TYPE_NSEC
);
1984 /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */
1986 if (rr
->n_skip_labels_source
!= 1)
1989 n
= dns_resource_key_name(rr
->key
);
1990 r
= dns_label_unescape(&n
, label
, sizeof label
, 0);
1993 if (r
!= 1 || label
[0] != '*')
1996 return dns_name_endswith(name
, n
);
1999 static int dnssec_nsec_in_path(DnsResourceRecord
*rr
, const char *name
) {
2000 const char *nn
, *common_suffix
;
2004 assert(rr
->key
->type
== DNS_TYPE_NSEC
);
2006 /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT)
2008 * A couple of examples:
2010 * NSEC bar → waldo.foo.bar: indicates that foo.bar exists and is an ENT
2011 * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs
2012 * NSEC yyy.zzz.xoo.bar → bar: indicates pretty much nothing about ENTs
2015 /* First, determine parent of next domain. */
2016 nn
= rr
->nsec
.next_domain_name
;
2017 r
= dns_name_parent(&nn
);
2021 /* If the name we just determined is not equal or child of the name we are interested in, then we can't say
2022 * anything at all. */
2023 r
= dns_name_endswith(nn
, name
);
2027 /* If the name we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */
2028 r
= dns_name_common_suffix(dns_resource_key_name(rr
->key
), rr
->nsec
.next_domain_name
, &common_suffix
);
2032 return dns_name_endswith(name
, common_suffix
);
2035 static int dnssec_nsec_from_parent_zone(DnsResourceRecord
*rr
, const char *name
) {
2039 assert(rr
->key
->type
== DNS_TYPE_NSEC
);
2041 /* Checks whether this NSEC originates to the parent zone or the child zone. */
2043 r
= dns_name_parent(&name
);
2047 r
= dns_name_equal(name
, dns_resource_key_name(rr
->key
));
2051 /* DNAME, and NS without SOA is an indication for a delegation. */
2052 if (bitmap_isset(rr
->nsec
.types
, DNS_TYPE_DNAME
))
2055 if (bitmap_isset(rr
->nsec
.types
, DNS_TYPE_NS
) && !bitmap_isset(rr
->nsec
.types
, DNS_TYPE_SOA
))
2061 static int dnssec_nsec_covers(DnsResourceRecord
*rr
, const char *name
) {
2066 assert(rr
->key
->type
== DNS_TYPE_NSEC
);
2068 /* Checks whether the name is covered by this NSEC RR. This means, that the name is somewhere below the NSEC's
2069 * signer name, and between the NSEC's two names. */
2071 r
= dns_resource_record_signer(rr
, &signer
);
2075 r
= dns_name_endswith(name
, signer
); /* this NSEC isn't suitable the name is not in the signer's domain */
2079 return dns_name_between(dns_resource_key_name(rr
->key
), name
, rr
->nsec
.next_domain_name
);
2082 static int dnssec_nsec_generate_wildcard(DnsResourceRecord
*rr
, const char *name
, char **wc
) {
2083 const char *common_suffix1
, *common_suffix2
, *signer
;
2084 int r
, labels1
, labels2
;
2087 assert(rr
->key
->type
== DNS_TYPE_NSEC
);
2089 /* Generates "Wildcard at the Closest Encloser" for the given name and NSEC RR. */
2091 r
= dns_resource_record_signer(rr
, &signer
);
2095 r
= dns_name_endswith(name
, signer
); /* this NSEC isn't suitable the name is not in the signer's domain */
2099 r
= dns_name_common_suffix(name
, dns_resource_key_name(rr
->key
), &common_suffix1
);
2103 r
= dns_name_common_suffix(name
, rr
->nsec
.next_domain_name
, &common_suffix2
);
2107 labels1
= dns_name_count_labels(common_suffix1
);
2111 labels2
= dns_name_count_labels(common_suffix2
);
2115 if (labels1
> labels2
)
2116 r
= dns_name_concat("*", common_suffix1
, 0, wc
);
2118 r
= dns_name_concat("*", common_suffix2
, 0, wc
);
2126 int dnssec_nsec_test(DnsAnswer
*answer
, DnsResourceKey
*key
, DnssecNsecResult
*result
, bool *authenticated
, uint32_t *ttl
) {
2127 bool have_nsec3
= false, covering_rr_authenticated
= false, wildcard_rr_authenticated
= false;
2128 DnsResourceRecord
*rr
, *covering_rr
= NULL
, *wildcard_rr
= NULL
;
2129 DnsAnswerFlags flags
;
2136 /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
2138 name
= dns_resource_key_name(key
);
2140 DNS_ANSWER_FOREACH_FLAGS(rr
, flags
, answer
) {
2142 if (rr
->key
->class != key
->class)
2145 have_nsec3
= have_nsec3
|| (rr
->key
->type
== DNS_TYPE_NSEC3
);
2147 if (rr
->key
->type
!= DNS_TYPE_NSEC
)
2150 /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */
2151 r
= dns_resource_record_is_synthetic(rr
);
2152 if (r
== -ENODATA
) /* No signing RR known. */
2159 /* Check if this is a direct match. If so, we have encountered a NODATA case */
2160 r
= dns_name_equal(dns_resource_key_name(rr
->key
), name
);
2164 /* If it's not a direct match, maybe it's a wild card match? */
2165 r
= dnssec_nsec_wildcard_equal(rr
, name
);
2170 if (key
->type
== DNS_TYPE_DS
) {
2171 /* If we look for a DS RR and the server sent us the NSEC RR of the child zone
2172 * we have a problem. For DS RRs we want the NSEC RR from the parent */
2173 if (bitmap_isset(rr
->nsec
.types
, DNS_TYPE_SOA
))
2176 /* For all RR types, ensure that if NS is set SOA is set too, so that we know
2177 * we got the child's NSEC. */
2178 if (bitmap_isset(rr
->nsec
.types
, DNS_TYPE_NS
) &&
2179 !bitmap_isset(rr
->nsec
.types
, DNS_TYPE_SOA
))
2183 if (bitmap_isset(rr
->nsec
.types
, key
->type
))
2184 *result
= DNSSEC_NSEC_FOUND
;
2185 else if (bitmap_isset(rr
->nsec
.types
, DNS_TYPE_CNAME
))
2186 *result
= DNSSEC_NSEC_CNAME
;
2188 *result
= DNSSEC_NSEC_NODATA
;
2191 *authenticated
= flags
& DNS_ANSWER_AUTHENTICATED
;
2198 /* Check if the name we are looking for is an empty non-terminal within the owner or next name
2199 * of the NSEC RR. */
2200 r
= dnssec_nsec_in_path(rr
, name
);
2204 *result
= DNSSEC_NSEC_NODATA
;
2207 *authenticated
= flags
& DNS_ANSWER_AUTHENTICATED
;
2214 /* The following two "covering" checks, are not useful if the NSEC is from the parent */
2215 r
= dnssec_nsec_from_parent_zone(rr
, name
);
2221 /* Check if this NSEC RR proves the absence of an explicit RR under this name */
2222 r
= dnssec_nsec_covers(rr
, name
);
2225 if (r
> 0 && (!covering_rr
|| !covering_rr_authenticated
)) {
2227 covering_rr_authenticated
= flags
& DNS_ANSWER_AUTHENTICATED
;
2232 _cleanup_free_
char *wc
= NULL
;
2233 r
= dnssec_nsec_generate_wildcard(covering_rr
, name
, &wc
);
2237 DNS_ANSWER_FOREACH_FLAGS(rr
, flags
, answer
) {
2239 if (rr
->key
->class != key
->class)
2242 if (rr
->key
->type
!= DNS_TYPE_NSEC
)
2245 /* Check if this NSEC RR proves the nonexistence of the wildcard */
2246 r
= dnssec_nsec_covers(rr
, wc
);
2249 if (r
> 0 && (!wildcard_rr
|| !wildcard_rr_authenticated
)) {
2251 wildcard_rr_authenticated
= flags
& DNS_ANSWER_AUTHENTICATED
;
2256 if (covering_rr
&& wildcard_rr
) {
2257 /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we
2258 * proved the NXDOMAIN case. */
2259 *result
= DNSSEC_NSEC_NXDOMAIN
;
2262 *authenticated
= covering_rr_authenticated
&& wildcard_rr_authenticated
;
2264 *ttl
= MIN(covering_rr
->ttl
, wildcard_rr
->ttl
);
2269 /* OK, this was not sufficient. Let's see if NSEC3 can help. */
2271 return dnssec_test_nsec3(answer
, key
, result
, authenticated
, ttl
);
2273 /* No appropriate NSEC RR found, report this. */
2274 *result
= DNSSEC_NSEC_NO_RR
;
2278 static int dnssec_nsec_test_enclosed(DnsAnswer
*answer
, uint16_t type
, const char *name
, const char *zone
, bool *authenticated
) {
2279 DnsResourceRecord
*rr
;
2280 DnsAnswerFlags flags
;
2286 /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified
2287 * 'zone'. The 'zone' must be a suffix of the 'name'. */
2289 DNS_ANSWER_FOREACH_FLAGS(rr
, flags
, answer
) {
2292 if (rr
->key
->type
!= type
&& type
!= DNS_TYPE_ANY
)
2295 switch (rr
->key
->type
) {
2299 /* We only care for NSEC RRs from the indicated zone */
2300 r
= dns_resource_record_is_signer(rr
, zone
);
2306 r
= dns_name_between(dns_resource_key_name(rr
->key
), name
, rr
->nsec
.next_domain_name
);
2313 case DNS_TYPE_NSEC3
: {
2314 _cleanup_free_
char *hashed_domain
= NULL
, *next_hashed_domain
= NULL
;
2316 /* We only care for NSEC3 RRs from the indicated zone */
2317 r
= dns_resource_record_is_signer(rr
, zone
);
2323 r
= nsec3_is_good(rr
, NULL
);
2329 /* Format the domain we are testing with the NSEC3 RR's hash function */
2330 r
= nsec3_hashed_domain_make(
2337 if ((size_t) r
!= rr
->nsec3
.next_hashed_name_size
)
2340 /* Format the NSEC3's next hashed name as proper domain name */
2341 r
= nsec3_hashed_domain_format(
2342 rr
->nsec3
.next_hashed_name
,
2343 rr
->nsec3
.next_hashed_name_size
,
2345 &next_hashed_domain
);
2349 r
= dns_name_between(dns_resource_key_name(rr
->key
), hashed_domain
, next_hashed_domain
);
2363 *authenticated
= flags
& DNS_ANSWER_AUTHENTICATED
;
2371 static int dnssec_test_positive_wildcard_nsec3(
2376 bool *authenticated
) {
2378 const char *next_closer
= NULL
;
2381 /* Run a positive NSEC3 wildcard proof. Specifically:
2383 * A proof that the "next closer" of the generating wildcard does not exist.
2385 * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for
2386 * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name
2387 * exists for the NSEC3 RR and we are done.
2389 * To prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f all we have to check is that
2390 * c.d.e.f does not exist. */
2394 r
= dns_name_parent(&name
);
2398 r
= dns_name_equal(name
, source
);
2405 return dnssec_nsec_test_enclosed(answer
, DNS_TYPE_NSEC3
, next_closer
, zone
, authenticated
);
2408 static int dnssec_test_positive_wildcard_nsec(
2413 bool *_authenticated
) {
2415 bool authenticated
= true;
2418 /* Run a positive NSEC wildcard proof. Specifically:
2420 * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and
2421 * a prefix of the synthesizing source "source" in the zone "zone".
2423 * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4
2425 * Note that if we want to prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f, then we
2426 * have to prove that none of the following exist:
2436 _cleanup_free_
char *wc
= NULL
;
2439 /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing,
2440 * i.e between the owner name and the next name of an NSEC RR. */
2441 r
= dnssec_nsec_test_enclosed(answer
, DNS_TYPE_NSEC
, name
, zone
, &a
);
2445 authenticated
= authenticated
&& a
;
2447 /* Strip one label off */
2448 r
= dns_name_parent(&name
);
2452 /* Did we reach the source of synthesis? */
2453 r
= dns_name_equal(name
, source
);
2457 /* Successful exit */
2458 *_authenticated
= authenticated
;
2462 /* Safety check, that the source of synthesis is still our suffix */
2463 r
= dns_name_endswith(name
, source
);
2469 /* Replace the label we stripped off with an asterisk */
2470 wc
= strjoin("*.", name
);
2474 /* And check if the proof holds for the asterisk name, too */
2475 r
= dnssec_nsec_test_enclosed(answer
, DNS_TYPE_NSEC
, wc
, zone
, &a
);
2479 authenticated
= authenticated
&& a
;
2480 /* In the next iteration we'll check the non-asterisk-prefixed version */
2484 int dnssec_test_positive_wildcard(
2489 bool *authenticated
) {
2496 assert(authenticated
);
2498 r
= dns_answer_contains_zone_nsec3(answer
, zone
);
2502 return dnssec_test_positive_wildcard_nsec3(answer
, name
, source
, zone
, authenticated
);
2504 return dnssec_test_positive_wildcard_nsec(answer
, name
, source
, zone
, authenticated
);
2509 int dnssec_verify_rrset(
2511 const DnsResourceKey
*key
,
2512 DnsResourceRecord
*rrsig
,
2513 DnsResourceRecord
*dnskey
,
2515 DnssecResult
*result
) {
2520 int dnssec_rrsig_match_dnskey(DnsResourceRecord
*rrsig
, DnsResourceRecord
*dnskey
, bool revoked_ok
) {
2525 int dnssec_key_match_rrsig(const DnsResourceKey
*key
, DnsResourceRecord
*rrsig
) {
2530 int dnssec_verify_rrset_search(
2532 const DnsResourceKey
*key
,
2533 DnsAnswer
*validated_dnskeys
,
2535 DnssecResult
*result
,
2536 DnsResourceRecord
**ret_rrsig
) {
2541 int dnssec_has_rrsig(DnsAnswer
*a
, const DnsResourceKey
*key
) {
2546 int dnssec_verify_dnskey_by_ds(DnsResourceRecord
*dnskey
, DnsResourceRecord
*ds
, bool mask_revoke
) {
2551 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord
*dnskey
, DnsAnswer
*validated_ds
) {
2556 int dnssec_nsec3_hash(DnsResourceRecord
*nsec3
, const char *name
, void *ret
) {
2561 int dnssec_nsec_test(DnsAnswer
*answer
, DnsResourceKey
*key
, DnssecNsecResult
*result
, bool *authenticated
, uint32_t *ttl
) {
2566 int dnssec_test_positive_wildcard(
2571 bool *authenticated
) {
2578 static const char* const dnssec_result_table
[_DNSSEC_RESULT_MAX
] = {
2579 [DNSSEC_VALIDATED
] = "validated",
2580 [DNSSEC_VALIDATED_WILDCARD
] = "validated-wildcard",
2581 [DNSSEC_INVALID
] = "invalid",
2582 [DNSSEC_SIGNATURE_EXPIRED
] = "signature-expired",
2583 [DNSSEC_UNSUPPORTED_ALGORITHM
] = "unsupported-algorithm",
2584 [DNSSEC_NO_SIGNATURE
] = "no-signature",
2585 [DNSSEC_MISSING_KEY
] = "missing-key",
2586 [DNSSEC_UNSIGNED
] = "unsigned",
2587 [DNSSEC_FAILED_AUXILIARY
] = "failed-auxiliary",
2588 [DNSSEC_NSEC_MISMATCH
] = "nsec-mismatch",
2589 [DNSSEC_INCOMPATIBLE_SERVER
] = "incompatible-server",
2590 [DNSSEC_UPSTREAM_FAILURE
] = "upstream-failure",
2591 [DNSSEC_TOO_MANY_VALIDATIONS
] = "too-many-validations",
2593 DEFINE_STRING_TABLE_LOOKUP(dnssec_result
, DnssecResult
);
2595 static const char* const dnssec_verdict_table
[_DNSSEC_VERDICT_MAX
] = {
2596 [DNSSEC_SECURE
] = "secure",
2597 [DNSSEC_INSECURE
] = "insecure",
2598 [DNSSEC_BOGUS
] = "bogus",
2599 [DNSSEC_INDETERMINATE
] = "indeterminate",
2601 DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict
, DnssecVerdict
);