resolved-dns-dnssec.c revision 28b8191e2f391f043d380d47eb79ed9ff66f14bd
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/***
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek This file is part of systemd.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek Copyright 2015 Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek (at your option) any later version.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek***/
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include <gcrypt.h>
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "alloc-util.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "dns-domain.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "hexdecoct.h"
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk#include "resolved-dns-dnssec.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "resolved-dns-packet.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "string-table.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering/* Open question:
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering *
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering * How does the DNSSEC canonical form of a hostname with a label
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer * containing a dot look like, the way DNS-SD does it?
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * TODO:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - wildcard zones compatibility (NSEC/NSEC3 wildcard check is missing)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - multi-label zone compatibility
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - cname/dname compatibility
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - per-interface DNSSEC setting
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - nxdomain on qname
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering * - retry on failed validation?
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - DNSSEC key revocation support? https://tools.ietf.org/html/rfc5011
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * - when doing negative caching, use NSEC/NSEC3 RR instead of SOA for TTL
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#define VERIFY_RRS_MAX 256
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#define MAX_KEY_SIZE (32*1024)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering#define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/* Maximum number of NSEC3 iterations we'll do. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#define NSEC3_ITERATIONS_MAX 2048
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/*
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * The DNSSEC Chain of trust:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * DS RRs are protected like normal RRs
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * Example chain:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk */
7f1ad696a273703789b624fe0b209fb63e953016Lennart Poettering
7f1ad696a273703789b624fe0b209fb63e953016Lennart Poetteringstatic void initialize_libgcrypt(void) {
e150e82097211f09b911c7784a89ef9efed713caMichał Bartoszkiewicz const char *p;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return;
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek p = gcry_check_version("1.4.5");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(p);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_control(GCRYCTL_DISABLE_SECMEM);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekuint16_t dnssec_keytag(DnsResourceRecord *dnskey) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const uint8_t *p;
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack uint32_t sum;
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack size_t i;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack /* The algorithm from RFC 4034, Appendix B. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey->key->type == DNS_TYPE_DNSKEY);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek sum = (uint32_t) dnskey->dnskey.flags +
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm);
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer p = dnskey->dnskey.key;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek for (i = 0; i < dnskey->dnskey.key_size; i++)
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i];
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer sum += (sum >> 16) & UINT32_C(0xFFFF);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek return sum & UINT32_C(0xFFFF);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int rr_compare(const void *a, const void *b) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b;
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek size_t m;
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek int r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Let's order the RRs according to RFC 4034, Section 6.3 */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(x);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(*x);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert((*x)->wire_format);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(y);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(*y);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert((*y)->wire_format);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m = MIN((*x)->wire_format_size, (*y)->wire_format_size);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = memcmp((*x)->wire_format, (*y)->wire_format, m);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r != 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if ((*x)->wire_format_size < (*y)->wire_format_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if ((*x)->wire_format_size > (*y)->wire_format_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int dnssec_rsa_verify_raw(
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek const char *hash_algorithm,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *signature, size_t signature_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *data, size_t data_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *exponent, size_t exponent_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *modulus, size_t modulus_size) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
0371ca0dac1d70b2e5060a3c4e6fbbc2bdbd8671Florian Weimer gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
0371ca0dac1d70b2e5060a3c4e6fbbc2bdbd8671Florian Weimer gcry_mpi_t n = NULL, e = NULL, s = NULL;
0371ca0dac1d70b2e5060a3c4e6fbbc2bdbd8671Florian Weimer gcry_error_t ge;
0371ca0dac1d70b2e5060a3c4e6fbbc2bdbd8671Florian Weimer int r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(hash_algorithm);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek }
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek ge = gcry_sexp_build(&signature_sexp,
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek NULL,
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek "(sig-val (rsa (s %m)))",
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek s);
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek if (ge != 0) {
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek r = -EIO;
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek goto finish;
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_sexp_build(&data_sexp,
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek NULL,
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek "(data (flags pkcs1) (hash %s %b))",
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek hash_algorithm,
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek (int) data_size,
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek data);
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek if (ge != 0) {
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek r = -EIO;
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek goto finish;
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek }
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek ge = gcry_sexp_build(&public_key_sexp,
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek NULL,
348ced909724a1331b85d57aede80a102a00e428Zbigniew Jędrzejewski-Szmek "(public-key (rsa (n %m) (e %m)))",
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek n,
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek e);
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_debug("RSA signature check failed: %s", gpg_strerror(ge));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek } else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = 1;
4608af4333d0f7f5f8e3bc632801b04ef07d246dLennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekfinish:
4608af4333d0f7f5f8e3bc632801b04ef07d246dLennart Poettering if (e)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_mpi_release(e);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (n)
34c10968cbe3b5591b3c0ce225b8694edd9709d0Lennart Poettering gcry_mpi_release(n);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (s)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_mpi_release(s);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (public_key_sexp)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_sexp_release(public_key_sexp);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (signature_sexp)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_sexp_release(signature_sexp);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (data_sexp)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_sexp_release(data_sexp);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int dnssec_rsa_verify(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const char *hash_algorithm,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *hash, size_t hash_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *rrsig,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *dnskey) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) size_t exponent_size, modulus_size;
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) void *exponent, *modulus;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) assert(hash_algorithm);
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) assert(hash);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(hash_size > 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(rrsig);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (*(uint8_t*) dnskey->dnskey.key == 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* exponent is > 255 bytes long */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek exponent = (uint8_t*) dnskey->dnskey.key + 3;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek exponent_size =
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) |
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (exponent_size < 256)
ed375bebf46c1251f4baa170b39ee93761dbdb19Zbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (3 + exponent_size >= dnskey->dnskey.key_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek modulus_size = dnskey->dnskey.key_size - 3 - exponent_size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek } else {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* exponent is <= 255 bytes long */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek exponent = (uint8_t*) dnskey->dnskey.key + 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0];
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (exponent_size <= 0)
f7dc3ab9f43b67abcbd34062b9352ab42debec49Lennart Poettering return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (1 + exponent_size >= dnskey->dnskey.key_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek modulus_size = dnskey->dnskey.key_size - 1 - exponent_size;
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return dnssec_rsa_verify_raw(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek hash_algorithm,
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek rrsig->rrsig.signature, rrsig->rrsig.signature_size,
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek hash, hash_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek exponent, exponent_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek modulus, modulus_size);
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidtstatic int dnssec_ecdsa_verify_raw(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const char *hash_algorithm,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const char *curve,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *signature_r, size_t signature_r_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *signature_s, size_t signature_s_size,
cbd671772c9ce053a7050ddd29de170eb9efac7eZbigniew Jędrzejewski-Szmek const void *data, size_t data_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const void *key, size_t key_size) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_mpi_t q = NULL, r = NULL, s = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_error_t ge;
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt int k;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(hash_algorithm);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek k = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL);
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek if (ge != 0) {
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek k = -EIO;
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek goto finish;
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek }
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL);
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek if (ge != 0) {
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek k = -EIO;
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek goto finish;
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek }
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek ge = gcry_sexp_build(&signature_sexp,
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek NULL,
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek "(sig-val (ecdsa (r %m) (s %m)))",
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek r,
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek s);
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek if (ge != 0) {
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek k = -EIO;
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ge = gcry_sexp_build(&data_sexp,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek NULL,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek "(data (flags rfc6979) (hash %s %b))",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek hash_algorithm,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek (int) data_size,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek data);
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek if (ge != 0) {
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek k = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt }
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek ge = gcry_sexp_build(&public_key_sexp,
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt NULL,
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek "(public-key (ecc (curve %s) (q %m)))",
fc55baee9964a118afbddbf82b8e667a0ad80b99Zbigniew Jędrzejewski-Szmek curve,
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt q);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ge != 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek k = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk }
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk k = 0;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk else if (ge != 0) {
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk log_debug("ECDSA signature check failed: %s", gpg_strerror(ge));
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk k = -EIO;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk } else
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk k = 1;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchukfinish:
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk if (r)
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt gcry_mpi_release(r);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk if (s)
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk gcry_mpi_release(s);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk if (q)
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk gcry_mpi_release(q);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (public_key_sexp)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_sexp_release(public_key_sexp);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (signature_sexp)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_sexp_release(signature_sexp);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (data_sexp)
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk gcry_sexp_release(data_sexp);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return k;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk}
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmekstatic int dnssec_ecdsa_verify(
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek const char *hash_algorithm,
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek int algorithm,
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek const void *hash, size_t hash_size,
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek DnsResourceRecord *rrsig,
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek DnsResourceRecord *dnskey) {
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek const char *curve;
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek size_t key_size;
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek uint8_t *q;
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek assert(hash);
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek assert(hash_size);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(rrsig);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek key_size = 32;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek curve = "NIST P-256";
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek key_size = 48;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek curve = "NIST P-384";
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek } else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EOPNOTSUPP;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnskey->dnskey.key_size != key_size * 2)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (rrsig->rrsig.signature_size != key_size * 2)
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek return -EINVAL;
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek q = alloca(key_size*2 + 1);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek memcpy(q+1, dnskey->dnskey.key, key_size*2);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return dnssec_ecdsa_verify_raw(
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering hash_algorithm,
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering curve,
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering rrsig->rrsig.signature, key_size,
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering hash, hash_size,
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering q, key_size*2+1);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering}
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poetteringstatic void md_add_uint8(gcry_md_hd_t md, uint8_t v) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering gcry_md_write(md, &v, sizeof(v));
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering}
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poetteringstatic void md_add_uint16(gcry_md_hd_t md, uint16_t v) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering v = htobe16(v);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering gcry_md_write(md, &v, sizeof(v));
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering}
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poetteringstatic void md_add_uint32(gcry_md_hd_t md, uint32_t v) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering v = htobe32(v);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering gcry_md_write(md, &v, sizeof(v));
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering}
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poetteringstatic int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering usec_t expiration, inception, skew;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert(rrsig);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert(rrsig->key->type == DNS_TYPE_RRSIG);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (realtime == USEC_INFINITY)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering realtime = now(CLOCK_REALTIME);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering expiration = rrsig->rrsig.expiration * USEC_PER_SEC;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering inception = rrsig->rrsig.inception * USEC_PER_SEC;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (inception > expiration)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return -EKEYREJECTED;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering /* Permit a certain amount of clock skew of 10% of the valid
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering * time range. This takes inspiration from unbound's
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering * resolver. */
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering skew = (expiration - inception) / 10;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (skew > SKEW_MAX)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering skew = SKEW_MAX;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (inception < skew)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek inception = 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek inception -= skew;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (expiration + skew < expiration)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek expiration = USEC_INFINITY;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek expiration += skew;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return realtime < inception || realtime > expiration;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int algorithm_to_gcrypt_md(uint8_t algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Translates a DNSSEC signature algorithm into a gcrypt
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * digest identifier.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * Note that we implement all algorithms listed as "Must
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * implement" and "Recommended to Implement" in RFC6944. We
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * don't implement any algorithms that are listed as
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * "Optional" or "Must Not Implement". Specifically, we do not
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * GOST-ECC. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek switch (algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_RSASHA1:
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_RSASHA256:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_ECDSAP256SHA256:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA256;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_ECDSAP384SHA384:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA384;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_RSASHA512:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA512;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek default:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EOPNOTSUPP;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint dnssec_verify_rrset(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsAnswer *a,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceKey *key,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *rrsig,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *dnskey,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek usec_t realtime,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnssecResult *result) {
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX];
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek size_t hash_size;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk void *hash;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord **list, *rr;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_hd_t md = NULL;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek int r, md_algorithm;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek size_t k, n = 0;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek assert(key);
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek assert(rrsig);
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek assert(dnskey);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(result);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(rrsig->key->type == DNS_TYPE_RRSIG);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey->key->type == DNS_TYPE_DNSKEY);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Verifies the the RRSet matching the specified "key" in "a",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * using the signature "rrsig" and the key "dnskey". It's
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * assumed the RRSIG and DNSKEY match. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (md_algorithm == -EOPNOTSUPP) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_UNSUPPORTED_ALGORITHM;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek }
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek if (md_algorithm < 0)
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek return md_algorithm;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek r = dnssec_rrsig_expired(rrsig, realtime);
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek if (r < 0)
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek return r;
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering if (r > 0) {
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering *result = DNSSEC_SIGNATURE_EXPIRED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Collect all relevant RRs in a single array, so that we can look at the RRset */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek list = newa(DnsResourceRecord *, a->n_rrs);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH(rr, a) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_resource_key_equal(key, rr->key);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r == 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering /* We need the wire format for ordering, and digest calculation */
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering r = dns_resource_record_to_wire_format(rr, true);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (r < 0)
d378991747d67fff1d4dc39e7fb2bc8f49f1b561Mirco Tischler return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek list[n++] = rr;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (n > VERIFY_RRS_MAX)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return -E2BIG;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (n <= 0)
82499507b369fea3033a74c22813bf423301aef4Lennart Poettering return -ENODATA;
82499507b369fea3033a74c22813bf423301aef4Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering /* Bring the RRs into canonical order */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek qsort_safe(list, n, sizeof(DnsResourceRecord*), rr_compare);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* OK, the RRs are now in canonical order. Let's calculate the digest */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek initialize_libgcrypt();
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering hash_size = gcry_md_get_algo_dlen(md_algorithm);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering assert(hash_size > 0);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_open(&md, md_algorithm, 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!md)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek md_add_uint16(md, rrsig->rrsig.type_covered);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint8(md, rrsig->rrsig.algorithm);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint8(md, rrsig->rrsig.labels);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint32(md, rrsig->rrsig.original_ttl);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint32(md, rrsig->rrsig.expiration);
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek md_add_uint32(md, rrsig->rrsig.inception);
c2457105d76e3daf159f554a9bafb9751b23d756Holger Hans Peter Freyther md_add_uint16(md, rrsig->rrsig.key_tag);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true);
c2457105d76e3daf159f554a9bafb9751b23d756Holger Hans Peter Freyther if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek gcry_md_write(md, wire_format_name, r);
c2457105d76e3daf159f554a9bafb9751b23d756Holger Hans Peter Freyther
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek for (k = 0; k < n; k++) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const char *suffix;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek size_t l;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek rr = list[k];
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = dns_name_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rrsig->rrsig.labels, &suffix);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0) /* This is a wildcard! */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_write(md, (uint8_t[]) { 1, '*'}, 2);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_name_to_wire_format(suffix, wire_format_name, sizeof(wire_format_name), true);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_write(md, wire_format_name, r);
9bdbc2e2ec523dbefe1c1c7e164b5544aff0b185Lukas Nykryn
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint16(md, rr->key->type);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek md_add_uint16(md, rr->key->class);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint32(md, rrsig->rrsig.original_ttl);
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden l = rr->wire_format_size - rr->wire_format_rdata_offset;
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden assert(l <= 0xFFFF);
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden md_add_uint16(md, (uint16_t) l);
3a83211689bdf4ab617a4fb79e11980c50918123Shawn Landden gcry_md_write(md, (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset, l);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek hash = gcry_md_read(md, 0);
0a20e3c10761378869af7bbef2733e3ae879d0f1Holger Hans Peter Freyther if (!hash) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering goto finish;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering switch (rrsig->rrsig.algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_RSASHA1:
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_RSASHA256:
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering case DNSSEC_ALGORITHM_RSASHA512:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dnssec_rsa_verify(
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering gcry_md_algo_name(md_algorithm),
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek hash, hash_size,
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering rrsig,
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering dnskey);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek break;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_ECDSAP256SHA256:
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek case DNSSEC_ALGORITHM_ECDSAP384SHA384:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dnssec_ecdsa_verify(
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering gcry_md_algo_name(md_algorithm),
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering rrsig->rrsig.algorithm,
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering hash, hash_size,
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering rrsig,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek dnskey);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering break;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = r ? DNSSEC_VALIDATED : DNSSEC_INVALID;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering r = 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringfinish:
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek gcry_md_close(md);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return r;
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering}
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poetteringint dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey) {
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering assert(rrsig);
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering assert(dnskey);
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* Checks if the specified DNSKEY RR matches the key used for
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering * the signature in the specified RRSIG RR */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering if (rrsig->key->type != DNS_TYPE_RRSIG)
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering return -EINVAL;
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering if (dnskey->key->type != DNS_TYPE_DNSKEY)
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return 0;
0a244b8ecb6dfcb381fe831dc2aa9bacb2c12975Lennart Poettering if (dnskey->key->class != rrsig->key->class)
0a244b8ecb6dfcb381fe831dc2aa9bacb2c12975Lennart Poettering return 0;
0a244b8ecb6dfcb381fe831dc2aa9bacb2c12975Lennart Poettering if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
0a244b8ecb6dfcb381fe831dc2aa9bacb2c12975Lennart Poettering return 0;
0a244b8ecb6dfcb381fe831dc2aa9bacb2c12975Lennart Poettering if ((dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
0a244b8ecb6dfcb381fe831dc2aa9bacb2c12975Lennart Poettering return 0;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (dnskey->dnskey.protocol != 3)
2d43b190901902dbd98ccea77c1d1ddc9e2a9955Dan McGee return 0;
2d43b190901902dbd98ccea77c1d1ddc9e2a9955Dan McGee if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
2d43b190901902dbd98ccea77c1d1ddc9e2a9955Dan McGee return 0;
ef1673d16907726d83bdff2e57b5261997a85020Mirco Tischler
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnssec_keytag(dnskey) != rrsig->rrsig.key_tag)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
6baa7db00812437bbc87e73faa1a11b6cf631958Lennart Poettering
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering return dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), rrsig->rrsig.signer);
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplett}
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poetteringint dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering int r;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering assert(key);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(rrsig);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
e7ff4e7fe9f3abd2297e4ef7b95dcb2804e051c3Greg Kroah-Hartman
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering if (rrsig->key->type != DNS_TYPE_RRSIG)
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering return 0;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering if (rrsig->key->class != key->class)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (rrsig->rrsig.type_covered != key->type)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* Make sure signer is a parent of the RRset */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rrsig->key), rrsig->rrsig.signer);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r <= 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek /* Make sure the owner name has at least as many labels as the "label" fields indicates. */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = dns_name_count_labels(DNS_RESOURCE_KEY_NAME(rrsig->key));
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < rrsig->rrsig.labels)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return 0;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return dns_name_equal(DNS_RESOURCE_KEY_NAME(rrsig->key), DNS_RESOURCE_KEY_NAME(key));
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek}
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmekstatic int dnssec_fix_rrset_ttl(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord *rrsig, usec_t realtime) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsResourceRecord *rr;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek int r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(key);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(rrsig);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH(rr, a) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = dns_resource_key_equal(key, rr->key);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r == 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek continue;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* Pick the TTL as the minimum of the RR's TTL, the
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek * RR's original TTL according to the RRSIG and the
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek }
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return 0;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek}
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmekint dnssec_verify_rrset_search(
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsAnswer *a,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsResourceKey *key,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsAnswer *validated_dnskeys,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek usec_t realtime,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnssecResult *result) {
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsResourceRecord *rrsig;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek int r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering assert(key);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(result);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (!a || a->n_rrs <= 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return -ENODATA;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* Iterate through each RRSIG RR. */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH(rrsig, a) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsResourceRecord *dnskey;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnsAnswerFlags flags;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek /* Is this an RRSIG RR that applies to RRs matching our key? */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = dnssec_key_match_rrsig(key, rrsig);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r == 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek continue;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering found_rrsig = true;
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering /* Look for a matching key */
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek DnssecResult one_result;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering continue;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* Is this a DNSKEY RR that matches they key of our RRSIG? */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = dnssec_rrsig_match_dnskey(rrsig, dnskey);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (r < 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r == 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
a569398925430de1f8479262e8ab39502054f2e9Lennart Poettering /* Take the time here, if it isn't set yet, so
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * that we do all validations with the same
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * time. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (realtime == USEC_INFINITY)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek realtime = now(CLOCK_REALTIME);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering /* Yay, we found a matching RRSIG with a matching
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering * DNSKEY, awesome. Now let's verify all entries of
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * the RRSet against the RRSIG and DNSKEY
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering * combination. */
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (r < 0)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek switch (one_result) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
da4993920cdf5527b8528f0a483b54ab3cbc1971Kay Sievers case DNSSEC_VALIDATED:
40adcda869bda55f44b57fd3a2bd71d006dfb51bLennart Poettering /* Yay, the RR has been validated,
759c945a43577d56e85a927f15e7d9aaa94a4e4aColin Walters * return immediately, but fix up the expiry */
82499507b369fea3033a74c22813bf423301aef4Lennart Poettering r = dnssec_fix_rrset_ttl(a, key, rrsig, realtime);
edc3797f7cd9e37c24e5241cac3263e7c918f732Lennart Poettering if (r < 0)
edc3797f7cd9e37c24e5241cac3263e7c918f732Lennart Poettering return r;
edc3797f7cd9e37c24e5241cac3263e7c918f732Lennart Poettering
edc3797f7cd9e37c24e5241cac3263e7c918f732Lennart Poettering *result = DNSSEC_VALIDATED;
edc3797f7cd9e37c24e5241cac3263e7c918f732Lennart Poettering return 0;
8a0889dfdafa3054c894e54852d8a9e3a7e8390bLennart Poettering
da4993920cdf5527b8528f0a483b54ab3cbc1971Kay Sievers case DNSSEC_INVALID:
da4993920cdf5527b8528f0a483b54ab3cbc1971Kay Sievers /* If the signature is invalid, let's try another
759c945a43577d56e85a927f15e7d9aaa94a4e4aColin Walters key and/or signature. After all they
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering key_tags and stuff are not unique, and
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek might be shared by multiple keys. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek found_invalid = true;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_UNSUPPORTED_ALGORITHM:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* If the key algorithm is
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek unsupported, try another
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek RRSIG/DNSKEY pair, but remember we
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek encountered this, so that we can
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return a proper error when we
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek encounter nothing better. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek found_unsupported_algorithm = true;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_SIGNATURE_EXPIRED:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* If the signature is expired, try
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek another one, but remember it, so
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek that we can return this */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek found_expired_rrsig = true;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek default:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_not_reached("Unexpected DNSSEC validation result");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (found_expired_rrsig)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_SIGNATURE_EXPIRED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (found_unsupported_algorithm)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_UNSUPPORTED_ALGORITHM;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (found_invalid)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_INVALID;
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering else if (found_rrsig)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_MISSING_KEY;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NO_SIGNATURE;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *rr;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek int r;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Checks whether there's at least one RRSIG in 'a' that proctects RRs of the specified key */
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer DNS_ANSWER_FOREACH(rr, a) {
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek r = dnssec_key_match_rrsig(key, rr);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
2f5df74a5ec135ab2baebf26af6f088e5b4b8205Holger Hans Peter Freyther size_t c = 0;
2f5df74a5ec135ab2baebf26af6f088e5b4b8205Holger Hans Peter Freyther int r;
2f5df74a5ec135ab2baebf26af6f088e5b4b8205Holger Hans Peter Freyther
2f5df74a5ec135ab2baebf26af6f088e5b4b8205Holger Hans Peter Freyther /* Converts the specified hostname into DNSSEC canonicalized
2f5df74a5ec135ab2baebf26af6f088e5b4b8205Holger Hans Peter Freyther * form. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (buffer_max < 2)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -ENOBUFS;
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering for (;;) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek size_t i;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_label_unescape(&n, buffer, buffer_max);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r == 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek break;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek int k;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* DNSSEC validation is always done on the ASCII version of the label */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek k = dns_label_apply_idna(buffer, r, buffer, buffer_max);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (k < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return k;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (k > 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = k;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek if (buffer_max < (size_t) r + 2)
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek return -ENOBUFS;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek /* The DNSSEC canonical form is not clear on what to
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * do with dots appearing in labels, the way DNS-SD
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * does it. Refuse it for now. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (memchr(buffer, '.', r))
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek return -EINVAL;
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek for (i = 0; i < (size_t) r; i ++) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (buffer[i] >= 'A' && buffer[i] <= 'Z')
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering buffer[i] = buffer[i] - 'A' + 'a';
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek buffer[r] = '.';
caa2f4c0c9613b2e02aafa308c8fb092576014a9Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek buffer += r + 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek c += r + 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek buffer_max -= r + 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
00a168618906bea43c3c57e20b9152582c324bf8Olivier Brunel if (c <= 0) {
00a168618906bea43c3c57e20b9152582c324bf8Olivier Brunel /* Not even a single label: this is the root domain name */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
00a168618906bea43c3c57e20b9152582c324bf8Olivier Brunel assert(buffer_max > 2);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek buffer[0] = '.';
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek buffer[1] = 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
caa2f4c0c9613b2e02aafa308c8fb092576014a9Zbigniew Jędrzejewski-Szmek
caa2f4c0c9613b2e02aafa308c8fb092576014a9Zbigniew Jędrzejewski-Szmek return (int) c;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int digest_to_gcrypt_md(uint8_t algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek switch (algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_DIGEST_SHA1:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA1;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_DIGEST_SHA256:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA256;
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNSSEC_DIGEST_SHA384:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA384;
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek default:
433dd100442e8197868def975c6fd38b48dc6439Lukas Nykryn return -EOPNOTSUPP;
433dd100442e8197868def975c6fd38b48dc6439Lukas Nykryn }
433dd100442e8197868def975c6fd38b48dc6439Lukas Nykryn}
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek
433dd100442e8197868def975c6fd38b48dc6439Lukas Nykrynint dnssec_verify_dnskey(DnsResourceRecord *dnskey, DnsResourceRecord *ds) {
433dd100442e8197868def975c6fd38b48dc6439Lukas Nykryn char owner_name[DNSSEC_CANONICAL_HOSTNAME_MAX];
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_hd_t md = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek size_t hash_size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek int md_algorithm, r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek void *result;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(ds);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnskey->key->type != DNS_TYPE_DNSKEY)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ds->key->type != DNS_TYPE_DS)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EKEYREJECTED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnskey->dnskey.protocol != 3)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EKEYREJECTED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnskey->dnskey.algorithm != ds->ds.algorithm)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnssec_keytag(dnskey) != ds->ds.key_tag)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek initialize_libgcrypt();
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_algorithm = digest_to_gcrypt_md(ds->ds.digest_type);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (md_algorithm < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return md_algorithm;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
fc1d70af2101e16c9e6f3c5bfd5ab315ee9e6daeLennart Poettering hash_size = gcry_md_get_algo_dlen(md_algorithm);
fc1d70af2101e16c9e6f3c5bfd5ab315ee9e6daeLennart Poettering assert(hash_size > 0);
fc1d70af2101e16c9e6f3c5bfd5ab315ee9e6daeLennart Poettering
fc1d70af2101e16c9e6f3c5bfd5ab315ee9e6daeLennart Poettering if (ds->ds.digest_size != hash_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dnssec_canonicalize(DNS_RESOURCE_KEY_NAME(dnskey->key), owner_name, sizeof(owner_name));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_open(&md, md_algorithm, 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!md)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EIO;
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_write(md, owner_name, r);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint16(md, dnskey->dnskey.flags);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek md_add_uint8(md, dnskey->dnskey.protocol);
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek md_add_uint8(md, dnskey->dnskey.algorithm);
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek result = gcry_md_read(md, 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!result) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = -EIO;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto finish;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering r = memcmp(result, ds->ds.digest, ds->ds.digest_size) != 0;
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poetteringfinish:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_close(md);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint dnssec_verify_dnskey_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *ds;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsAnswerFlags flags;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek int r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(dnskey);
caa2f4c0c9613b2e02aafa308c8fb092576014a9Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (dnskey->key->type != DNS_TYPE_DNSKEY)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering continue;
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ds->key->type != DNS_TYPE_DS)
00a168618906bea43c3c57e20b9152582c324bf8Olivier Brunel continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (ds->key->class != dnskey->key->class)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), DNS_RESOURCE_KEY_NAME(ds->key));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r == 0)
93b73b064c663d6248bebfbbbd82989b5ca10fc5Lennart Poettering continue;
93b73b064c663d6248bebfbbbd82989b5ca10fc5Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dnssec_verify_dnskey(dnskey, ds);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering return 0;
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int nsec3_hash_to_gcrypt_md(uint8_t algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek switch (algorithm) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case NSEC3_ALGORITHM_SHA1:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return GCRY_MD_SHA1;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek default:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EOPNOTSUPP;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek uint8_t wire_format[DNS_WIRE_FOMAT_HOSTNAME_MAX];
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek gcry_md_hd_t md = NULL;
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering size_t hash_size;
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering int algorithm;
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering void *result;
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering unsigned k;
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering int r;
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(nsec3);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(name);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(ret);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (nsec3->key->type != DNS_TYPE_NSEC3)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_debug("Ignoring NSEC3 RR %s with excessive number of iterations.", dns_resource_record_to_string(nsec3));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EOPNOTSUPP;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (algorithm < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return algorithm;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek initialize_libgcrypt();
763c7aa288485cf5ab627fe1d25ff58e76f9dacbZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek hash_size = gcry_md_get_algo_dlen(algorithm);
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering assert(hash_size > 0);
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (nsec3->nsec3.next_hashed_name_size != hash_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EINVAL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_md_open(&md, algorithm, 0);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!md)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return -EIO;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_md_write(md, wire_format, r);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering result = gcry_md_read(md, 0);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!result) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = -EIO;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering goto finish;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering for (k = 0; k < nsec3->nsec3.iterations; k++) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering uint8_t tmp[hash_size];
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering memcpy(tmp, result, hash_size);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_md_reset(md);
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek gcry_md_write(md, tmp, hash_size);
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek result = gcry_md_read(md, 0);
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek if (!result) {
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek r = -EIO;
bdd13f6be4b588568683a1ab54f421fc6a636dbbZbigniew Jędrzejewski-Szmek goto finish;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering memcpy(ret, result, hash_size);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = (int) hash_size;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringfinish:
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering gcry_md_close(md);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering}
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int nsec3_is_good(DnsResourceRecord *rr, DnsAnswerFlags flags, DnsResourceRecord *nsec3) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek const char *a, *b;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering int r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(rr);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->key->type != DNS_TYPE_NSEC3)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!IN_SET(rr->nsec3.flags, 0, 1))
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Ignore NSEC3 RRs whose algorithm we don't know */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Ignore NSEC3 RRs with an excessive number of required iterations */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!nsec3)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 1;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (nsec3 == rr) /* Shortcut */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 1;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->key->class != nsec3->key->class)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->nsec3.iterations != nsec3->nsec3.iterations)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (memcmp(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering a = DNS_RESOURCE_KEY_NAME(rr->key);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = dns_name_parent(&a); /* strip off hash */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r == 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek b = DNS_RESOURCE_KEY_NAME(nsec3->key);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = dns_name_parent(&b); /* strip off hash */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r == 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return dns_name_equal(a, b);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering}
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringstatic int nsec3_hashed_domain(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering _cleanup_free_ char *l = NULL, *hashed_domain = NULL;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering int hashed_size;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(nsec3);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(domain);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(zone);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(ret);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (hashed_size < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return hashed_size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering l = base32hexmem(hashed, hashed_size, false);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!l)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return -ENOMEM;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering hashed_domain = strjoin(l, ".", zone, NULL);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!hashed_domain)
3bfd4e0c6341b0ef946d2198f089743fa99e0a97WaLyong Cho return -ENOMEM;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
74055aa76278232ff05574fc47c4e6b3560554a7Lennart Poettering *ret = hashed_domain;
74055aa76278232ff05574fc47c4e6b3560554a7Lennart Poettering hashed_domain = NULL;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return hashed_size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering/* See RFC 5155, Section 8
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * matches the wildcard domain.
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering *
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * that there is no proof either way. The latter is the case if a the proof of non-existence of a given
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * to conclude anything we indicate this by returning NO_RR. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering _cleanup_free_ char *next_closer_domain = NULL, *wildcard = NULL, *wildcard_domain = NULL;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering const char *zone, *p, *pp = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *rr, *enclosure_rr, *suffix_rr, *wildcard_rr = NULL;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering DnsAnswerFlags flags;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek int hashed_size, r;
4daf54a851e4fb7ed1a13c3117bba12528fd2c7fZbigniew Jędrzejewski-Szmek bool a, no_closer = false, no_wildcard = false, optout = false;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
6203e07a83214a55bb1f88508fcda2005c601deaLennart Poettering assert(key);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(result);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(authenticated);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* First step, find the zone name and the NSEC3 parameters of the zone.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * it is sufficient to look for the longest common suffix we find with
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * records from a given zone in a response must use the same
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * parameters. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek zone = DNS_RESOURCE_KEY_NAME(key);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek for (;;) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH_FLAGS(suffix_rr, flags, answer) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = nsec3_is_good(suffix_rr, flags, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r == 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering continue;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering r = dns_name_equal_skip(DNS_RESOURCE_KEY_NAME(suffix_rr->key), 1, zone);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0)
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering goto found_zone;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Strip one label from the front */
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering r = dns_name_parent(&zone);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r == 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek break;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NO_RR;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer return 0;
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekfound_zone:
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek p = DNS_RESOURCE_KEY_NAME(key);
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering for (;;) {
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering _cleanup_free_ char *hashed_domain = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering hashed_size = nsec3_hashed_domain(suffix_rr, p, zone, &hashed_domain);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (hashed_size == -EOPNOTSUPP) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (hashed_size < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return hashed_size;
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = nsec3_is_good(enclosure_rr, flags, suffix_rr);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r == 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_name_equal(DNS_RESOURCE_KEY_NAME(enclosure_rr->key), hashed_domain);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek a = flags & DNS_ANSWER_AUTHENTICATED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek goto found_closest_encloser;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen /* We didn't find the closest encloser with this name,
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen * but let's remember this domain name, it might be
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen * the next closer name */
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen pp = p;
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Strip one label from the front */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_name_parent(&p);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r == 0)
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek break;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NO_RR;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmekfound_closest_encloser:
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek /* We found a closest encloser in 'p'; next closer is 'pp' */
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return -EBADMSG;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* Ensure that this data is from the delegated domain
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk * (i.e. originates from the "lower" DNS server), and isn't
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk * just glue records (i.e. doesn't originate from the "upper"
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk * DNS server). */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return -EBADMSG;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering if (!pp) {
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk if (bitmap_isset(enclosure_rr->nsec3.types, key->type))
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk *result = DNSSEC_NSEC_FOUND;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME))
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering *result = DNSSEC_NSEC_CNAME;
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering else
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering *result = DNSSEC_NSEC_NODATA;
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering *authenticated = a;
d07f7b9ef2835c290d6beadebd17d15308608eeaLennart Poettering
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return 0;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk }
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* Prove that there is no next closer and whether or not there is a wildcard domain. */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
ca2670162464b98f44d3f30a1d8b47b02609784cMichał Bartoszkiewicz wildcard = strappend("*.", p);
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering if (!wildcard)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return -ENOMEM;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk r = nsec3_hashed_domain(enclosure_rr, wildcard, zone, &wildcard_domain);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r != hashed_size)
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering return -EBADMSG;
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering r = nsec3_hashed_domain(enclosure_rr, pp, zone, &next_closer_domain);
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering if (r < 0)
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering return r;
6a0f1f6d5af7c7300d3db7a0ba2b068f8abd222bLennart Poettering if (r != hashed_size)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return -EBADMSG;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering _cleanup_free_ char *label = NULL, *next_hashed_domain = NULL;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = nsec3_is_good(rr, flags, suffix_rr);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r < 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (r == 0)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering continue;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk label = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!label)
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return -ENOMEM;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering next_hashed_domain = strjoin(label, ".", zone, NULL);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk if (!next_hashed_domain)
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return -ENOMEM;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), next_closer_domain, next_hashed_domain);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (r < 0)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return r;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (r > 0) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (rr->nsec3.flags & 1)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering optout = true;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering a = a && (flags & DNS_ANSWER_AUTHENTICATED);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering no_closer = true;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering }
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (r < 0)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return r;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (r > 0) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering a = a && (flags & DNS_ANSWER_AUTHENTICATED);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering wildcard_rr = rr;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering }
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain, next_hashed_domain);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (r < 0)
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner return r;
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner if (r > 0) {
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner if (rr->nsec3.flags & 1)
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner /* This only makes sense if we have a wildcard delegation, which is
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering * this not happening, so hence cannot simply conclude NXDOMAIN as
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner * we would wish */
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner optout = true;
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering a = a && (flags & DNS_ANSWER_AUTHENTICATED);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering no_wildcard = true;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering }
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering }
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (wildcard_rr && no_wildcard)
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return -EBADMSG;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering if (!no_closer) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering *result = DNSSEC_NSEC_NO_RR;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (wildcard_rr) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* A wildcard exists that matches our query. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (optout)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* This is not specified in any RFC to the best of my knowledge, but
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering * if the next closer enclosure is covered by an opt-out NSEC3 RR
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * it means that we cannot prove that the source of synthesis is
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * correct, as there may be a closer match. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_OPTOUT;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk else if (bitmap_isset(wildcard_rr->nsec3.types, key->type))
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk *result = DNSSEC_NSEC_FOUND;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_CNAME;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NODATA;
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen } else {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (optout)
e150e82097211f09b911c7784a89ef9efed713caMichał Bartoszkiewicz /* The RFC only specifies that we have to care for optout for NODATA for
e150e82097211f09b911c7784a89ef9efed713caMichał Bartoszkiewicz * DS records. However, children of an insecure opt-out delegation should
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * also be considered opt-out, rather than verified NXDOMAIN.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * Note that we do not require a proof of wildcard non-existence if the
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * next closer domain is covered by an opt-out, as that would not provide
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek * any additional information. */
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen *result = DNSSEC_NSEC_OPTOUT;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (no_wildcard)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NXDOMAIN;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NO_RR;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d288f79fb4a2fe4a93cf99f74dacd2cebd3f2440Zbigniew Jędrzejewski-Szmek }
b1389b0d0805392570085acc7cb10eafcf885405Zbigniew Jędrzejewski-Szmek }
b1389b0d0805392570085acc7cb10eafcf885405Zbigniew Jędrzejewski-Szmek
d288f79fb4a2fe4a93cf99f74dacd2cebd3f2440Zbigniew Jędrzejewski-Szmek *authenticated = a;
d288f79fb4a2fe4a93cf99f74dacd2cebd3f2440Zbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidtint dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsResourceRecord *rr;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek bool have_nsec3 = false;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsAnswerFlags flags;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek int r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(key);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert(result);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(authenticated);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (rr->key->class != key->class)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering continue;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek switch (rr->key->type) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNS_TYPE_NSEC:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (bitmap_isset(rr->nsec.types, key->type))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_FOUND;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_CNAME;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NODATA;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key), rr->nsec.next_domain_name);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r < 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return r;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (r > 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NXDOMAIN;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
03ee5c38cb0da193dd08733fb4c0c2809cee6a99Lennart Poettering }
03ee5c38cb0da193dd08733fb4c0c2809cee6a99Lennart Poettering break;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek case DNS_TYPE_NSEC3:
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek have_nsec3 = true;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek break;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek }
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* OK, this was not sufficient. Let's see if NSEC3 can help. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (have_nsec3)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return dnssec_test_nsec3(answer, key, result, authenticated);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* No approproate NSEC RR found, report this. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *result = DNSSEC_NSEC_NO_RR;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return 0;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek}
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_NO] = "no",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_DOWNGRADE_OK] = "downgrade-ok",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_YES] = "yes",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek};
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-SzmekDEFINE_STRING_TABLE_LOOKUP(dnssec_mode, DnssecMode);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_VALIDATED] = "validated",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_INVALID] = "invalid",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_NO_SIGNATURE] = "no-signature",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_MISSING_KEY] = "missing-key",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_UNSIGNED] = "unsigned",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server",
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering};
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering