]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-dnssec.c
Add an extra debug log to dissect_image()
[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 int r;
894
895 r = initialize_libgcrypt(false);
896 if (r < 0)
897 return r;
898 #endif
899
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,
905 sig_data, sig_size,
906 rrsig,
907 dnskey);
908 #endif
909 case DNSSEC_ALGORITHM_ED448:
910 return -EOPNOTSUPP;
911 default:
912 /* OK, the RRs are now in canonical order. Let's calculate the digest */
913 md_algorithm = algorithm_to_implementation_id(rrsig->rrsig.algorithm);
914 #if PREFER_OPENSSL
915 if (!md_algorithm)
916 return -EOPNOTSUPP;
917
918 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new();
919 if (!ctx)
920 return -ENOMEM;
921
922 if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0)
923 return -EIO;
924
925 if (EVP_DigestUpdate(ctx, sig_data, sig_size) <= 0)
926 return -EIO;
927
928 if (EVP_DigestFinal_ex(ctx, hash, &hash_size) <= 0)
929 return -EIO;
930
931 assert(hash_size > 0);
932
933 #else
934 if (md_algorithm < 0)
935 return md_algorithm;
936
937 gcry_error_t err = gcry_md_open(&md, md_algorithm, 0);
938 if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
939 return -EIO;
940
941 hash_size = gcry_md_get_algo_dlen(md_algorithm);
942 assert(hash_size > 0);
943
944 gcry_md_write(md, sig_data, sig_size);
945
946 hash = gcry_md_read(md, 0);
947 if (!hash)
948 return -EIO;
949 #endif
950 }
951
952 switch (rrsig->rrsig.algorithm) {
953
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)),
960 hash, hash_size,
961 rrsig,
962 dnskey);
963
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,
969 hash, hash_size,
970 rrsig,
971 dnskey);
972
973 default:
974 assert_not_reached();
975 }
976 }
977
978 int dnssec_verify_rrset(
979 DnsAnswer *a,
980 const DnsResourceKey *key,
981 DnsResourceRecord *rrsig,
982 DnsResourceRecord *dnskey,
983 usec_t realtime,
984 DnssecResult *result) {
985
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 */
990 size_t n = 0;
991 bool wildcard;
992 int r;
993
994 assert(key);
995 assert(rrsig);
996 assert(dnskey);
997 assert(result);
998 assert(rrsig->key->type == DNS_TYPE_RRSIG);
999 assert(dnskey->key->type == DNS_TYPE_DNSKEY);
1000
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. */
1004
1005 r = dnssec_rrsig_prepare(rrsig);
1006 if (r == -EINVAL) {
1007 *result = DNSSEC_INVALID;
1008 return r;
1009 }
1010 if (r < 0)
1011 return r;
1012
1013 r = dnssec_rrsig_expired(rrsig, realtime);
1014 if (r < 0)
1015 return r;
1016 if (r > 0) {
1017 *result = DNSSEC_SIGNATURE_EXPIRED;
1018 return 0;
1019 }
1020
1021 name = dns_resource_key_name(key);
1022
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);
1026 if (r < 0)
1027 return r;
1028 if (r == 0) {
1029 *result = DNSSEC_INVALID;
1030 return 0;
1031 }
1032 }
1033
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);
1037 if (r < 0)
1038 return r;
1039 if (r > 0) {
1040 *result = DNSSEC_INVALID;
1041 return 0;
1042 }
1043 }
1044
1045 /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
1046 r = dns_name_suffix(name, rrsig->rrsig.labels, &source);
1047 if (r < 0)
1048 return r;
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;
1052 return 0;
1053 }
1054 if (r == 1) {
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, "*");
1058 if (r < 0)
1059 return r;
1060 if (r > 0)
1061 source = name;
1062
1063 wildcard = r == 0;
1064 } else
1065 wildcard = r > 0;
1066
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));
1069
1070 DNS_ANSWER_FOREACH(rr, a) {
1071 r = dns_resource_key_equal(key, rr->key);
1072 if (r < 0)
1073 return r;
1074 if (r == 0)
1075 continue;
1076
1077 /* We need the wire format for ordering, and digest calculation */
1078 r = dns_resource_record_to_wire_format(rr, true);
1079 if (r < 0)
1080 return r;
1081
1082 list[n++] = rr;
1083
1084 if (n > VERIFY_RRS_MAX)
1085 return -E2BIG;
1086 }
1087
1088 if (n <= 0)
1089 return -ENODATA;
1090
1091 /* Bring the RRs into canonical order */
1092 typesafe_qsort(list, n, rr_compare);
1093
1094 r = dnssec_rrset_serialize_sig(rrsig, source, list, n, wildcard,
1095 &sig_data, &sig_size);
1096 if (r < 0)
1097 return r;
1098
1099 r = dnssec_rrset_verify_sig(rrsig, dnskey, sig_data, sig_size);
1100 if (r == -EOPNOTSUPP) {
1101 *result = DNSSEC_UNSUPPORTED_ALGORITHM;
1102 return 0;
1103 }
1104 if (r < 0)
1105 return r;
1106
1107 /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */
1108 if (r > 0)
1109 dnssec_fix_rrset_ttl(list, n, rrsig);
1110
1111 if (r == 0)
1112 *result = DNSSEC_INVALID;
1113 else if (wildcard)
1114 *result = DNSSEC_VALIDATED_WILDCARD;
1115 else
1116 *result = DNSSEC_VALIDATED;
1117
1118 return 0;
1119 }
1120
1121 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
1122
1123 assert(rrsig);
1124 assert(dnskey);
1125
1126 /* Checks if the specified DNSKEY RR matches the key used for
1127 * the signature in the specified RRSIG RR */
1128
1129 if (rrsig->key->type != DNS_TYPE_RRSIG)
1130 return -EINVAL;
1131
1132 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1133 return 0;
1134 if (dnskey->key->class != rrsig->key->class)
1135 return 0;
1136 if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
1137 return 0;
1138 if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
1139 return 0;
1140 if (dnskey->dnskey.protocol != 3)
1141 return 0;
1142 if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
1143 return 0;
1144
1145 if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag)
1146 return 0;
1147
1148 return dns_name_equal(dns_resource_key_name(dnskey->key), rrsig->rrsig.signer);
1149 }
1150
1151 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
1152 assert(key);
1153 assert(rrsig);
1154
1155 /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
1156
1157 if (rrsig->key->type != DNS_TYPE_RRSIG)
1158 return 0;
1159 if (rrsig->key->class != key->class)
1160 return 0;
1161 if (rrsig->rrsig.type_covered != key->type)
1162 return 0;
1163
1164 return dns_name_equal(dns_resource_key_name(rrsig->key), dns_resource_key_name(key));
1165 }
1166
1167 int dnssec_verify_rrset_search(
1168 DnsAnswer *a,
1169 const DnsResourceKey *key,
1170 DnsAnswer *validated_dnskeys,
1171 usec_t realtime,
1172 DnssecResult *result,
1173 DnsResourceRecord **ret_rrsig) {
1174
1175 bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
1176 unsigned nvalidations = 0;
1177 DnsResourceRecord *rrsig;
1178 int r;
1179
1180 assert(key);
1181 assert(result);
1182
1183 /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
1184
1185 if (dns_answer_isempty(a))
1186 return -ENODATA;
1187
1188 /* Iterate through each RRSIG RR. */
1189 DNS_ANSWER_FOREACH(rrsig, a) {
1190 DnsResourceRecord *dnskey;
1191 DnsAnswerFlags flags;
1192
1193 /* Is this an RRSIG RR that applies to RRs matching our key? */
1194 r = dnssec_key_match_rrsig(key, rrsig);
1195 if (r < 0)
1196 return r;
1197 if (r == 0)
1198 continue;
1199
1200 found_rrsig = true;
1201
1202 /* Look for a matching key */
1203 DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
1204 DnssecResult one_result;
1205
1206 if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
1207 continue;
1208
1209 /* Is this a DNSKEY RR that matches they key of our RRSIG? */
1210 r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false);
1211 if (r < 0)
1212 return r;
1213 if (r == 0)
1214 continue;
1215
1216 /* Take the time here, if it isn't set yet, so
1217 * that we do all validations with the same
1218 * time. */
1219 if (realtime == USEC_INFINITY)
1220 realtime = now(CLOCK_REALTIME);
1221
1222 /* Have we seen an unreasonable number of invalid signatures? */
1223 if (nvalidations > DNSSEC_INVALID_MAX) {
1224 if (ret_rrsig)
1225 *ret_rrsig = NULL;
1226 *result = DNSSEC_TOO_MANY_VALIDATIONS;
1227 return (int) nvalidations;
1228 }
1229
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
1233 * combination. */
1234
1235 r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
1236 if (r < 0)
1237 return r;
1238
1239 nvalidations++;
1240
1241 switch (one_result) {
1242
1243 case DNSSEC_VALIDATED:
1244 case DNSSEC_VALIDATED_WILDCARD:
1245 /* Yay, the RR has been validated,
1246 * return immediately, but fix up the expiry */
1247 if (ret_rrsig)
1248 *ret_rrsig = rrsig;
1249
1250 *result = one_result;
1251 return (int) nvalidations;
1252
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;
1259 continue;
1260
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;
1269 continue;
1270
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;
1276 continue;
1277
1278 default:
1279 assert_not_reached();
1280 }
1281 }
1282 }
1283
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;
1292 else
1293 *result = DNSSEC_NO_SIGNATURE;
1294
1295 if (ret_rrsig)
1296 *ret_rrsig = NULL;
1297
1298 return (int) nvalidations;
1299 }
1300
1301 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
1302 DnsResourceRecord *rr;
1303 int r;
1304
1305 /* Checks whether there's at least one RRSIG in 'a' that protects RRs of the specified key */
1306
1307 DNS_ANSWER_FOREACH(rr, a) {
1308 r = dnssec_key_match_rrsig(key, rr);
1309 if (r < 0)
1310 return r;
1311 if (r > 0)
1312 return 1;
1313 }
1314
1315 return 0;
1316 }
1317
1318 static hash_md_t digest_to_hash_md(uint8_t algorithm) {
1319
1320 /* Translates a DNSSEC digest algorithm into an openssl/gcrypt digest identifier */
1321
1322 switch (algorithm) {
1323
1324 case DNSSEC_DIGEST_SHA1:
1325 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1);
1326
1327 case DNSSEC_DIGEST_SHA256:
1328 return OPENSSL_OR_GCRYPT(EVP_sha256(), GCRY_MD_SHA256);
1329
1330 case DNSSEC_DIGEST_SHA384:
1331 return OPENSSL_OR_GCRYPT(EVP_sha384(), GCRY_MD_SHA384);
1332
1333 default:
1334 return OPENSSL_OR_GCRYPT(NULL, -EOPNOTSUPP);
1335 }
1336 }
1337
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;
1341 int r;
1342
1343 assert(dnskey);
1344 assert(ds);
1345
1346 /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
1347
1348 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1349 return -EINVAL;
1350 if (ds->key->type != DNS_TYPE_DS)
1351 return -EINVAL;
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;
1358
1359 if (dnskey->dnskey.algorithm != ds->ds.algorithm)
1360 return 0;
1361 if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag)
1362 return 0;
1363
1364 r = dns_name_to_wire_format(dns_resource_key_name(dnskey->key), wire_format, sizeof wire_format, true);
1365 if (r < 0)
1366 return r;
1367 encoded_length = r;
1368
1369 hash_md_t md_algorithm = digest_to_hash_md(ds->ds.digest_type);
1370
1371 #if PREFER_OPENSSL
1372 if (!md_algorithm)
1373 return -EOPNOTSUPP;
1374
1375 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = NULL;
1376 uint8_t result[EVP_MAX_MD_SIZE];
1377
1378 unsigned hash_size = EVP_MD_size(md_algorithm);
1379 assert(hash_size > 0);
1380
1381 if (ds->ds.digest_size != hash_size)
1382 return 0;
1383
1384 ctx = EVP_MD_CTX_new();
1385 if (!ctx)
1386 return -ENOMEM;
1387
1388 if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0)
1389 return -EIO;
1390
1391 if (EVP_DigestUpdate(ctx, wire_format, encoded_length) <= 0)
1392 return -EIO;
1393
1394 if (mask_revoke)
1395 md_add_uint16(ctx, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
1396 else
1397 md_add_uint16(ctx, dnskey->dnskey.flags);
1398
1399 r = md_add_uint8(ctx, dnskey->dnskey.protocol);
1400 if (r <= 0)
1401 return r;
1402 r = md_add_uint8(ctx, dnskey->dnskey.algorithm);
1403 if (r <= 0)
1404 return r;
1405 if (EVP_DigestUpdate(ctx, dnskey->dnskey.key, dnskey->dnskey.key_size) <= 0)
1406 return -EIO;
1407
1408 if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
1409 return -EIO;
1410
1411 #else
1412 if (md_algorithm < 0)
1413 return -EOPNOTSUPP;
1414
1415 r = initialize_libgcrypt(false);
1416 if (r < 0)
1417 return r;
1418
1419 _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
1420
1421 size_t hash_size = gcry_md_get_algo_dlen(md_algorithm);
1422 assert(hash_size > 0);
1423
1424 if (ds->ds.digest_size != hash_size)
1425 return 0;
1426
1427 gcry_error_t err = gcry_md_open(&md, md_algorithm, 0);
1428 if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
1429 return -EIO;
1430
1431 gcry_md_write(md, wire_format, encoded_length);
1432 if (mask_revoke)
1433 md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
1434 else
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);
1439
1440 void *result = gcry_md_read(md, 0);
1441 if (!result)
1442 return -EIO;
1443 #endif
1444
1445 return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0;
1446 }
1447
1448 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
1449 DnsResourceRecord *ds;
1450 DnsAnswerFlags flags;
1451 int r;
1452
1453 assert(dnskey);
1454
1455 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1456 return 0;
1457
1458 DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
1459
1460 if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
1461 continue;
1462
1463 if (ds->key->type != DNS_TYPE_DS)
1464 continue;
1465 if (ds->key->class != dnskey->key->class)
1466 continue;
1467
1468 r = dns_name_equal(dns_resource_key_name(dnskey->key), dns_resource_key_name(ds->key));
1469 if (r < 0)
1470 return r;
1471 if (r == 0)
1472 continue;
1473
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 */
1477 if (r < 0)
1478 return r;
1479 if (r > 0)
1480 return 1;
1481 }
1482
1483 return 0;
1484 }
1485
1486 static hash_md_t nsec3_hash_to_hash_md(uint8_t algorithm) {
1487
1488 /* Translates a DNSSEC NSEC3 hash algorithm into an openssl/gcrypt digest identifier */
1489
1490 switch (algorithm) {
1491
1492 case NSEC3_ALGORITHM_SHA1:
1493 return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1);
1494
1495 default:
1496 return OPENSSL_OR_GCRYPT(NULL, -EOPNOTSUPP);
1497 }
1498 }
1499
1500 int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
1501 uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
1502 int r;
1503
1504 assert(nsec3);
1505 assert(name);
1506 assert(ret);
1507
1508 if (nsec3->key->type != DNS_TYPE_NSEC3)
1509 return -EINVAL;
1510
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));
1515
1516 hash_md_t algorithm = nsec3_hash_to_hash_md(nsec3->nsec3.algorithm);
1517 #if PREFER_OPENSSL
1518 if (!algorithm)
1519 return -EOPNOTSUPP;
1520
1521 size_t hash_size = EVP_MD_size(algorithm);
1522 assert(hash_size > 0);
1523
1524 if (nsec3->nsec3.next_hashed_name_size != hash_size)
1525 return -EINVAL;
1526
1527 _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new();
1528 if (!ctx)
1529 return -ENOMEM;
1530
1531 if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0)
1532 return -EIO;
1533
1534 r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
1535 if (r < 0)
1536 return r;
1537
1538 if (EVP_DigestUpdate(ctx, wire_format, r) <= 0)
1539 return -EIO;
1540 if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0)
1541 return -EIO;
1542
1543 uint8_t result[EVP_MAX_MD_SIZE];
1544 if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
1545 return -EIO;
1546
1547 for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) {
1548 if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0)
1549 return -EIO;
1550 if (EVP_DigestUpdate(ctx, result, hash_size) <= 0)
1551 return -EIO;
1552 if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0)
1553 return -EIO;
1554
1555 if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
1556 return -EIO;
1557 }
1558 #else
1559 if (algorithm < 0)
1560 return algorithm;
1561
1562 r = initialize_libgcrypt(false);
1563 if (r < 0)
1564 return r;
1565
1566 size_t encoded_length;
1567 unsigned hash_size = gcry_md_get_algo_dlen(algorithm);
1568 assert(hash_size > 0);
1569
1570 if (nsec3->nsec3.next_hashed_name_size != hash_size)
1571 return -EINVAL;
1572
1573 r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
1574 if (r < 0)
1575 return r;
1576 encoded_length = r;
1577
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)
1581 return -EIO;
1582
1583 gcry_md_write(md, wire_format, encoded_length);
1584 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
1585
1586 void *result = gcry_md_read(md, 0);
1587 if (!result)
1588 return -EIO;
1589
1590 for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) {
1591 uint8_t tmp[hash_size];
1592 memcpy(tmp, result, hash_size);
1593
1594 gcry_md_reset(md);
1595 gcry_md_write(md, tmp, hash_size);
1596 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
1597
1598 result = gcry_md_read(md, 0);
1599 if (!result)
1600 return -EIO;
1601 }
1602 #endif
1603
1604 memcpy(ret, result, hash_size);
1605 return (int) hash_size;
1606 }
1607
1608 static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
1609 const char *a, *b;
1610 int r;
1611
1612 assert(rr);
1613
1614 if (rr->key->type != DNS_TYPE_NSEC3)
1615 return 0;
1616
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))
1619 return 0;
1620
1621 /* Ignore NSEC3 RRs whose algorithm we don't know */
1622 #if PREFER_OPENSSL
1623 if (!nsec3_hash_to_hash_md(rr->nsec3.algorithm))
1624 return 0;
1625 #else
1626 if (nsec3_hash_to_hash_md(rr->nsec3.algorithm) < 0)
1627 return 0;
1628 #endif
1629
1630 /* Ignore NSEC3 RRs with an excessive number of required iterations */
1631 if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
1632 return 0;
1633
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))
1637 return 0;
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))
1640 return 0;
1641
1642 if (!nsec3)
1643 return 1;
1644
1645 /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
1646
1647 if (nsec3 == rr) /* Shortcut */
1648 return 1;
1649
1650 if (rr->key->class != nsec3->key->class)
1651 return 0;
1652 if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
1653 return 0;
1654 if (rr->nsec3.iterations != nsec3->nsec3.iterations)
1655 return 0;
1656 if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
1657 return 0;
1658 if (memcmp_safe(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
1659 return 0;
1660
1661 a = dns_resource_key_name(rr->key);
1662 r = dns_name_parent(&a); /* strip off hash */
1663 if (r <= 0)
1664 return r;
1665
1666 b = dns_resource_key_name(nsec3->key);
1667 r = dns_name_parent(&b); /* strip off hash */
1668 if (r <= 0)
1669 return r;
1670
1671 /* Make sure both have the same parent */
1672 return dns_name_equal(a, b);
1673 }
1674
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;
1677 char *j;
1678
1679 assert(hashed);
1680 assert(hashed_size > 0);
1681 assert(zone);
1682 assert(ret);
1683
1684 l = base32hexmem(hashed, hashed_size, false);
1685 if (!l)
1686 return -ENOMEM;
1687
1688 j = strjoin(l, ".", zone);
1689 if (!j)
1690 return -ENOMEM;
1691
1692 *ret = j;
1693 return (int) hashed_size;
1694 }
1695
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];
1698 int hashed_size;
1699
1700 assert(nsec3);
1701 assert(domain);
1702 assert(zone);
1703 assert(ret);
1704
1705 hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed);
1706 if (hashed_size < 0)
1707 return hashed_size;
1708
1709 return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret);
1710 }
1711
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.
1717 *
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;
1727 int hashed_size, r;
1728 bool a, no_closer = false, no_wildcard = false, optout = false;
1729
1730 assert(key);
1731 assert(result);
1732
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
1737 * parameters. */
1738 zone = dns_resource_key_name(key);
1739 for (;;) {
1740 DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) {
1741 r = nsec3_is_good(zone_rr, NULL);
1742 if (r < 0)
1743 return r;
1744 if (r == 0)
1745 continue;
1746
1747 r = dns_name_equal_skip(dns_resource_key_name(zone_rr->key), 1, zone);
1748 if (r < 0)
1749 return r;
1750 if (r > 0)
1751 goto found_zone;
1752 }
1753
1754 /* Strip one label from the front */
1755 r = dns_name_parent(&zone);
1756 if (r < 0)
1757 return r;
1758 if (r == 0)
1759 break;
1760 }
1761
1762 *result = DNSSEC_NSEC_NO_RR;
1763 return 0;
1764
1765 found_zone:
1766 /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
1767 p = dns_resource_key_name(key);
1768 for (;;) {
1769 _cleanup_free_ char *hashed_domain = NULL;
1770
1771 hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain);
1772 if (hashed_size == -EOPNOTSUPP) {
1773 *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
1774 return 0;
1775 }
1776 if (hashed_size < 0)
1777 return hashed_size;
1778
1779 DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) {
1780
1781 r = nsec3_is_good(enclosure_rr, zone_rr);
1782 if (r < 0)
1783 return r;
1784 if (r == 0)
1785 continue;
1786
1787 if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
1788 continue;
1789
1790 r = dns_name_equal(dns_resource_key_name(enclosure_rr->key), hashed_domain);
1791 if (r < 0)
1792 return r;
1793 if (r > 0) {
1794 a = flags & DNS_ANSWER_AUTHENTICATED;
1795 goto found_closest_encloser;
1796 }
1797 }
1798
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 */
1802
1803 pp = p;
1804
1805 /* Strip one label from the front */
1806 r = dns_name_parent(&p);
1807 if (r < 0)
1808 return r;
1809 if (r == 0)
1810 break;
1811 }
1812
1813 *result = DNSSEC_NSEC_NO_RR;
1814 return 0;
1815
1816 found_closest_encloser:
1817 /* We found a closest encloser in 'p'; next closer is 'pp' */
1818
1819 if (!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. */
1823
1824 if (key->type == DNS_TYPE_DS) {
1825 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1826 return -EBADMSG;
1827 } else {
1828 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
1829 !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1830 return -EBADMSG;
1831 }
1832
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;
1838 else
1839 *result = DNSSEC_NSEC_NODATA;
1840
1841 if (authenticated)
1842 *authenticated = a;
1843 if (ttl)
1844 *ttl = enclosure_rr->ttl;
1845
1846 return 0;
1847 }
1848
1849 /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
1850 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME))
1851 return -EBADMSG;
1852
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"
1856 * DNS server). */
1857 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
1858 !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1859 return -EBADMSG;
1860
1861 /* Prove that there is no next closer and whether or not there is a wildcard domain. */
1862
1863 wildcard = strjoina("*.", p);
1864 r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain);
1865 if (r < 0)
1866 return r;
1867 if (r != hashed_size)
1868 return -EBADMSG;
1869
1870 r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain);
1871 if (r < 0)
1872 return r;
1873 if (r != hashed_size)
1874 return -EBADMSG;
1875
1876 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
1877 _cleanup_free_ char *next_hashed_domain = NULL;
1878
1879 r = nsec3_is_good(rr, zone_rr);
1880 if (r < 0)
1881 return r;
1882 if (r == 0)
1883 continue;
1884
1885 r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain);
1886 if (r < 0)
1887 return r;
1888
1889 r = dns_name_between(dns_resource_key_name(rr->key), next_closer_domain, next_hashed_domain);
1890 if (r < 0)
1891 return r;
1892 if (r > 0) {
1893 if (rr->nsec3.flags & 1)
1894 optout = true;
1895
1896 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1897
1898 no_closer = true;
1899 }
1900
1901 r = dns_name_equal(dns_resource_key_name(rr->key), wildcard_domain);
1902 if (r < 0)
1903 return r;
1904 if (r > 0) {
1905 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1906
1907 wildcard_rr = rr;
1908 }
1909
1910 r = dns_name_between(dns_resource_key_name(rr->key), wildcard_domain, next_hashed_domain);
1911 if (r < 0)
1912 return r;
1913 if (r > 0) {
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
1918 * we would wish */
1919 optout = true;
1920
1921 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1922
1923 no_wildcard = true;
1924 }
1925 }
1926
1927 if (wildcard_rr && no_wildcard)
1928 return -EBADMSG;
1929
1930 if (!no_closer) {
1931 *result = DNSSEC_NSEC_NO_RR;
1932 return 0;
1933 }
1934
1935 if (wildcard_rr) {
1936 /* A wildcard exists that matches our query. */
1937 if (optout)
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;
1947 else
1948 *result = DNSSEC_NSEC_NODATA;
1949 } else {
1950 if (optout)
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;
1960 else {
1961 *result = DNSSEC_NSEC_NO_RR;
1962
1963 return 0;
1964 }
1965 }
1966
1967 if (authenticated)
1968 *authenticated = a;
1969
1970 if (ttl)
1971 *ttl = enclosure_rr->ttl;
1972
1973 return 0;
1974 }
1975
1976 static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) {
1977 char label[DNS_LABEL_MAX+1];
1978 const char *n;
1979 int r;
1980
1981 assert(rr);
1982 assert(rr->key->type == DNS_TYPE_NSEC);
1983
1984 /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */
1985
1986 if (rr->n_skip_labels_source != 1)
1987 return 0;
1988
1989 n = dns_resource_key_name(rr->key);
1990 r = dns_label_unescape(&n, label, sizeof label, 0);
1991 if (r <= 0)
1992 return r;
1993 if (r != 1 || label[0] != '*')
1994 return 0;
1995
1996 return dns_name_endswith(name, n);
1997 }
1998
1999 static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) {
2000 const char *nn, *common_suffix;
2001 int r;
2002
2003 assert(rr);
2004 assert(rr->key->type == DNS_TYPE_NSEC);
2005
2006 /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT)
2007 *
2008 * A couple of examples:
2009 *
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
2013 */
2014
2015 /* First, determine parent of next domain. */
2016 nn = rr->nsec.next_domain_name;
2017 r = dns_name_parent(&nn);
2018 if (r <= 0)
2019 return r;
2020
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);
2024 if (r <= 0)
2025 return r;
2026
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);
2029 if (r < 0)
2030 return r;
2031
2032 return dns_name_endswith(name, common_suffix);
2033 }
2034
2035 static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) {
2036 int r;
2037
2038 assert(rr);
2039 assert(rr->key->type == DNS_TYPE_NSEC);
2040
2041 /* Checks whether this NSEC originates to the parent zone or the child zone. */
2042
2043 r = dns_name_parent(&name);
2044 if (r <= 0)
2045 return r;
2046
2047 r = dns_name_equal(name, dns_resource_key_name(rr->key));
2048 if (r <= 0)
2049 return r;
2050
2051 /* DNAME, and NS without SOA is an indication for a delegation. */
2052 if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME))
2053 return 1;
2054
2055 if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
2056 return 1;
2057
2058 return 0;
2059 }
2060
2061 static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
2062 const char *signer;
2063 int r;
2064
2065 assert(rr);
2066 assert(rr->key->type == DNS_TYPE_NSEC);
2067
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. */
2070
2071 r = dns_resource_record_signer(rr, &signer);
2072 if (r < 0)
2073 return r;
2074
2075 r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
2076 if (r <= 0)
2077 return r;
2078
2079 return dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
2080 }
2081
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;
2085
2086 assert(rr);
2087 assert(rr->key->type == DNS_TYPE_NSEC);
2088
2089 /* Generates "Wildcard at the Closest Encloser" for the given name and NSEC RR. */
2090
2091 r = dns_resource_record_signer(rr, &signer);
2092 if (r < 0)
2093 return r;
2094
2095 r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
2096 if (r <= 0)
2097 return r;
2098
2099 r = dns_name_common_suffix(name, dns_resource_key_name(rr->key), &common_suffix1);
2100 if (r < 0)
2101 return r;
2102
2103 r = dns_name_common_suffix(name, rr->nsec.next_domain_name, &common_suffix2);
2104 if (r < 0)
2105 return r;
2106
2107 labels1 = dns_name_count_labels(common_suffix1);
2108 if (labels1 < 0)
2109 return labels1;
2110
2111 labels2 = dns_name_count_labels(common_suffix2);
2112 if (labels2 < 0)
2113 return labels2;
2114
2115 if (labels1 > labels2)
2116 r = dns_name_concat("*", common_suffix1, 0, wc);
2117 else
2118 r = dns_name_concat("*", common_suffix2, 0, wc);
2119
2120 if (r < 0)
2121 return r;
2122
2123 return 0;
2124 }
2125
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;
2130 const char *name;
2131 int r;
2132
2133 assert(key);
2134 assert(result);
2135
2136 /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
2137
2138 name = dns_resource_key_name(key);
2139
2140 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2141
2142 if (rr->key->class != key->class)
2143 continue;
2144
2145 have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3);
2146
2147 if (rr->key->type != DNS_TYPE_NSEC)
2148 continue;
2149
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. */
2153 continue;
2154 if (r < 0)
2155 return r;
2156 if (r > 0)
2157 continue;
2158
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);
2161 if (r < 0)
2162 return r;
2163 if (r == 0) {
2164 /* If it's not a direct match, maybe it's a wild card match? */
2165 r = dnssec_nsec_wildcard_equal(rr, name);
2166 if (r < 0)
2167 return r;
2168 }
2169 if (r > 0) {
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))
2174 continue;
2175 } else {
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))
2180 continue;
2181 }
2182
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;
2187 else
2188 *result = DNSSEC_NSEC_NODATA;
2189
2190 if (authenticated)
2191 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2192 if (ttl)
2193 *ttl = rr->ttl;
2194
2195 return 0;
2196 }
2197
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);
2201 if (r < 0)
2202 return r;
2203 if (r > 0) {
2204 *result = DNSSEC_NSEC_NODATA;
2205
2206 if (authenticated)
2207 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2208 if (ttl)
2209 *ttl = rr->ttl;
2210
2211 return 0;
2212 }
2213
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);
2216 if (r < 0)
2217 return r;
2218 if (r > 0)
2219 continue;
2220
2221 /* Check if this NSEC RR proves the absence of an explicit RR under this name */
2222 r = dnssec_nsec_covers(rr, name);
2223 if (r < 0)
2224 return r;
2225 if (r > 0 && (!covering_rr || !covering_rr_authenticated)) {
2226 covering_rr = rr;
2227 covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2228 }
2229 }
2230
2231 if (covering_rr) {
2232 _cleanup_free_ char *wc = NULL;
2233 r = dnssec_nsec_generate_wildcard(covering_rr, name, &wc);
2234 if (r < 0)
2235 return r;
2236
2237 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2238
2239 if (rr->key->class != key->class)
2240 continue;
2241
2242 if (rr->key->type != DNS_TYPE_NSEC)
2243 continue;
2244
2245 /* Check if this NSEC RR proves the nonexistence of the wildcard */
2246 r = dnssec_nsec_covers(rr, wc);
2247 if (r < 0)
2248 return r;
2249 if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) {
2250 wildcard_rr = rr;
2251 wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2252 }
2253 }
2254 }
2255
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;
2260
2261 if (authenticated)
2262 *authenticated = covering_rr_authenticated && wildcard_rr_authenticated;
2263 if (ttl)
2264 *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl);
2265
2266 return 0;
2267 }
2268
2269 /* OK, this was not sufficient. Let's see if NSEC3 can help. */
2270 if (have_nsec3)
2271 return dnssec_test_nsec3(answer, key, result, authenticated, ttl);
2272
2273 /* No appropriate NSEC RR found, report this. */
2274 *result = DNSSEC_NSEC_NO_RR;
2275 return 0;
2276 }
2277
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;
2281 int r;
2282
2283 assert(name);
2284 assert(zone);
2285
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'. */
2288
2289 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2290 bool found = false;
2291
2292 if (rr->key->type != type && type != DNS_TYPE_ANY)
2293 continue;
2294
2295 switch (rr->key->type) {
2296
2297 case DNS_TYPE_NSEC:
2298
2299 /* We only care for NSEC RRs from the indicated zone */
2300 r = dns_resource_record_is_signer(rr, zone);
2301 if (r < 0)
2302 return r;
2303 if (r == 0)
2304 continue;
2305
2306 r = dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
2307 if (r < 0)
2308 return r;
2309
2310 found = r > 0;
2311 break;
2312
2313 case DNS_TYPE_NSEC3: {
2314 _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL;
2315
2316 /* We only care for NSEC3 RRs from the indicated zone */
2317 r = dns_resource_record_is_signer(rr, zone);
2318 if (r < 0)
2319 return r;
2320 if (r == 0)
2321 continue;
2322
2323 r = nsec3_is_good(rr, NULL);
2324 if (r < 0)
2325 return r;
2326 if (r == 0)
2327 break;
2328
2329 /* Format the domain we are testing with the NSEC3 RR's hash function */
2330 r = nsec3_hashed_domain_make(
2331 rr,
2332 name,
2333 zone,
2334 &hashed_domain);
2335 if (r < 0)
2336 return r;
2337 if ((size_t) r != rr->nsec3.next_hashed_name_size)
2338 break;
2339
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,
2344 zone,
2345 &next_hashed_domain);
2346 if (r < 0)
2347 return r;
2348
2349 r = dns_name_between(dns_resource_key_name(rr->key), hashed_domain, next_hashed_domain);
2350 if (r < 0)
2351 return r;
2352
2353 found = r > 0;
2354 break;
2355 }
2356
2357 default:
2358 continue;
2359 }
2360
2361 if (found) {
2362 if (authenticated)
2363 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2364 return 1;
2365 }
2366 }
2367
2368 return 0;
2369 }
2370
2371 static int dnssec_test_positive_wildcard_nsec3(
2372 DnsAnswer *answer,
2373 const char *name,
2374 const char *source,
2375 const char *zone,
2376 bool *authenticated) {
2377
2378 const char *next_closer = NULL;
2379 int r;
2380
2381 /* Run a positive NSEC3 wildcard proof. Specifically:
2382 *
2383 * A proof that the "next closer" of the generating wildcard does not exist.
2384 *
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.
2388 *
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. */
2391
2392 for (;;) {
2393 next_closer = name;
2394 r = dns_name_parent(&name);
2395 if (r <= 0)
2396 return r;
2397
2398 r = dns_name_equal(name, source);
2399 if (r < 0)
2400 return r;
2401 if (r > 0)
2402 break;
2403 }
2404
2405 return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated);
2406 }
2407
2408 static int dnssec_test_positive_wildcard_nsec(
2409 DnsAnswer *answer,
2410 const char *name,
2411 const char *source,
2412 const char *zone,
2413 bool *_authenticated) {
2414
2415 bool authenticated = true;
2416 int r;
2417
2418 /* Run a positive NSEC wildcard proof. Specifically:
2419 *
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".
2422 *
2423 * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4
2424 *
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:
2427 *
2428 * 1) a.b.c.d.e.f
2429 * 2) *.b.c.d.e.f
2430 * 3) b.c.d.e.f
2431 * 4) *.c.d.e.f
2432 * 5) c.d.e.f
2433 */
2434
2435 for (;;) {
2436 _cleanup_free_ char *wc = NULL;
2437 bool a = false;
2438
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);
2442 if (r <= 0)
2443 return r;
2444
2445 authenticated = authenticated && a;
2446
2447 /* Strip one label off */
2448 r = dns_name_parent(&name);
2449 if (r <= 0)
2450 return r;
2451
2452 /* Did we reach the source of synthesis? */
2453 r = dns_name_equal(name, source);
2454 if (r < 0)
2455 return r;
2456 if (r > 0) {
2457 /* Successful exit */
2458 *_authenticated = authenticated;
2459 return 1;
2460 }
2461
2462 /* Safety check, that the source of synthesis is still our suffix */
2463 r = dns_name_endswith(name, source);
2464 if (r < 0)
2465 return r;
2466 if (r == 0)
2467 return -EBADMSG;
2468
2469 /* Replace the label we stripped off with an asterisk */
2470 wc = strjoin("*.", name);
2471 if (!wc)
2472 return -ENOMEM;
2473
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);
2476 if (r <= 0)
2477 return r;
2478
2479 authenticated = authenticated && a;
2480 /* In the next iteration we'll check the non-asterisk-prefixed version */
2481 }
2482 }
2483
2484 int dnssec_test_positive_wildcard(
2485 DnsAnswer *answer,
2486 const char *name,
2487 const char *source,
2488 const char *zone,
2489 bool *authenticated) {
2490
2491 int r;
2492
2493 assert(name);
2494 assert(source);
2495 assert(zone);
2496 assert(authenticated);
2497
2498 r = dns_answer_contains_zone_nsec3(answer, zone);
2499 if (r < 0)
2500 return r;
2501 if (r > 0)
2502 return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated);
2503 else
2504 return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated);
2505 }
2506
2507 #else
2508
2509 int dnssec_verify_rrset(
2510 DnsAnswer *a,
2511 const DnsResourceKey *key,
2512 DnsResourceRecord *rrsig,
2513 DnsResourceRecord *dnskey,
2514 usec_t realtime,
2515 DnssecResult *result) {
2516
2517 return -EOPNOTSUPP;
2518 }
2519
2520 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
2521
2522 return -EOPNOTSUPP;
2523 }
2524
2525 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
2526
2527 return -EOPNOTSUPP;
2528 }
2529
2530 int dnssec_verify_rrset_search(
2531 DnsAnswer *a,
2532 const DnsResourceKey *key,
2533 DnsAnswer *validated_dnskeys,
2534 usec_t realtime,
2535 DnssecResult *result,
2536 DnsResourceRecord **ret_rrsig) {
2537
2538 return -EOPNOTSUPP;
2539 }
2540
2541 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
2542
2543 return -EOPNOTSUPP;
2544 }
2545
2546 int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
2547
2548 return -EOPNOTSUPP;
2549 }
2550
2551 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
2552
2553 return -EOPNOTSUPP;
2554 }
2555
2556 int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
2557
2558 return -EOPNOTSUPP;
2559 }
2560
2561 int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
2562
2563 return -EOPNOTSUPP;
2564 }
2565
2566 int dnssec_test_positive_wildcard(
2567 DnsAnswer *answer,
2568 const char *name,
2569 const char *source,
2570 const char *zone,
2571 bool *authenticated) {
2572
2573 return -EOPNOTSUPP;
2574 }
2575
2576 #endif
2577
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",
2592 };
2593 DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
2594
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",
2600 };
2601 DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict);