]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-dnssec.c
Merge pull request #31000 from flatcar-hub/krnowak/mutable-overlays
[thirdparty/systemd.git] / src / resolve / resolved-dns-dnssec.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "alloc-util.h"
4 #include "dns-domain.h"
5 #include "fd-util.h"
6 #include "fileio.h"
7 #include "gcrypt-util.h"
8 #include "hexdecoct.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"
16
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
23 #endif
24
25 #define VERIFY_RRS_MAX 256
26 #define MAX_KEY_SIZE (32*1024)
27
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)
30
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
34
35 /*
36 * The DNSSEC Chain of trust:
37 *
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
41 *
42 * Example chain:
43 * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
44 */
45
46 uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
47 const uint8_t *p;
48 uint32_t sum, f;
49
50 /* The algorithm from RFC 4034, Appendix B. */
51
52 assert(dnskey);
53 assert(dnskey->key->type == DNS_TYPE_DNSKEY);
54
55 f = (uint32_t) dnskey->dnskey.flags;
56
57 if (mask_revoke)
58 f &= ~DNSKEY_FLAG_REVOKE;
59
60 sum = f + ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm);
61
62 p = dnskey->dnskey.key;
63
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];
66
67 sum += (sum >> 16) & UINT32_C(0xFFFF);
68
69 return sum & UINT32_C(0xFFFF);
70 }
71
72 #if HAVE_OPENSSL_OR_GCRYPT
73
74 static int rr_compare(DnsResourceRecord * const *a, DnsResourceRecord * const *b) {
75 const DnsResourceRecord *x = *a, *y = *b;
76 size_t m;
77 int r;
78
79 /* Let's order the RRs according to RFC 4034, Section 6.3 */
80
81 assert(x);
82 assert(x->wire_format);
83 assert(y);
84 assert(y->wire_format);
85
86 m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y));
87
88 r = memcmp(DNS_RESOURCE_RECORD_RDATA(x), DNS_RESOURCE_RECORD_RDATA(y), m);
89 if (r != 0)
90 return r;
91
92 return CMP(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y));
93 }
94
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) {
101 int r;
102
103 #if PREFER_OPENSSL
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;
110
111 assert(hash_algorithm);
112
113 e = BN_bin2bn(exponent, exponent_size, NULL);
114 if (!e)
115 return -EIO;
116
117 m = BN_bin2bn(modulus, modulus_size, NULL);
118 if (!m)
119 return -EIO;
120
121 rpubkey = RSA_new();
122 if (!rpubkey)
123 return -ENOMEM;
124
125 if (RSA_set0_key(rpubkey, m, e, NULL) <= 0)
126 return -EIO;
127 e = m = NULL;
128
129 assert((size_t) RSA_size(rpubkey) == signature_size);
130
131 epubkey = EVP_PKEY_new();
132 if (!epubkey)
133 return -ENOMEM;
134
135 if (EVP_PKEY_assign_RSA(epubkey, RSAPublicKey_dup(rpubkey)) <= 0)
136 return -EIO;
137
138 ctx = EVP_PKEY_CTX_new(epubkey, NULL);
139 if (!ctx)
140 return -ENOMEM;
141
142 if (EVP_PKEY_verify_init(ctx) <= 0)
143 return -EIO;
144
145 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
146 return -EIO;
147
148 if (EVP_PKEY_CTX_set_signature_md(ctx, hash_algorithm) <= 0)
149 return -EIO;
150
151 r = EVP_PKEY_verify(ctx, signature, signature_size, data, data_size);
152 if (r < 0)
153 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
154 "Signature verification failed: 0x%lx", ERR_get_error());
155
156 # pragma GCC diagnostic pop
157 #else
158 gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
159 gcry_mpi_t n = NULL, e = NULL, s = NULL;
160 gcry_error_t ge;
161
162 assert(hash_algorithm);
163
164 ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL);
165 if (ge != 0) {
166 r = -EIO;
167 goto finish;
168 }
169
170 ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL);
171 if (ge != 0) {
172 r = -EIO;
173 goto finish;
174 }
175
176 ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL);
177 if (ge != 0) {
178 r = -EIO;
179 goto finish;
180 }
181
182 ge = gcry_sexp_build(&signature_sexp,
183 NULL,
184 "(sig-val (rsa (s %m)))",
185 s);
186
187 if (ge != 0) {
188 r = -EIO;
189 goto finish;
190 }
191
192 ge = gcry_sexp_build(&data_sexp,
193 NULL,
194 "(data (flags pkcs1) (hash %s %b))",
195 hash_algorithm,
196 (int) data_size,
197 data);
198 if (ge != 0) {
199 r = -EIO;
200 goto finish;
201 }
202
203 ge = gcry_sexp_build(&public_key_sexp,
204 NULL,
205 "(public-key (rsa (n %m) (e %m)))",
206 n,
207 e);
208 if (ge != 0) {
209 r = -EIO;
210 goto finish;
211 }
212
213 ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
214 if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
215 r = 0;
216 else if (ge != 0)
217 r = log_debug_errno(SYNTHETIC_ERRNO(EIO),
218 "RSA signature check failed: %s", gpg_strerror(ge));
219 else
220 r = 1;
221
222 finish:
223 if (e)
224 gcry_mpi_release(e);
225 if (n)
226 gcry_mpi_release(n);
227 if (s)
228 gcry_mpi_release(s);
229
230 if (public_key_sexp)
231 gcry_sexp_release(public_key_sexp);
232 if (signature_sexp)
233 gcry_sexp_release(signature_sexp);
234 if (data_sexp)
235 gcry_sexp_release(data_sexp);
236 #endif
237 return r;
238 }
239
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) {
245
246 size_t exponent_size, modulus_size;
247 void *exponent, *modulus;
248
249 assert(hash_algorithm);
250 assert(hash);
251 assert(hash_size > 0);
252 assert(rrsig);
253 assert(dnskey);
254
255 if (*(uint8_t*) dnskey->dnskey.key == 0) {
256 /* exponent is > 255 bytes long */
257
258 exponent = (uint8_t*) dnskey->dnskey.key + 3;
259 exponent_size =
260 ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) |
261 ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]);
262
263 if (exponent_size < 256)
264 return -EINVAL;
265
266 if (3 + exponent_size >= dnskey->dnskey.key_size)
267 return -EINVAL;
268
269 modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size;
270 modulus_size = dnskey->dnskey.key_size - 3 - exponent_size;
271
272 } else {
273 /* exponent is <= 255 bytes long */
274
275 exponent = (uint8_t*) dnskey->dnskey.key + 1;
276 exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0];
277
278 if (exponent_size <= 0)
279 return -EINVAL;
280
281 if (1 + exponent_size >= dnskey->dnskey.key_size)
282 return -EINVAL;
283
284 modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size;
285 modulus_size = dnskey->dnskey.key_size - 1 - exponent_size;
286 }
287
288 return dnssec_rsa_verify_raw(
289 hash_algorithm,
290 rrsig->rrsig.signature, rrsig->rrsig.signature_size,
291 hash, hash_size,
292 exponent, exponent_size,
293 modulus, modulus_size);
294 }
295
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) {
303 int k;
304
305 #if PREFER_OPENSSL
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;
314
315 assert(hash_algorithm);
316
317 ec_group = EC_GROUP_new_by_curve_name(curve);
318 if (!ec_group)
319 return -ENOMEM;
320
321 p = EC_POINT_new(ec_group);
322 if (!p)
323 return -ENOMEM;
324
325 bctx = BN_CTX_new();
326 if (!bctx)
327 return -ENOMEM;
328
329 if (EC_POINT_oct2point(ec_group, p, key, key_size, bctx) <= 0)
330 return -EIO;
331
332 eckey = EC_KEY_new();
333 if (!eckey)
334 return -ENOMEM;
335
336 if (EC_KEY_set_group(eckey, ec_group) <= 0)
337 return -EIO;
338
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());
342
343 assert(EC_KEY_check_key(eckey) == 1);
344
345 r = BN_bin2bn(signature_r, signature_r_size, NULL);
346 if (!r)
347 return -EIO;
348
349 s = BN_bin2bn(signature_s, signature_s_size, NULL);
350 if (!s)
351 return -EIO;
352
353 /* TODO: We should eventually use the EVP API once it supports ECDSA signature verification */
354
355 sig = ECDSA_SIG_new();
356 if (!sig)
357 return -ENOMEM;
358
359 if (ECDSA_SIG_set0(sig, r, s) <= 0)
360 return -EIO;
361 r = s = NULL;
362
363 k = ECDSA_do_verify(data, data_size, sig, eckey);
364 if (k < 0)
365 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
366 "Signature verification failed: 0x%lx", ERR_get_error());
367
368 # pragma GCC diagnostic pop
369 #else
370 gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
371 gcry_mpi_t q = NULL, r = NULL, s = NULL;
372 gcry_error_t ge;
373
374 assert(hash_algorithm);
375
376 ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL);
377 if (ge != 0) {
378 k = -EIO;
379 goto finish;
380 }
381
382 ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL);
383 if (ge != 0) {
384 k = -EIO;
385 goto finish;
386 }
387
388 ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL);
389 if (ge != 0) {
390 k = -EIO;
391 goto finish;
392 }
393
394 ge = gcry_sexp_build(&signature_sexp,
395 NULL,
396 "(sig-val (ecdsa (r %m) (s %m)))",
397 r,
398 s);
399 if (ge != 0) {
400 k = -EIO;
401 goto finish;
402 }
403
404 ge = gcry_sexp_build(&data_sexp,
405 NULL,
406 "(data (flags rfc6979) (hash %s %b))",
407 hash_algorithm,
408 (int) data_size,
409 data);
410 if (ge != 0) {
411 k = -EIO;
412 goto finish;
413 }
414
415 ge = gcry_sexp_build(&public_key_sexp,
416 NULL,
417 "(public-key (ecc (curve %s) (q %m)))",
418 curve,
419 q);
420 if (ge != 0) {
421 k = -EIO;
422 goto finish;
423 }
424
425 ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
426 if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
427 k = 0;
428 else if (ge != 0) {
429 log_debug("ECDSA signature check failed: %s", gpg_strerror(ge));
430 k = -EIO;
431 } else
432 k = 1;
433 finish:
434 if (r)
435 gcry_mpi_release(r);
436 if (s)
437 gcry_mpi_release(s);
438 if (q)
439 gcry_mpi_release(q);
440
441 if (public_key_sexp)
442 gcry_sexp_release(public_key_sexp);
443 if (signature_sexp)
444 gcry_sexp_release(signature_sexp);
445 if (data_sexp)
446 gcry_sexp_release(data_sexp);
447 #endif
448 return k;
449 }
450
451 static int dnssec_ecdsa_verify(
452 hash_algorithm_t hash_algorithm,
453 int algorithm,
454 const void *hash, size_t hash_size,
455 DnsResourceRecord *rrsig,
456 DnsResourceRecord *dnskey) {
457
458 elliptic_curve_t curve;
459 size_t key_size;
460 uint8_t *q;
461
462 assert(hash);
463 assert(hash_size);
464 assert(rrsig);
465 assert(dnskey);
466
467 if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) {
468 curve = OPENSSL_OR_GCRYPT(NID_X9_62_prime256v1, "NIST P-256"); /* NIST P-256 */
469 key_size = 32;
470 } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) {
471 curve = OPENSSL_OR_GCRYPT(NID_secp384r1, "NIST P-384"); /* NIST P-384 */
472 key_size = 48;
473 } else
474 return -EOPNOTSUPP;
475
476 if (dnskey->dnskey.key_size != key_size * 2)
477 return -EINVAL;
478
479 if (rrsig->rrsig.signature_size != key_size * 2)
480 return -EINVAL;
481
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);
485
486 return dnssec_ecdsa_verify_raw(
487 hash_algorithm,
488 curve,
489 rrsig->rrsig.signature, key_size,
490 (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
491 hash, hash_size,
492 q, key_size*2+1);
493 }
494
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) {
500
501 #if PREFER_OPENSSL
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;
505 int r;
506
507 assert(curve == NID_ED25519);
508 assert(signature_size == key_size * 2);
509
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);
513
514 evkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, key, key_size);
515 if (!evkey)
516 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
517 "EVP_PKEY_new_raw_public_key failed: 0x%lx", ERR_get_error());
518
519 pctx = EVP_PKEY_CTX_new(evkey, NULL);
520 if (!pctx)
521 return -ENOMEM;
522
523 ctx = EVP_MD_CTX_new();
524 if (!ctx)
525 return -ENOMEM;
526
527 /* This prevents EVP_DigestVerifyInit from managing pctx and complicating our free logic. */
528 EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
529
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)
532 return -EIO;
533
534 r = EVP_DigestVerify(ctx, signature, signature_size, data, data_size);
535 if (r < 0)
536 return log_debug_errno(SYNTHETIC_ERRNO(EIO),
537 "Signature verification failed: 0x%lx", ERR_get_error());
538
539 return r;
540
541 #elif GCRYPT_VERSION_NUMBER >= 0x010600
542 gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
543 gcry_error_t ge;
544 int k;
545
546 assert(signature_size == key_size * 2);
547
548 ge = gcry_sexp_build(&signature_sexp,
549 NULL,
550 "(sig-val (eddsa (r %b) (s %b)))",
551 (int) key_size,
552 signature,
553 (int) key_size,
554 signature + key_size);
555 if (ge != 0) {
556 k = -EIO;
557 goto finish;
558 }
559
560 ge = gcry_sexp_build(&data_sexp,
561 NULL,
562 "(data (flags eddsa) (hash-algo sha512) (value %b))",
563 (int) data_size,
564 data);
565 if (ge != 0) {
566 k = -EIO;
567 goto finish;
568 }
569
570 ge = gcry_sexp_build(&public_key_sexp,
571 NULL,
572 "(public-key (ecc (curve %s) (flags eddsa) (q %b)))",
573 curve,
574 (int) key_size,
575 key);
576 if (ge != 0) {
577 k = -EIO;
578 goto finish;
579 }
580
581 ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
582 if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
583 k = 0;
584 else if (ge != 0)
585 k = log_debug_errno(SYNTHETIC_ERRNO(EIO),
586 "EdDSA signature check failed: %s", gpg_strerror(ge));
587 else
588 k = 1;
589 finish:
590 if (public_key_sexp)
591 gcry_sexp_release(public_key_sexp);
592 if (signature_sexp)
593 gcry_sexp_release(signature_sexp);
594 if (data_sexp)
595 gcry_sexp_release(data_sexp);
596
597 return k;
598 #else
599 return -EOPNOTSUPP;
600 #endif
601 }
602
603 static int dnssec_eddsa_verify(
604 int algorithm,
605 const void *data, size_t data_size,
606 DnsResourceRecord *rrsig,
607 DnsResourceRecord *dnskey) {
608 elliptic_curve_t curve;
609 size_t key_size;
610
611 if (algorithm == DNSSEC_ALGORITHM_ED25519) {
612 curve = OPENSSL_OR_GCRYPT(NID_ED25519, "Ed25519");
613 key_size = 32;
614 } else
615 return -EOPNOTSUPP;
616
617 if (dnskey->dnskey.key_size != key_size)
618 return -EINVAL;
619
620 if (rrsig->rrsig.signature_size != key_size * 2)
621 return -EINVAL;
622
623 return dnssec_eddsa_verify_raw(
624 curve,
625 rrsig->rrsig.signature, rrsig->rrsig.signature_size,
626 data, data_size,
627 dnskey->dnskey.key, key_size);
628 }
629
630 static int md_add_uint8(hash_context_t ctx, uint8_t v) {
631 #if PREFER_OPENSSL
632 return EVP_DigestUpdate(ctx, &v, sizeof(v));
633 #else
634 gcry_md_write(ctx, &v, sizeof(v));
635 return 0;
636 #endif
637 }
638
639 static int md_add_uint16(hash_context_t ctx, uint16_t v) {
640 v = htobe16(v);
641 #if PREFER_OPENSSL
642 return EVP_DigestUpdate(ctx, &v, sizeof(v));
643 #else
644 gcry_md_write(ctx, &v, sizeof(v));
645 return 0;
646 #endif
647 }
648
649 static void fwrite_uint8(FILE *fp, uint8_t v) {
650 fwrite(&v, sizeof(v), 1, fp);
651 }
652
653 static void fwrite_uint16(FILE *fp, uint16_t v) {
654 v = htobe16(v);
655 fwrite(&v, sizeof(v), 1, fp);
656 }
657
658 static void fwrite_uint32(FILE *fp, uint32_t v) {
659 v = htobe32(v);
660 fwrite(&v, sizeof(v), 1, fp);
661 }
662
663 static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
664 int n_key_labels, n_signer_labels;
665 const char *name;
666 int r;
667
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. */
670
671 assert(rrsig);
672 assert(rrsig->key->type == DNS_TYPE_RRSIG);
673
674 /* Check if this RRSIG RR is already prepared */
675 if (rrsig->n_skip_labels_source != UINT8_MAX)
676 return 0;
677
678 if (rrsig->rrsig.inception > rrsig->rrsig.expiration)
679 return -EINVAL;
680
681 name = dns_resource_key_name(rrsig->key);
682
683 n_key_labels = dns_name_count_labels(name);
684 if (n_key_labels < 0)
685 return n_key_labels;
686 if (rrsig->rrsig.labels > n_key_labels)
687 return -EINVAL;
688
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)
693 return -EINVAL;
694
695 r = dns_name_skip(name, n_key_labels - n_signer_labels, &name);
696 if (r < 0)
697 return r;
698 if (r == 0)
699 return -EINVAL;
700
701 /* Check if the signer is really a suffix of us */
702 r = dns_name_equal(name, rrsig->rrsig.signer);
703 if (r < 0)
704 return r;
705 if (r == 0)
706 return -EINVAL;
707
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;
711
712 return 0;
713 }
714
715 static int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) {
716 usec_t expiration, inception, skew;
717
718 assert(rrsig);
719 assert(rrsig->key->type == DNS_TYPE_RRSIG);
720
721 if (realtime == USEC_INFINITY)
722 realtime = now(CLOCK_REALTIME);
723
724 expiration = rrsig->rrsig.expiration * USEC_PER_SEC;
725 inception = rrsig->rrsig.inception * USEC_PER_SEC;
726
727 /* Consider inverted validity intervals as expired */
728 if (inception > expiration)
729 return true;
730
731 /* Permit a certain amount of clock skew of 10% of the valid
732 * time range. This takes inspiration from unbound's
733 * resolver. */
734 skew = (expiration - inception) / 10;
735 if (skew > SKEW_MAX)
736 skew = SKEW_MAX;
737
738 if (inception < skew)
739 inception = 0;
740 else
741 inception -= skew;
742
743 if (expiration + skew < expiration)
744 expiration = USEC_INFINITY;
745 else
746 expiration += skew;
747
748 return realtime < inception || realtime > expiration;
749 }
750
751 static hash_md_t algorithm_to_implementation_id(uint8_t algorithm) {
752
753 /* Translates a DNSSEC signature algorithm into an openssl/gcrypt digest identifier.
754 *
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. */
758
759 switch (algorithm) {
760
761 case DNSSEC_ALGORITHM_RSASHA1:
762 case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
763 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1);
764
765 case DNSSEC_ALGORITHM_RSASHA256:
766 case DNSSEC_ALGORITHM_ECDSAP256SHA256:
767 return OPENSSL_OR_GCRYPT(EVP_sha256(), GCRY_MD_SHA256);
768
769 case DNSSEC_ALGORITHM_ECDSAP384SHA384:
770 return OPENSSL_OR_GCRYPT(EVP_sha384(), GCRY_MD_SHA384);
771
772 case DNSSEC_ALGORITHM_RSASHA512:
773 return OPENSSL_OR_GCRYPT(EVP_sha512(), GCRY_MD_SHA512);
774
775 default:
776 return OPENSSL_OR_GCRYPT(NULL, -EOPNOTSUPP);
777 }
778 }
779
780 static void dnssec_fix_rrset_ttl(
781 DnsResourceRecord *list[],
782 unsigned n,
783 DnsResourceRecord *rrsig) {
784
785 assert(list);
786 assert(n > 0);
787 assert(rrsig);
788
789 for (unsigned k = 0; k < n; k++) {
790 DnsResourceRecord *rr = list[k];
791
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;
797
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;
801 }
802
803 rrsig->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
804 }
805
806 static int dnssec_rrset_serialize_sig(
807 DnsResourceRecord *rrsig,
808 const char *source,
809 DnsResourceRecord **list,
810 size_t list_len,
811 bool wildcard,
812 char **ret_sig_data,
813 size_t *ret_sig_size) {
814
815 _cleanup_(memstream_done) MemStream m = {};
816 uint8_t wire_format_name[DNS_WIRE_FORMAT_HOSTNAME_MAX];
817 DnsResourceRecord *rr;
818 FILE *f;
819 int r;
820
821 assert(rrsig);
822 assert(source);
823 assert(list || list_len == 0);
824 assert(ret_sig_data);
825 assert(ret_sig_size);
826
827 f = memstream_init(&m);
828 if (!f)
829 return -ENOMEM;
830
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);
838
839 r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true);
840 if (r < 0)
841 return r;
842 fwrite(wire_format_name, 1, r, f);
843
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);
846 if (r < 0)
847 return r;
848
849 for (size_t k = 0; k < list_len; k++) {
850 size_t l;
851
852 rr = list[k];
853
854 /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */
855 if (wildcard)
856 fwrite((uint8_t[]) { 1, '*'}, sizeof(uint8_t), 2, f);
857 fwrite(wire_format_name, 1, r, f);
858
859 fwrite_uint16(f, rr->key->type);
860 fwrite_uint16(f, rr->key->class);
861 fwrite_uint32(f, rrsig->rrsig.original_ttl);
862
863 l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr);
864 assert(l <= 0xFFFF);
865
866 fwrite_uint16(f, (uint16_t) l);
867 fwrite(DNS_RESOURCE_RECORD_RDATA(rr), 1, l, f);
868 }
869
870 return memstream_finalize(&m, ret_sig_data, ret_sig_size);
871 }
872
873 static int dnssec_rrset_verify_sig(
874 DnsResourceRecord *rrsig,
875 DnsResourceRecord *dnskey,
876 const char *sig_data,
877 size_t sig_size) {
878
879 assert(rrsig);
880 assert(dnskey);
881 assert(sig_data);
882 assert(sig_size > 0);
883
884 hash_md_t md_algorithm;
885
886 #if PREFER_OPENSSL
887 uint8_t hash[EVP_MAX_MD_SIZE];
888 unsigned hash_size;
889 #else
890 _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
891 void *hash;
892 size_t hash_size;
893
894 initialize_libgcrypt(false);
895 #endif
896
897 switch (rrsig->rrsig.algorithm) {
898 case DNSSEC_ALGORITHM_ED25519:
899 #if PREFER_OPENSSL || GCRYPT_VERSION_NUMBER >= 0x010600
900 return dnssec_eddsa_verify(
901 rrsig->rrsig.algorithm,
902 sig_data, sig_size,
903 rrsig,
904 dnskey);
905 #endif
906 case DNSSEC_ALGORITHM_ED448:
907 return -EOPNOTSUPP;
908 default:
909 /* OK, the RRs are now in canonical order. Let's calculate the digest */
910 md_algorithm = algorithm_to_implementation_id(rrsig->rrsig.algorithm);
911 #if PREFER_OPENSSL
912 if (!md_algorithm)
913 return -EOPNOTSUPP;
914
915 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new();
916 if (!ctx)
917 return -ENOMEM;
918
919 if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0)
920 return -EIO;
921
922 if (EVP_DigestUpdate(ctx, sig_data, sig_size) <= 0)
923 return -EIO;
924
925 if (EVP_DigestFinal_ex(ctx, hash, &hash_size) <= 0)
926 return -EIO;
927
928 assert(hash_size > 0);
929
930 #else
931 if (md_algorithm < 0)
932 return md_algorithm;
933
934 gcry_error_t err = gcry_md_open(&md, md_algorithm, 0);
935 if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
936 return -EIO;
937
938 hash_size = gcry_md_get_algo_dlen(md_algorithm);
939 assert(hash_size > 0);
940
941 gcry_md_write(md, sig_data, sig_size);
942
943 hash = gcry_md_read(md, 0);
944 if (!hash)
945 return -EIO;
946 #endif
947 }
948
949 switch (rrsig->rrsig.algorithm) {
950
951 case DNSSEC_ALGORITHM_RSASHA1:
952 case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
953 case DNSSEC_ALGORITHM_RSASHA256:
954 case DNSSEC_ALGORITHM_RSASHA512:
955 return dnssec_rsa_verify(
956 OPENSSL_OR_GCRYPT(md_algorithm, gcry_md_algo_name(md_algorithm)),
957 hash, hash_size,
958 rrsig,
959 dnskey);
960
961 case DNSSEC_ALGORITHM_ECDSAP256SHA256:
962 case DNSSEC_ALGORITHM_ECDSAP384SHA384:
963 return dnssec_ecdsa_verify(
964 OPENSSL_OR_GCRYPT(md_algorithm, gcry_md_algo_name(md_algorithm)),
965 rrsig->rrsig.algorithm,
966 hash, hash_size,
967 rrsig,
968 dnskey);
969
970 default:
971 assert_not_reached();
972 }
973 }
974
975 int dnssec_verify_rrset(
976 DnsAnswer *a,
977 const DnsResourceKey *key,
978 DnsResourceRecord *rrsig,
979 DnsResourceRecord *dnskey,
980 usec_t realtime,
981 DnssecResult *result) {
982
983 DnsResourceRecord **list, *rr;
984 const char *source, *name;
985 _cleanup_free_ char *sig_data = NULL;
986 size_t sig_size = 0; /* avoid false maybe-uninitialized warning */
987 size_t n = 0;
988 bool wildcard;
989 int r;
990
991 assert(key);
992 assert(rrsig);
993 assert(dnskey);
994 assert(result);
995 assert(rrsig->key->type == DNS_TYPE_RRSIG);
996 assert(dnskey->key->type == DNS_TYPE_DNSKEY);
997
998 /* Verifies that the RRSet matches the specified "key" in "a",
999 * using the signature "rrsig" and the key "dnskey". It's
1000 * assumed that RRSIG and DNSKEY match. */
1001
1002 r = dnssec_rrsig_prepare(rrsig);
1003 if (r == -EINVAL) {
1004 *result = DNSSEC_INVALID;
1005 return r;
1006 }
1007 if (r < 0)
1008 return r;
1009
1010 r = dnssec_rrsig_expired(rrsig, realtime);
1011 if (r < 0)
1012 return r;
1013 if (r > 0) {
1014 *result = DNSSEC_SIGNATURE_EXPIRED;
1015 return 0;
1016 }
1017
1018 name = dns_resource_key_name(key);
1019
1020 /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
1021 if (dns_type_apex_only(rrsig->rrsig.type_covered)) {
1022 r = dns_name_equal(rrsig->rrsig.signer, name);
1023 if (r < 0)
1024 return r;
1025 if (r == 0) {
1026 *result = DNSSEC_INVALID;
1027 return 0;
1028 }
1029 }
1030
1031 /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */
1032 if (rrsig->rrsig.type_covered == DNS_TYPE_DS) {
1033 r = dns_name_equal(rrsig->rrsig.signer, name);
1034 if (r < 0)
1035 return r;
1036 if (r > 0) {
1037 *result = DNSSEC_INVALID;
1038 return 0;
1039 }
1040 }
1041
1042 /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
1043 r = dns_name_suffix(name, rrsig->rrsig.labels, &source);
1044 if (r < 0)
1045 return r;
1046 if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) {
1047 /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */
1048 *result = DNSSEC_INVALID;
1049 return 0;
1050 }
1051 if (r == 1) {
1052 /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really
1053 * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */
1054 r = dns_name_startswith(name, "*");
1055 if (r < 0)
1056 return r;
1057 if (r > 0)
1058 source = name;
1059
1060 wildcard = r == 0;
1061 } else
1062 wildcard = r > 0;
1063
1064 /* Collect all relevant RRs in a single array, so that we can look at the RRset */
1065 list = newa(DnsResourceRecord *, dns_answer_size(a));
1066
1067 DNS_ANSWER_FOREACH(rr, a) {
1068 r = dns_resource_key_equal(key, rr->key);
1069 if (r < 0)
1070 return r;
1071 if (r == 0)
1072 continue;
1073
1074 /* We need the wire format for ordering, and digest calculation */
1075 r = dns_resource_record_to_wire_format(rr, true);
1076 if (r < 0)
1077 return r;
1078
1079 list[n++] = rr;
1080
1081 if (n > VERIFY_RRS_MAX)
1082 return -E2BIG;
1083 }
1084
1085 if (n <= 0)
1086 return -ENODATA;
1087
1088 /* Bring the RRs into canonical order */
1089 typesafe_qsort(list, n, rr_compare);
1090
1091 r = dnssec_rrset_serialize_sig(rrsig, source, list, n, wildcard,
1092 &sig_data, &sig_size);
1093 if (r < 0)
1094 return r;
1095
1096 r = dnssec_rrset_verify_sig(rrsig, dnskey, sig_data, sig_size);
1097 if (r == -EOPNOTSUPP) {
1098 *result = DNSSEC_UNSUPPORTED_ALGORITHM;
1099 return 0;
1100 }
1101 if (r < 0)
1102 return r;
1103
1104 /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */
1105 if (r > 0)
1106 dnssec_fix_rrset_ttl(list, n, rrsig);
1107
1108 if (r == 0)
1109 *result = DNSSEC_INVALID;
1110 else if (wildcard)
1111 *result = DNSSEC_VALIDATED_WILDCARD;
1112 else
1113 *result = DNSSEC_VALIDATED;
1114
1115 return 0;
1116 }
1117
1118 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
1119
1120 assert(rrsig);
1121 assert(dnskey);
1122
1123 /* Checks if the specified DNSKEY RR matches the key used for
1124 * the signature in the specified RRSIG RR */
1125
1126 if (rrsig->key->type != DNS_TYPE_RRSIG)
1127 return -EINVAL;
1128
1129 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1130 return 0;
1131 if (dnskey->key->class != rrsig->key->class)
1132 return 0;
1133 if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
1134 return 0;
1135 if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
1136 return 0;
1137 if (dnskey->dnskey.protocol != 3)
1138 return 0;
1139 if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
1140 return 0;
1141
1142 if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag)
1143 return 0;
1144
1145 return dns_name_equal(dns_resource_key_name(dnskey->key), rrsig->rrsig.signer);
1146 }
1147
1148 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
1149 assert(key);
1150 assert(rrsig);
1151
1152 /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
1153
1154 if (rrsig->key->type != DNS_TYPE_RRSIG)
1155 return 0;
1156 if (rrsig->key->class != key->class)
1157 return 0;
1158 if (rrsig->rrsig.type_covered != key->type)
1159 return 0;
1160
1161 return dns_name_equal(dns_resource_key_name(rrsig->key), dns_resource_key_name(key));
1162 }
1163
1164 int dnssec_verify_rrset_search(
1165 DnsAnswer *a,
1166 const DnsResourceKey *key,
1167 DnsAnswer *validated_dnskeys,
1168 usec_t realtime,
1169 DnssecResult *result,
1170 DnsResourceRecord **ret_rrsig) {
1171
1172 bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
1173 unsigned nvalidations = 0;
1174 DnsResourceRecord *rrsig;
1175 int r;
1176
1177 assert(key);
1178 assert(result);
1179
1180 /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
1181
1182 if (dns_answer_isempty(a))
1183 return -ENODATA;
1184
1185 /* Iterate through each RRSIG RR. */
1186 DNS_ANSWER_FOREACH(rrsig, a) {
1187 DnsResourceRecord *dnskey;
1188 DnsAnswerFlags flags;
1189
1190 /* Is this an RRSIG RR that applies to RRs matching our key? */
1191 r = dnssec_key_match_rrsig(key, rrsig);
1192 if (r < 0)
1193 return r;
1194 if (r == 0)
1195 continue;
1196
1197 found_rrsig = true;
1198
1199 /* Look for a matching key */
1200 DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
1201 DnssecResult one_result;
1202
1203 if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
1204 continue;
1205
1206 /* Is this a DNSKEY RR that matches they key of our RRSIG? */
1207 r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false);
1208 if (r < 0)
1209 return r;
1210 if (r == 0)
1211 continue;
1212
1213 /* Take the time here, if it isn't set yet, so
1214 * that we do all validations with the same
1215 * time. */
1216 if (realtime == USEC_INFINITY)
1217 realtime = now(CLOCK_REALTIME);
1218
1219 /* Have we seen an unreasonable number of invalid signaures? */
1220 if (nvalidations > DNSSEC_INVALID_MAX) {
1221 if (ret_rrsig)
1222 *ret_rrsig = NULL;
1223 *result = DNSSEC_TOO_MANY_VALIDATIONS;
1224 return (int) nvalidations;
1225 }
1226
1227 /* Yay, we found a matching RRSIG with a matching
1228 * DNSKEY, awesome. Now let's verify all entries of
1229 * the RRSet against the RRSIG and DNSKEY
1230 * combination. */
1231
1232 r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
1233 if (r < 0)
1234 return r;
1235
1236 nvalidations++;
1237
1238 switch (one_result) {
1239
1240 case DNSSEC_VALIDATED:
1241 case DNSSEC_VALIDATED_WILDCARD:
1242 /* Yay, the RR has been validated,
1243 * return immediately, but fix up the expiry */
1244 if (ret_rrsig)
1245 *ret_rrsig = rrsig;
1246
1247 *result = one_result;
1248 return (int) nvalidations;
1249
1250 case DNSSEC_INVALID:
1251 /* If the signature is invalid, let's try another
1252 key and/or signature. After all they
1253 key_tags and stuff are not unique, and
1254 might be shared by multiple keys. */
1255 found_invalid = true;
1256 continue;
1257
1258 case DNSSEC_UNSUPPORTED_ALGORITHM:
1259 /* If the key algorithm is
1260 unsupported, try another
1261 RRSIG/DNSKEY pair, but remember we
1262 encountered this, so that we can
1263 return a proper error when we
1264 encounter nothing better. */
1265 found_unsupported_algorithm = true;
1266 continue;
1267
1268 case DNSSEC_SIGNATURE_EXPIRED:
1269 /* If the signature is expired, try
1270 another one, but remember it, so
1271 that we can return this */
1272 found_expired_rrsig = true;
1273 continue;
1274
1275 default:
1276 assert_not_reached();
1277 }
1278 }
1279 }
1280
1281 if (found_expired_rrsig)
1282 *result = DNSSEC_SIGNATURE_EXPIRED;
1283 else if (found_unsupported_algorithm)
1284 *result = DNSSEC_UNSUPPORTED_ALGORITHM;
1285 else if (found_invalid)
1286 *result = DNSSEC_INVALID;
1287 else if (found_rrsig)
1288 *result = DNSSEC_MISSING_KEY;
1289 else
1290 *result = DNSSEC_NO_SIGNATURE;
1291
1292 if (ret_rrsig)
1293 *ret_rrsig = NULL;
1294
1295 return (int) nvalidations;
1296 }
1297
1298 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
1299 DnsResourceRecord *rr;
1300 int r;
1301
1302 /* Checks whether there's at least one RRSIG in 'a' that protects RRs of the specified key */
1303
1304 DNS_ANSWER_FOREACH(rr, a) {
1305 r = dnssec_key_match_rrsig(key, rr);
1306 if (r < 0)
1307 return r;
1308 if (r > 0)
1309 return 1;
1310 }
1311
1312 return 0;
1313 }
1314
1315 static hash_md_t digest_to_hash_md(uint8_t algorithm) {
1316
1317 /* Translates a DNSSEC digest algorithm into an openssl/gcrypt digest identifier */
1318
1319 switch (algorithm) {
1320
1321 case DNSSEC_DIGEST_SHA1:
1322 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1);
1323
1324 case DNSSEC_DIGEST_SHA256:
1325 return OPENSSL_OR_GCRYPT(EVP_sha256(), GCRY_MD_SHA256);
1326
1327 case DNSSEC_DIGEST_SHA384:
1328 return OPENSSL_OR_GCRYPT(EVP_sha384(), GCRY_MD_SHA384);
1329
1330 default:
1331 return OPENSSL_OR_GCRYPT(NULL, -EOPNOTSUPP);
1332 }
1333 }
1334
1335 int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
1336 uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
1337 int r;
1338
1339 assert(dnskey);
1340 assert(ds);
1341
1342 /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
1343
1344 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1345 return -EINVAL;
1346 if (ds->key->type != DNS_TYPE_DS)
1347 return -EINVAL;
1348 if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
1349 return -EKEYREJECTED;
1350 if (!mask_revoke && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
1351 return -EKEYREJECTED;
1352 if (dnskey->dnskey.protocol != 3)
1353 return -EKEYREJECTED;
1354
1355 if (dnskey->dnskey.algorithm != ds->ds.algorithm)
1356 return 0;
1357 if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag)
1358 return 0;
1359
1360 r = dns_name_to_wire_format(dns_resource_key_name(dnskey->key), wire_format, sizeof wire_format, true);
1361 if (r < 0)
1362 return r;
1363
1364 hash_md_t md_algorithm = digest_to_hash_md(ds->ds.digest_type);
1365
1366 #if PREFER_OPENSSL
1367 if (!md_algorithm)
1368 return -EOPNOTSUPP;
1369
1370 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = NULL;
1371 uint8_t result[EVP_MAX_MD_SIZE];
1372
1373 unsigned hash_size = EVP_MD_size(md_algorithm);
1374 assert(hash_size > 0);
1375
1376 if (ds->ds.digest_size != hash_size)
1377 return 0;
1378
1379 ctx = EVP_MD_CTX_new();
1380 if (!ctx)
1381 return -ENOMEM;
1382
1383 if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0)
1384 return -EIO;
1385
1386 if (EVP_DigestUpdate(ctx, wire_format, r) <= 0)
1387 return -EIO;
1388
1389 if (mask_revoke)
1390 md_add_uint16(ctx, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
1391 else
1392 md_add_uint16(ctx, dnskey->dnskey.flags);
1393
1394 r = md_add_uint8(ctx, dnskey->dnskey.protocol);
1395 if (r <= 0)
1396 return r;
1397 r = md_add_uint8(ctx, dnskey->dnskey.algorithm);
1398 if (r <= 0)
1399 return r;
1400 if (EVP_DigestUpdate(ctx, dnskey->dnskey.key, dnskey->dnskey.key_size) <= 0)
1401 return -EIO;
1402
1403 if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
1404 return -EIO;
1405
1406 #else
1407 if (md_algorithm < 0)
1408 return -EOPNOTSUPP;
1409
1410 initialize_libgcrypt(false);
1411
1412 _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
1413
1414 size_t hash_size = gcry_md_get_algo_dlen(md_algorithm);
1415 assert(hash_size > 0);
1416
1417 if (ds->ds.digest_size != hash_size)
1418 return 0;
1419
1420 gcry_error_t err = gcry_md_open(&md, md_algorithm, 0);
1421 if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
1422 return -EIO;
1423
1424 gcry_md_write(md, wire_format, r);
1425 if (mask_revoke)
1426 md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
1427 else
1428 md_add_uint16(md, dnskey->dnskey.flags);
1429 md_add_uint8(md, dnskey->dnskey.protocol);
1430 md_add_uint8(md, dnskey->dnskey.algorithm);
1431 gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size);
1432
1433 void *result = gcry_md_read(md, 0);
1434 if (!result)
1435 return -EIO;
1436 #endif
1437
1438 return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0;
1439 }
1440
1441 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
1442 DnsResourceRecord *ds;
1443 DnsAnswerFlags flags;
1444 int r;
1445
1446 assert(dnskey);
1447
1448 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1449 return 0;
1450
1451 DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
1452
1453 if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
1454 continue;
1455
1456 if (ds->key->type != DNS_TYPE_DS)
1457 continue;
1458 if (ds->key->class != dnskey->key->class)
1459 continue;
1460
1461 r = dns_name_equal(dns_resource_key_name(dnskey->key), dns_resource_key_name(ds->key));
1462 if (r < 0)
1463 return r;
1464 if (r == 0)
1465 continue;
1466
1467 r = dnssec_verify_dnskey_by_ds(dnskey, ds, false);
1468 if (IN_SET(r, -EKEYREJECTED, -EOPNOTSUPP))
1469 return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */
1470 if (r < 0)
1471 return r;
1472 if (r > 0)
1473 return 1;
1474 }
1475
1476 return 0;
1477 }
1478
1479 static hash_md_t nsec3_hash_to_hash_md(uint8_t algorithm) {
1480
1481 /* Translates a DNSSEC NSEC3 hash algorithm into an openssl/gcrypt digest identifier */
1482
1483 switch (algorithm) {
1484
1485 case NSEC3_ALGORITHM_SHA1:
1486 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1);
1487
1488 default:
1489 return OPENSSL_OR_GCRYPT(NULL, -EOPNOTSUPP);
1490 }
1491 }
1492
1493 int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
1494 uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
1495 int r;
1496
1497 assert(nsec3);
1498 assert(name);
1499 assert(ret);
1500
1501 if (nsec3->key->type != DNS_TYPE_NSEC3)
1502 return -EINVAL;
1503
1504 if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX)
1505 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1506 "Ignoring NSEC3 RR %s with excessive number of iterations.",
1507 dns_resource_record_to_string(nsec3));
1508
1509 hash_md_t algorithm = nsec3_hash_to_hash_md(nsec3->nsec3.algorithm);
1510 #if PREFER_OPENSSL
1511 if (!algorithm)
1512 return -EOPNOTSUPP;
1513
1514 size_t hash_size = EVP_MD_size(algorithm);
1515 assert(hash_size > 0);
1516
1517 if (nsec3->nsec3.next_hashed_name_size != hash_size)
1518 return -EINVAL;
1519
1520 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new();
1521 if (!ctx)
1522 return -ENOMEM;
1523
1524 if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0)
1525 return -EIO;
1526
1527 r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
1528 if (r < 0)
1529 return r;
1530
1531 if (EVP_DigestUpdate(ctx, wire_format, r) <= 0)
1532 return -EIO;
1533 if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0)
1534 return -EIO;
1535
1536 uint8_t result[EVP_MAX_MD_SIZE];
1537 if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
1538 return -EIO;
1539
1540 for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) {
1541 if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0)
1542 return -EIO;
1543 if (EVP_DigestUpdate(ctx, result, hash_size) <= 0)
1544 return -EIO;
1545 if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0)
1546 return -EIO;
1547
1548 if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
1549 return -EIO;
1550 }
1551 #else
1552 if (algorithm < 0)
1553 return algorithm;
1554
1555 initialize_libgcrypt(false);
1556
1557 unsigned hash_size = gcry_md_get_algo_dlen(algorithm);
1558 assert(hash_size > 0);
1559
1560 if (nsec3->nsec3.next_hashed_name_size != hash_size)
1561 return -EINVAL;
1562
1563 r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
1564 if (r < 0)
1565 return r;
1566
1567 _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
1568 gcry_error_t err = gcry_md_open(&md, algorithm, 0);
1569 if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
1570 return -EIO;
1571
1572 gcry_md_write(md, wire_format, r);
1573 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
1574
1575 void *result = gcry_md_read(md, 0);
1576 if (!result)
1577 return -EIO;
1578
1579 for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) {
1580 uint8_t tmp[hash_size];
1581 memcpy(tmp, result, hash_size);
1582
1583 gcry_md_reset(md);
1584 gcry_md_write(md, tmp, hash_size);
1585 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
1586
1587 result = gcry_md_read(md, 0);
1588 if (!result)
1589 return -EIO;
1590 }
1591 #endif
1592
1593 memcpy(ret, result, hash_size);
1594 return (int) hash_size;
1595 }
1596
1597 static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
1598 const char *a, *b;
1599 int r;
1600
1601 assert(rr);
1602
1603 if (rr->key->type != DNS_TYPE_NSEC3)
1604 return 0;
1605
1606 /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
1607 if (!IN_SET(rr->nsec3.flags, 0, 1))
1608 return 0;
1609
1610 /* Ignore NSEC3 RRs whose algorithm we don't know */
1611 #if PREFER_OPENSSL
1612 if (!nsec3_hash_to_hash_md(rr->nsec3.algorithm))
1613 return 0;
1614 #else
1615 if (nsec3_hash_to_hash_md(rr->nsec3.algorithm) < 0)
1616 return 0;
1617 #endif
1618
1619 /* Ignore NSEC3 RRs with an excessive number of required iterations */
1620 if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
1621 return 0;
1622
1623 /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this
1624 * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */
1625 if (!IN_SET(rr->n_skip_labels_source, 0, UINT8_MAX))
1626 return 0;
1627 /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */
1628 if (!IN_SET(rr->n_skip_labels_signer, 1, UINT8_MAX))
1629 return 0;
1630
1631 if (!nsec3)
1632 return 1;
1633
1634 /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
1635
1636 if (nsec3 == rr) /* Shortcut */
1637 return 1;
1638
1639 if (rr->key->class != nsec3->key->class)
1640 return 0;
1641 if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
1642 return 0;
1643 if (rr->nsec3.iterations != nsec3->nsec3.iterations)
1644 return 0;
1645 if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
1646 return 0;
1647 if (memcmp_safe(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
1648 return 0;
1649
1650 a = dns_resource_key_name(rr->key);
1651 r = dns_name_parent(&a); /* strip off hash */
1652 if (r <= 0)
1653 return r;
1654
1655 b = dns_resource_key_name(nsec3->key);
1656 r = dns_name_parent(&b); /* strip off hash */
1657 if (r <= 0)
1658 return r;
1659
1660 /* Make sure both have the same parent */
1661 return dns_name_equal(a, b);
1662 }
1663
1664 static int nsec3_hashed_domain_format(const uint8_t *hashed, size_t hashed_size, const char *zone, char **ret) {
1665 _cleanup_free_ char *l = NULL;
1666 char *j;
1667
1668 assert(hashed);
1669 assert(hashed_size > 0);
1670 assert(zone);
1671 assert(ret);
1672
1673 l = base32hexmem(hashed, hashed_size, false);
1674 if (!l)
1675 return -ENOMEM;
1676
1677 j = strjoin(l, ".", zone);
1678 if (!j)
1679 return -ENOMEM;
1680
1681 *ret = j;
1682 return (int) hashed_size;
1683 }
1684
1685 static int nsec3_hashed_domain_make(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) {
1686 uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
1687 int hashed_size;
1688
1689 assert(nsec3);
1690 assert(domain);
1691 assert(zone);
1692 assert(ret);
1693
1694 hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed);
1695 if (hashed_size < 0)
1696 return hashed_size;
1697
1698 return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret);
1699 }
1700
1701 /* See RFC 5155, Section 8
1702 * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest
1703 * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there
1704 * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that
1705 * matches the wildcard domain.
1706 *
1707 * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or
1708 * that there is no proof either way. The latter is the case if a proof of non-existence of a given
1709 * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records
1710 * to conclude anything we indicate this by returning NO_RR. */
1711 static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
1712 _cleanup_free_ char *next_closer_domain = NULL, *wildcard_domain = NULL;
1713 const char *zone, *p, *pp = NULL, *wildcard;
1714 DnsResourceRecord *rr, *enclosure_rr, *zone_rr, *wildcard_rr = NULL;
1715 DnsAnswerFlags flags;
1716 int hashed_size, r;
1717 bool a, no_closer = false, no_wildcard = false, optout = false;
1718
1719 assert(key);
1720 assert(result);
1721
1722 /* First step, find the zone name and the NSEC3 parameters of the zone.
1723 * it is sufficient to look for the longest common suffix we find with
1724 * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
1725 * records from a given zone in a response must use the same
1726 * parameters. */
1727 zone = dns_resource_key_name(key);
1728 for (;;) {
1729 DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) {
1730 r = nsec3_is_good(zone_rr, NULL);
1731 if (r < 0)
1732 return r;
1733 if (r == 0)
1734 continue;
1735
1736 r = dns_name_equal_skip(dns_resource_key_name(zone_rr->key), 1, zone);
1737 if (r < 0)
1738 return r;
1739 if (r > 0)
1740 goto found_zone;
1741 }
1742
1743 /* Strip one label from the front */
1744 r = dns_name_parent(&zone);
1745 if (r < 0)
1746 return r;
1747 if (r == 0)
1748 break;
1749 }
1750
1751 *result = DNSSEC_NSEC_NO_RR;
1752 return 0;
1753
1754 found_zone:
1755 /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
1756 p = dns_resource_key_name(key);
1757 for (;;) {
1758 _cleanup_free_ char *hashed_domain = NULL;
1759
1760 hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain);
1761 if (hashed_size == -EOPNOTSUPP) {
1762 *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
1763 return 0;
1764 }
1765 if (hashed_size < 0)
1766 return hashed_size;
1767
1768 DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) {
1769
1770 r = nsec3_is_good(enclosure_rr, zone_rr);
1771 if (r < 0)
1772 return r;
1773 if (r == 0)
1774 continue;
1775
1776 if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
1777 continue;
1778
1779 r = dns_name_equal(dns_resource_key_name(enclosure_rr->key), hashed_domain);
1780 if (r < 0)
1781 return r;
1782 if (r > 0) {
1783 a = flags & DNS_ANSWER_AUTHENTICATED;
1784 goto found_closest_encloser;
1785 }
1786 }
1787
1788 /* We didn't find the closest encloser with this name,
1789 * but let's remember this domain name, it might be
1790 * the next closer name */
1791
1792 pp = p;
1793
1794 /* Strip one label from the front */
1795 r = dns_name_parent(&p);
1796 if (r < 0)
1797 return r;
1798 if (r == 0)
1799 break;
1800 }
1801
1802 *result = DNSSEC_NSEC_NO_RR;
1803 return 0;
1804
1805 found_closest_encloser:
1806 /* We found a closest encloser in 'p'; next closer is 'pp' */
1807
1808 if (!pp) {
1809 /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR
1810 * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are
1811 * appropriately set. */
1812
1813 if (key->type == DNS_TYPE_DS) {
1814 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1815 return -EBADMSG;
1816 } else {
1817 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
1818 !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1819 return -EBADMSG;
1820 }
1821
1822 /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
1823 if (bitmap_isset(enclosure_rr->nsec3.types, key->type))
1824 *result = DNSSEC_NSEC_FOUND;
1825 else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME))
1826 *result = DNSSEC_NSEC_CNAME;
1827 else
1828 *result = DNSSEC_NSEC_NODATA;
1829
1830 if (authenticated)
1831 *authenticated = a;
1832 if (ttl)
1833 *ttl = enclosure_rr->ttl;
1834
1835 return 0;
1836 }
1837
1838 /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
1839 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME))
1840 return -EBADMSG;
1841
1842 /* Ensure that this data is from the delegated domain
1843 * (i.e. originates from the "lower" DNS server), and isn't
1844 * just glue records (i.e. doesn't originate from the "upper"
1845 * DNS server). */
1846 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
1847 !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1848 return -EBADMSG;
1849
1850 /* Prove that there is no next closer and whether or not there is a wildcard domain. */
1851
1852 wildcard = strjoina("*.", p);
1853 r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain);
1854 if (r < 0)
1855 return r;
1856 if (r != hashed_size)
1857 return -EBADMSG;
1858
1859 r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain);
1860 if (r < 0)
1861 return r;
1862 if (r != hashed_size)
1863 return -EBADMSG;
1864
1865 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
1866 _cleanup_free_ char *next_hashed_domain = NULL;
1867
1868 r = nsec3_is_good(rr, zone_rr);
1869 if (r < 0)
1870 return r;
1871 if (r == 0)
1872 continue;
1873
1874 r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain);
1875 if (r < 0)
1876 return r;
1877
1878 r = dns_name_between(dns_resource_key_name(rr->key), next_closer_domain, next_hashed_domain);
1879 if (r < 0)
1880 return r;
1881 if (r > 0) {
1882 if (rr->nsec3.flags & 1)
1883 optout = true;
1884
1885 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1886
1887 no_closer = true;
1888 }
1889
1890 r = dns_name_equal(dns_resource_key_name(rr->key), wildcard_domain);
1891 if (r < 0)
1892 return r;
1893 if (r > 0) {
1894 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1895
1896 wildcard_rr = rr;
1897 }
1898
1899 r = dns_name_between(dns_resource_key_name(rr->key), wildcard_domain, next_hashed_domain);
1900 if (r < 0)
1901 return r;
1902 if (r > 0) {
1903 if (rr->nsec3.flags & 1)
1904 /* This only makes sense if we have a wildcard delegation, which is
1905 * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on
1906 * this not happening, so hence cannot simply conclude NXDOMAIN as
1907 * we would wish */
1908 optout = true;
1909
1910 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1911
1912 no_wildcard = true;
1913 }
1914 }
1915
1916 if (wildcard_rr && no_wildcard)
1917 return -EBADMSG;
1918
1919 if (!no_closer) {
1920 *result = DNSSEC_NSEC_NO_RR;
1921 return 0;
1922 }
1923
1924 if (wildcard_rr) {
1925 /* A wildcard exists that matches our query. */
1926 if (optout)
1927 /* This is not specified in any RFC to the best of my knowledge, but
1928 * if the next closer enclosure is covered by an opt-out NSEC3 RR
1929 * it means that we cannot prove that the source of synthesis is
1930 * correct, as there may be a closer match. */
1931 *result = DNSSEC_NSEC_OPTOUT;
1932 else if (bitmap_isset(wildcard_rr->nsec3.types, key->type))
1933 *result = DNSSEC_NSEC_FOUND;
1934 else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME))
1935 *result = DNSSEC_NSEC_CNAME;
1936 else
1937 *result = DNSSEC_NSEC_NODATA;
1938 } else {
1939 if (optout)
1940 /* The RFC only specifies that we have to care for optout for NODATA for
1941 * DS records. However, children of an insecure opt-out delegation should
1942 * also be considered opt-out, rather than verified NXDOMAIN.
1943 * Note that we do not require a proof of wildcard non-existence if the
1944 * next closer domain is covered by an opt-out, as that would not provide
1945 * any additional information. */
1946 *result = DNSSEC_NSEC_OPTOUT;
1947 else if (no_wildcard)
1948 *result = DNSSEC_NSEC_NXDOMAIN;
1949 else {
1950 *result = DNSSEC_NSEC_NO_RR;
1951
1952 return 0;
1953 }
1954 }
1955
1956 if (authenticated)
1957 *authenticated = a;
1958
1959 if (ttl)
1960 *ttl = enclosure_rr->ttl;
1961
1962 return 0;
1963 }
1964
1965 static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) {
1966 char label[DNS_LABEL_MAX+1];
1967 const char *n;
1968 int r;
1969
1970 assert(rr);
1971 assert(rr->key->type == DNS_TYPE_NSEC);
1972
1973 /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */
1974
1975 if (rr->n_skip_labels_source != 1)
1976 return 0;
1977
1978 n = dns_resource_key_name(rr->key);
1979 r = dns_label_unescape(&n, label, sizeof label, 0);
1980 if (r <= 0)
1981 return r;
1982 if (r != 1 || label[0] != '*')
1983 return 0;
1984
1985 return dns_name_endswith(name, n);
1986 }
1987
1988 static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) {
1989 const char *nn, *common_suffix;
1990 int r;
1991
1992 assert(rr);
1993 assert(rr->key->type == DNS_TYPE_NSEC);
1994
1995 /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT)
1996 *
1997 * A couple of examples:
1998 *
1999 * NSEC bar → waldo.foo.bar: indicates that foo.bar exists and is an ENT
2000 * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs
2001 * NSEC yyy.zzz.xoo.bar → bar: indicates pretty much nothing about ENTs
2002 */
2003
2004 /* First, determine parent of next domain. */
2005 nn = rr->nsec.next_domain_name;
2006 r = dns_name_parent(&nn);
2007 if (r <= 0)
2008 return r;
2009
2010 /* If the name we just determined is not equal or child of the name we are interested in, then we can't say
2011 * anything at all. */
2012 r = dns_name_endswith(nn, name);
2013 if (r <= 0)
2014 return r;
2015
2016 /* 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. */
2017 r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
2018 if (r < 0)
2019 return r;
2020
2021 return dns_name_endswith(name, common_suffix);
2022 }
2023
2024 static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) {
2025 int r;
2026
2027 assert(rr);
2028 assert(rr->key->type == DNS_TYPE_NSEC);
2029
2030 /* Checks whether this NSEC originates to the parent zone or the child zone. */
2031
2032 r = dns_name_parent(&name);
2033 if (r <= 0)
2034 return r;
2035
2036 r = dns_name_equal(name, dns_resource_key_name(rr->key));
2037 if (r <= 0)
2038 return r;
2039
2040 /* DNAME, and NS without SOA is an indication for a delegation. */
2041 if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME))
2042 return 1;
2043
2044 if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
2045 return 1;
2046
2047 return 0;
2048 }
2049
2050 static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
2051 const char *signer;
2052 int r;
2053
2054 assert(rr);
2055 assert(rr->key->type == DNS_TYPE_NSEC);
2056
2057 /* Checks whether the name is covered by this NSEC RR. This means, that the name is somewhere below the NSEC's
2058 * signer name, and between the NSEC's two names. */
2059
2060 r = dns_resource_record_signer(rr, &signer);
2061 if (r < 0)
2062 return r;
2063
2064 r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
2065 if (r <= 0)
2066 return r;
2067
2068 return dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
2069 }
2070
2071 static int dnssec_nsec_generate_wildcard(DnsResourceRecord *rr, const char *name, char **wc) {
2072 const char *common_suffix1, *common_suffix2, *signer;
2073 int r, labels1, labels2;
2074
2075 assert(rr);
2076 assert(rr->key->type == DNS_TYPE_NSEC);
2077
2078 /* Generates "Wildcard at the Closest Encloser" for the given name and NSEC RR. */
2079
2080 r = dns_resource_record_signer(rr, &signer);
2081 if (r < 0)
2082 return r;
2083
2084 r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
2085 if (r <= 0)
2086 return r;
2087
2088 r = dns_name_common_suffix(name, dns_resource_key_name(rr->key), &common_suffix1);
2089 if (r < 0)
2090 return r;
2091
2092 r = dns_name_common_suffix(name, rr->nsec.next_domain_name, &common_suffix2);
2093 if (r < 0)
2094 return r;
2095
2096 labels1 = dns_name_count_labels(common_suffix1);
2097 if (labels1 < 0)
2098 return labels1;
2099
2100 labels2 = dns_name_count_labels(common_suffix2);
2101 if (labels2 < 0)
2102 return labels2;
2103
2104 if (labels1 > labels2)
2105 r = dns_name_concat("*", common_suffix1, 0, wc);
2106 else
2107 r = dns_name_concat("*", common_suffix2, 0, wc);
2108
2109 if (r < 0)
2110 return r;
2111
2112 return 0;
2113 }
2114
2115 int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
2116 bool have_nsec3 = false, covering_rr_authenticated = false, wildcard_rr_authenticated = false;
2117 DnsResourceRecord *rr, *covering_rr = NULL, *wildcard_rr = NULL;
2118 DnsAnswerFlags flags;
2119 const char *name;
2120 int r;
2121
2122 assert(key);
2123 assert(result);
2124
2125 /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
2126
2127 name = dns_resource_key_name(key);
2128
2129 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2130
2131 if (rr->key->class != key->class)
2132 continue;
2133
2134 have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3);
2135
2136 if (rr->key->type != DNS_TYPE_NSEC)
2137 continue;
2138
2139 /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */
2140 r = dns_resource_record_is_synthetic(rr);
2141 if (r == -ENODATA) /* No signing RR known. */
2142 continue;
2143 if (r < 0)
2144 return r;
2145 if (r > 0)
2146 continue;
2147
2148 /* Check if this is a direct match. If so, we have encountered a NODATA case */
2149 r = dns_name_equal(dns_resource_key_name(rr->key), name);
2150 if (r < 0)
2151 return r;
2152 if (r == 0) {
2153 /* If it's not a direct match, maybe it's a wild card match? */
2154 r = dnssec_nsec_wildcard_equal(rr, name);
2155 if (r < 0)
2156 return r;
2157 }
2158 if (r > 0) {
2159 if (key->type == DNS_TYPE_DS) {
2160 /* If we look for a DS RR and the server sent us the NSEC RR of the child zone
2161 * we have a problem. For DS RRs we want the NSEC RR from the parent */
2162 if (bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
2163 continue;
2164 } else {
2165 /* For all RR types, ensure that if NS is set SOA is set too, so that we know
2166 * we got the child's NSEC. */
2167 if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) &&
2168 !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
2169 continue;
2170 }
2171
2172 if (bitmap_isset(rr->nsec.types, key->type))
2173 *result = DNSSEC_NSEC_FOUND;
2174 else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME))
2175 *result = DNSSEC_NSEC_CNAME;
2176 else
2177 *result = DNSSEC_NSEC_NODATA;
2178
2179 if (authenticated)
2180 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2181 if (ttl)
2182 *ttl = rr->ttl;
2183
2184 return 0;
2185 }
2186
2187 /* Check if the name we are looking for is an empty non-terminal within the owner or next name
2188 * of the NSEC RR. */
2189 r = dnssec_nsec_in_path(rr, name);
2190 if (r < 0)
2191 return r;
2192 if (r > 0) {
2193 *result = DNSSEC_NSEC_NODATA;
2194
2195 if (authenticated)
2196 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2197 if (ttl)
2198 *ttl = rr->ttl;
2199
2200 return 0;
2201 }
2202
2203 /* The following two "covering" checks, are not useful if the NSEC is from the parent */
2204 r = dnssec_nsec_from_parent_zone(rr, name);
2205 if (r < 0)
2206 return r;
2207 if (r > 0)
2208 continue;
2209
2210 /* Check if this NSEC RR proves the absence of an explicit RR under this name */
2211 r = dnssec_nsec_covers(rr, name);
2212 if (r < 0)
2213 return r;
2214 if (r > 0 && (!covering_rr || !covering_rr_authenticated)) {
2215 covering_rr = rr;
2216 covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2217 }
2218 }
2219
2220 if (covering_rr) {
2221 _cleanup_free_ char *wc = NULL;
2222 r = dnssec_nsec_generate_wildcard(covering_rr, name, &wc);
2223 if (r < 0)
2224 return r;
2225
2226 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2227
2228 if (rr->key->class != key->class)
2229 continue;
2230
2231 if (rr->key->type != DNS_TYPE_NSEC)
2232 continue;
2233
2234 /* Check if this NSEC RR proves the nonexistence of the wildcard */
2235 r = dnssec_nsec_covers(rr, wc);
2236 if (r < 0)
2237 return r;
2238 if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) {
2239 wildcard_rr = rr;
2240 wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2241 }
2242 }
2243 }
2244
2245 if (covering_rr && wildcard_rr) {
2246 /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we
2247 * proved the NXDOMAIN case. */
2248 *result = DNSSEC_NSEC_NXDOMAIN;
2249
2250 if (authenticated)
2251 *authenticated = covering_rr_authenticated && wildcard_rr_authenticated;
2252 if (ttl)
2253 *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl);
2254
2255 return 0;
2256 }
2257
2258 /* OK, this was not sufficient. Let's see if NSEC3 can help. */
2259 if (have_nsec3)
2260 return dnssec_test_nsec3(answer, key, result, authenticated, ttl);
2261
2262 /* No appropriate NSEC RR found, report this. */
2263 *result = DNSSEC_NSEC_NO_RR;
2264 return 0;
2265 }
2266
2267 static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) {
2268 DnsResourceRecord *rr;
2269 DnsAnswerFlags flags;
2270 int r;
2271
2272 assert(name);
2273 assert(zone);
2274
2275 /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified
2276 * 'zone'. The 'zone' must be a suffix of the 'name'. */
2277
2278 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2279 bool found = false;
2280
2281 if (rr->key->type != type && type != DNS_TYPE_ANY)
2282 continue;
2283
2284 switch (rr->key->type) {
2285
2286 case DNS_TYPE_NSEC:
2287
2288 /* We only care for NSEC RRs from the indicated zone */
2289 r = dns_resource_record_is_signer(rr, zone);
2290 if (r < 0)
2291 return r;
2292 if (r == 0)
2293 continue;
2294
2295 r = dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
2296 if (r < 0)
2297 return r;
2298
2299 found = r > 0;
2300 break;
2301
2302 case DNS_TYPE_NSEC3: {
2303 _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL;
2304
2305 /* We only care for NSEC3 RRs from the indicated zone */
2306 r = dns_resource_record_is_signer(rr, zone);
2307 if (r < 0)
2308 return r;
2309 if (r == 0)
2310 continue;
2311
2312 r = nsec3_is_good(rr, NULL);
2313 if (r < 0)
2314 return r;
2315 if (r == 0)
2316 break;
2317
2318 /* Format the domain we are testing with the NSEC3 RR's hash function */
2319 r = nsec3_hashed_domain_make(
2320 rr,
2321 name,
2322 zone,
2323 &hashed_domain);
2324 if (r < 0)
2325 return r;
2326 if ((size_t) r != rr->nsec3.next_hashed_name_size)
2327 break;
2328
2329 /* Format the NSEC3's next hashed name as proper domain name */
2330 r = nsec3_hashed_domain_format(
2331 rr->nsec3.next_hashed_name,
2332 rr->nsec3.next_hashed_name_size,
2333 zone,
2334 &next_hashed_domain);
2335 if (r < 0)
2336 return r;
2337
2338 r = dns_name_between(dns_resource_key_name(rr->key), hashed_domain, next_hashed_domain);
2339 if (r < 0)
2340 return r;
2341
2342 found = r > 0;
2343 break;
2344 }
2345
2346 default:
2347 continue;
2348 }
2349
2350 if (found) {
2351 if (authenticated)
2352 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2353 return 1;
2354 }
2355 }
2356
2357 return 0;
2358 }
2359
2360 static int dnssec_test_positive_wildcard_nsec3(
2361 DnsAnswer *answer,
2362 const char *name,
2363 const char *source,
2364 const char *zone,
2365 bool *authenticated) {
2366
2367 const char *next_closer = NULL;
2368 int r;
2369
2370 /* Run a positive NSEC3 wildcard proof. Specifically:
2371 *
2372 * A proof that the "next closer" of the generating wildcard does not exist.
2373 *
2374 * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for
2375 * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name
2376 * exists for the NSEC3 RR and we are done.
2377 *
2378 * 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
2379 * c.d.e.f does not exist. */
2380
2381 for (;;) {
2382 next_closer = name;
2383 r = dns_name_parent(&name);
2384 if (r <= 0)
2385 return r;
2386
2387 r = dns_name_equal(name, source);
2388 if (r < 0)
2389 return r;
2390 if (r > 0)
2391 break;
2392 }
2393
2394 return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated);
2395 }
2396
2397 static int dnssec_test_positive_wildcard_nsec(
2398 DnsAnswer *answer,
2399 const char *name,
2400 const char *source,
2401 const char *zone,
2402 bool *_authenticated) {
2403
2404 bool authenticated = true;
2405 int r;
2406
2407 /* Run a positive NSEC wildcard proof. Specifically:
2408 *
2409 * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and
2410 * a prefix of the synthesizing source "source" in the zone "zone".
2411 *
2412 * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4
2413 *
2414 * 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
2415 * have to prove that none of the following exist:
2416 *
2417 * 1) a.b.c.d.e.f
2418 * 2) *.b.c.d.e.f
2419 * 3) b.c.d.e.f
2420 * 4) *.c.d.e.f
2421 * 5) c.d.e.f
2422 */
2423
2424 for (;;) {
2425 _cleanup_free_ char *wc = NULL;
2426 bool a = false;
2427
2428 /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing,
2429 * i.e between the owner name and the next name of an NSEC RR. */
2430 r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, name, zone, &a);
2431 if (r <= 0)
2432 return r;
2433
2434 authenticated = authenticated && a;
2435
2436 /* Strip one label off */
2437 r = dns_name_parent(&name);
2438 if (r <= 0)
2439 return r;
2440
2441 /* Did we reach the source of synthesis? */
2442 r = dns_name_equal(name, source);
2443 if (r < 0)
2444 return r;
2445 if (r > 0) {
2446 /* Successful exit */
2447 *_authenticated = authenticated;
2448 return 1;
2449 }
2450
2451 /* Safety check, that the source of synthesis is still our suffix */
2452 r = dns_name_endswith(name, source);
2453 if (r < 0)
2454 return r;
2455 if (r == 0)
2456 return -EBADMSG;
2457
2458 /* Replace the label we stripped off with an asterisk */
2459 wc = strjoin("*.", name);
2460 if (!wc)
2461 return -ENOMEM;
2462
2463 /* And check if the proof holds for the asterisk name, too */
2464 r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, wc, zone, &a);
2465 if (r <= 0)
2466 return r;
2467
2468 authenticated = authenticated && a;
2469 /* In the next iteration we'll check the non-asterisk-prefixed version */
2470 }
2471 }
2472
2473 int dnssec_test_positive_wildcard(
2474 DnsAnswer *answer,
2475 const char *name,
2476 const char *source,
2477 const char *zone,
2478 bool *authenticated) {
2479
2480 int r;
2481
2482 assert(name);
2483 assert(source);
2484 assert(zone);
2485 assert(authenticated);
2486
2487 r = dns_answer_contains_zone_nsec3(answer, zone);
2488 if (r < 0)
2489 return r;
2490 if (r > 0)
2491 return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated);
2492 else
2493 return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated);
2494 }
2495
2496 #else
2497
2498 int dnssec_verify_rrset(
2499 DnsAnswer *a,
2500 const DnsResourceKey *key,
2501 DnsResourceRecord *rrsig,
2502 DnsResourceRecord *dnskey,
2503 usec_t realtime,
2504 DnssecResult *result) {
2505
2506 return -EOPNOTSUPP;
2507 }
2508
2509 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
2510
2511 return -EOPNOTSUPP;
2512 }
2513
2514 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
2515
2516 return -EOPNOTSUPP;
2517 }
2518
2519 int dnssec_verify_rrset_search(
2520 DnsAnswer *a,
2521 const DnsResourceKey *key,
2522 DnsAnswer *validated_dnskeys,
2523 usec_t realtime,
2524 DnssecResult *result,
2525 DnsResourceRecord **ret_rrsig) {
2526
2527 return -EOPNOTSUPP;
2528 }
2529
2530 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
2531
2532 return -EOPNOTSUPP;
2533 }
2534
2535 int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
2536
2537 return -EOPNOTSUPP;
2538 }
2539
2540 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
2541
2542 return -EOPNOTSUPP;
2543 }
2544
2545 int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
2546
2547 return -EOPNOTSUPP;
2548 }
2549
2550 int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
2551
2552 return -EOPNOTSUPP;
2553 }
2554
2555 int dnssec_test_positive_wildcard(
2556 DnsAnswer *answer,
2557 const char *name,
2558 const char *source,
2559 const char *zone,
2560 bool *authenticated) {
2561
2562 return -EOPNOTSUPP;
2563 }
2564
2565 #endif
2566
2567 static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
2568 [DNSSEC_VALIDATED] = "validated",
2569 [DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard",
2570 [DNSSEC_INVALID] = "invalid",
2571 [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
2572 [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
2573 [DNSSEC_NO_SIGNATURE] = "no-signature",
2574 [DNSSEC_MISSING_KEY] = "missing-key",
2575 [DNSSEC_UNSIGNED] = "unsigned",
2576 [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
2577 [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch",
2578 [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server",
2579 [DNSSEC_UPSTREAM_FAILURE] = "upstream-failure",
2580 [DNSSEC_TOO_MANY_VALIDATIONS] = "too-many-validations",
2581 };
2582 DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
2583
2584 static const char* const dnssec_verdict_table[_DNSSEC_VERDICT_MAX] = {
2585 [DNSSEC_SECURE] = "secure",
2586 [DNSSEC_INSECURE] = "insecure",
2587 [DNSSEC_BOGUS] = "bogus",
2588 [DNSSEC_INDETERMINATE] = "indeterminate",
2589 };
2590 DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict);