resolved-dns-dnssec.c revision e0240c64b76ba8f0c9219feb23a5783f23100216
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/***
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc This file is part of systemd.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc Copyright 2015 Lennart Poettering
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc systemd is free software; you can redistribute it and/or modify it
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc under the terms of the GNU Lesser General Public License as published by
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc the Free Software Foundation; either version 2.1 of the License, or
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (at your option) any later version.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc systemd is distributed in the hope that it will be useful, but
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc WITHOUT ANY WARRANTY; without even the implied warranty of
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc Lesser General Public License for more details.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc You should have received a copy of the GNU Lesser General Public License
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc along with systemd; If not, see <http://www.gnu.org/licenses/>.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc***/
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <gcrypt.h>
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "alloc-util.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "dns-domain.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "hexdecoct.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "resolved-dns-dnssec.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "resolved-dns-packet.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "string-table.h"
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh/* Open question:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * How does the DNSSEC canonical form of a hostname with a label
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * containing a dot look like, the way DNS-SD does it?
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh *
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * TODO:
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh *
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - Make trust anchor store read additional DS+DNSKEY data from disk
f595a68a3b8953a12aa778c2abd7642df8da8c3ayz * - wildcard zones compatibility (NSEC/NSEC3 wildcard check is missing)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * - multi-label zone compatibility
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * - cname/dname compatibility
f595a68a3b8953a12aa778c2abd7642df8da8c3ayz * - per-interface DNSSEC setting
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * - fix TTL for cache entries to match RRSIG TTL
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - retry on failed validation?
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh * - DSA support?
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini * */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini#define VERIFY_RRS_MAX 256
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini#define MAX_KEY_SIZE (32*1024)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan/* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh#define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems/*
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems * The DNSSEC Chain of trust:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * DS RRs are protected like normal RRs
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Example chain:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic void initialize_libgcrypt(void) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini const char *p;
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz p = gcry_check_version("1.4.5");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(p);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_control(GCRYCTL_DISABLE_SECMEM);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini}
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic bool dnssec_algorithm_supported(int algorithm) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return IN_SET(algorithm,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNSSEC_ALGORITHM_RSASHA1,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini DNSSEC_ALGORITHM_RSASHA256,
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini DNSSEC_ALGORITHM_RSASHA512,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh DNSSEC_ALGORITHM_ECDSAP256SHA256,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh DNSSEC_ALGORITHM_ECDSAP384SHA384);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzuint16_t dnssec_keytag(DnsResourceRecord *dnskey) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz const uint8_t *p;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint32_t sum;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini size_t i;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini /* The algorithm from RFC 4034, Appendix B. */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(dnskey);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(dnskey->key->type == DNS_TYPE_DNSKEY);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini sum = (uint32_t) dnskey->dnskey.flags +
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini p = dnskey->dnskey.key;
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini for (i = 0; i < dnskey->dnskey.key_size; i++)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i];
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
3fd94f8c011031b38162a1db3b554de4371c167fam sum += (sum >> 16) & UINT32_C(0xFFFF);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return sum & UINT32_C(0xFFFF);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int rr_compare(const void *a, const void *b) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan size_t m;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan int r;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems /* Let's order the RRs according to RFC 4034, Section 6.3 */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(x);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini assert(*x);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert((*x)->wire_format);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(y);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(*y);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert((*y)->wire_format);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz m = MIN((*x)->wire_format_size, (*y)->wire_format_size);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = memcmp((*x)->wire_format, (*y)->wire_format, m);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r != 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if ((*x)->wire_format_size < (*y)->wire_format_size)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return -1;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini else if ((*x)->wire_format_size > (*y)->wire_format_size)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 1;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 0;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int dnssec_rsa_verify_raw(
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const char *hash_algorithm,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const void *signature, size_t signature_size,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const void *data, size_t data_size,
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini const void *exponent, size_t exponent_size,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh const void *modulus, size_t modulus_size) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_mpi_t n = NULL, e = NULL, s = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_error_t ge;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(hash_algorithm);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_sexp_build(&signature_sexp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz NULL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "(sig-val (rsa (s %m)))",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz s);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_sexp_build(&data_sexp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz NULL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "(data (flags pkcs1) (hash %s %b))",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash_algorithm,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (int) data_size,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz data);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_sexp_build(&public_key_sexp,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini NULL,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini "(public-key (rsa (n %m) (e %m)))",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz n,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz e);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh r = 0;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh else if (ge != 0) {
3fd94f8c011031b38162a1db3b554de4371c167fam log_debug("RSA signature check failed: %s", gpg_strerror(ge));
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini r = -EIO;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan } else
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan r = 1;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanfinish:
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (e)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_mpi_release(e);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (n)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_mpi_release(n);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (s)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_mpi_release(s);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (public_key_sexp)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_sexp_release(public_key_sexp);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (signature_sexp)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_sexp_release(signature_sexp);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (data_sexp)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_sexp_release(data_sexp);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return r;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int dnssec_rsa_verify(
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const char *hash_algorithm,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const void *hash, size_t hash_size,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan DnsResourceRecord *rrsig,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan DnsResourceRecord *dnskey) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan size_t exponent_size, modulus_size;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan void *exponent, *modulus;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(hash_algorithm);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(hash);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(hash_size > 0);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(rrsig);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(dnskey);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (*(uint8_t*) dnskey->dnskey.key == 0) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan /* exponent is > 255 bytes long */
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan exponent = (uint8_t*) dnskey->dnskey.key + 3;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan exponent_size =
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ((size_t) (((uint8_t*) dnskey->dnskey.key)[0]) << 8) |
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ((size_t) ((uint8_t*) dnskey->dnskey.key)[1]);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (exponent_size < 256)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return -EINVAL;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (3 + exponent_size >= dnskey->dnskey.key_size)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return -EINVAL;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan modulus_size = dnskey->dnskey.key_size - 3 - exponent_size;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan } else {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini /* exponent is <= 255 bytes long */
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini exponent = (uint8_t*) dnskey->dnskey.key + 1;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0];
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (exponent_size <= 0)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return -EINVAL;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (1 + exponent_size >= dnskey->dnskey.key_size)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return -EINVAL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems modulus_size = dnskey->dnskey.key_size - 1 - exponent_size;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan }
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return dnssec_rsa_verify_raw(
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini hash_algorithm,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan rrsig->rrsig.signature, rrsig->rrsig.signature_size,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini hash, hash_size,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan exponent, exponent_size,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini modulus, modulus_size);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic int dnssec_ecdsa_verify_raw(
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const char *hash_algorithm,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini const char *curve,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const void *signature_r, size_t signature_r_size,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini const void *signature_s, size_t signature_s_size,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan const void *data, size_t data_size,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini const void *key, size_t key_size) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan gcry_mpi_t q = NULL, r = NULL, s = NULL;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_error_t ge;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan int k;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(hash_algorithm);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (ge != 0) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan k = -EIO;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan goto finish;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan }
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (ge != 0) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini k = -EIO;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini goto finish;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini }
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (ge != 0) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini k = -EIO;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini goto finish;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini }
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini ge = gcry_sexp_build(&signature_sexp,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini NULL,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini "(sig-val (ecdsa (r %m) (s %m)))",
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini r,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini s);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (ge != 0) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini k = -EIO;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini goto finish;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini }
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini ge = gcry_sexp_build(&data_sexp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz NULL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "(data (flags rfc6979) (hash %s %b))",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash_algorithm,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (int) data_size,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz data);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz k = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_sexp_build(&public_key_sexp,
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh NULL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "(public-key (ecc (curve %s) (q %m)))",
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini curve,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini q);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ge != 0) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini k = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini k = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else if (ge != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz log_debug("ECDSA signature check failed: %s", gpg_strerror(ge));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz k = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz k = 1;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowminifinish:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_mpi_release(r);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (s)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_mpi_release(s);
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini if (q)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_mpi_release(q);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (public_key_sexp)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems gcry_sexp_release(public_key_sexp);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (signature_sexp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_sexp_release(signature_sexp);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (data_sexp)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh gcry_sexp_release(data_sexp);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return k;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini}
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic int dnssec_ecdsa_verify(
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems const char *hash_algorithm,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini int algorithm,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini const void *hash, size_t hash_size,
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini DnsResourceRecord *rrsig,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini DnsResourceRecord *dnskey) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini const char *curve;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini size_t key_size;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini uint8_t *q;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(hash);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(hash_size);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(rrsig);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini assert(dnskey);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems key_size = 32;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini curve = "NIST P-256";
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini key_size = 48;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems curve = "NIST P-384";
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini } else
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return -EOPNOTSUPP;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (dnskey->dnskey.key_size != key_size * 2)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return -EINVAL;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (rrsig->rrsig.signature_size != key_size * 2)
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini return -EINVAL;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems q = alloca(key_size*2 + 1);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini memcpy(q+1, dnskey->dnskey.key, key_size*2);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return dnssec_ecdsa_verify_raw(
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems hash_algorithm,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini curve,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini rrsig->rrsig.signature, key_size,
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini hash, hash_size,
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems q, key_size*2+1);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini}
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowministatic void md_add_uint8(gcry_md_hd_t md, uint8_t v) {
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_md_write(md, &v, sizeof(v));
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems}
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic void md_add_uint16(gcry_md_hd_t md, uint16_t v) {
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini v = htobe16(v);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_md_write(md, &v, sizeof(v));
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems}
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic void md_add_uint32(gcry_md_hd_t md, uint32_t v) {
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini v = htobe32(v);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini gcry_md_write(md, &v, sizeof(v));
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems}
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowministatic int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) {
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini usec_t expiration, inception, skew;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(rrsig);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(rrsig->key->type == DNS_TYPE_RRSIG);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (realtime == USEC_INFINITY)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini realtime = now(CLOCK_REALTIME);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini expiration = rrsig->rrsig.expiration * USEC_PER_SEC;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini inception = rrsig->rrsig.inception * USEC_PER_SEC;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (inception > expiration)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return -EKEYREJECTED;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini /* Permit a certain amount of clock skew of 10% of the valid
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * time range. This takes inspiration from unbound's
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini * resolver. */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems skew = (expiration - inception) / 10;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (skew > SKEW_MAX)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini skew = SKEW_MAX;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (inception < skew)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems inception = 0;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini else
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini inception -= skew;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (expiration + skew < expiration)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz expiration = USEC_INFINITY;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan expiration += skew;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return realtime < inception || realtime > expiration;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int algorithm_to_gcrypt(uint8_t algorithm) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Translates a DNSSEC signature algorithm into a gcrypt digest identifier */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz switch (algorithm) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA1:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return GCRY_MD_SHA1;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini case DNSSEC_ALGORITHM_RSASHA256:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_ECDSAP256SHA256:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return GCRY_MD_SHA256;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_ECDSAP384SHA384:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return GCRY_MD_SHA384;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA512:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return GCRY_MD_SHA512;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz default:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EOPNOTSUPP;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint dnssec_verify_rrset(
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsAnswer *a,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceKey *key,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceRecord *rrsig,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceRecord *dnskey,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz usec_t realtime,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnssecResult *result) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz size_t hash_size;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh void *hash;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc DnsResourceRecord **list, *rr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_hd_t md = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int r, algorithm;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz size_t k, n = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(key);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc assert(rrsig);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh assert(dnskey);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(result);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc assert(rrsig->key->type == DNS_TYPE_RRSIG);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc assert(dnskey->key->type == DNS_TYPE_DNSKEY);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Verifies the the RRSet matching the specified "key" in "a",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * using the signature "rrsig" and the key "dnskey". It's
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * assumed the RRSIG and DNSKEY match. */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!dnssec_algorithm_supported(rrsig->rrsig.algorithm)) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_UNSUPPORTED_ALGORITHM;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (a->n_rrs > VERIFY_RRS_MAX)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -E2BIG;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh r = dnssec_rrsig_expired(rrsig, realtime);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return r;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r > 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_SIGNATURE_EXPIRED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Collect all relevant RRs in a single array, so that we can look at the RRset */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz list = newa(DnsResourceRecord *, a->n_rrs);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNS_ANSWER_FOREACH(rr, a) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_resource_key_equal(key, rr->key);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (r < 0)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini return r;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (r == 0)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* We need the wire format for ordering, and digest calculation */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_resource_record_to_wire_format(rr, true);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
d62bc4badc1c1f1549c961cfb8b420e650e1272byz list[n++] = rr;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini }
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (n <= 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -ENODATA;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Bring the RRs into canonical order */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz qsort_safe(list, n, sizeof(DnsResourceRecord*), rr_compare);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* OK, the RRs are now in canonical order. Let's calculate the digest */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz initialize_libgcrypt();
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz algorithm = algorithm_to_gcrypt(rrsig->rrsig.algorithm);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (algorithm < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return algorithm;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash_size = gcry_md_get_algo_dlen(algorithm);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(hash_size > 0);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini gcry_md_open(&md, algorithm, 0);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (!md)
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini return -EIO;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint16(md, rrsig->rrsig.type_covered);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint8(md, rrsig->rrsig.algorithm);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint8(md, rrsig->rrsig.labels);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint32(md, rrsig->rrsig.original_ttl);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint32(md, rrsig->rrsig.expiration);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint32(md, rrsig->rrsig.inception);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems md_add_uint16(md, rrsig->rrsig.key_tag);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (r < 0)
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini goto finish;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini gcry_md_write(md, wire_format_name, r);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini for (k = 0; k < n; k++) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const char *suffix;
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini size_t l;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rr = list[k];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini r = dns_name_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rrsig->rrsig.labels, &suffix);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r > 0) /* This is a wildcard! */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_write(md, (uint8_t[]) { 1, '*'}, 2);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_name_to_wire_format(suffix, wire_format_name, sizeof(wire_format_name), true);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_write(md, wire_format_name, r);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz md_add_uint16(md, rr->key->type);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz md_add_uint16(md, rr->key->class);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz md_add_uint32(md, rrsig->rrsig.original_ttl);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz l = rr->wire_format_size - rr->wire_format_rdata_offset;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(l <= 0xFFFF);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz md_add_uint16(md, (uint16_t) l);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh gcry_md_write(md, (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset, l);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash = gcry_md_read(md, 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!hash) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz switch (rrsig->rrsig.algorithm) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA1:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA256:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_ALGORITHM_RSASHA512:
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh r = dnssec_rsa_verify(
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_algo_name(algorithm),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash, hash_size,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rrsig,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dnskey);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini case DNSSEC_ALGORITHM_ECDSAP256SHA256:
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini case DNSSEC_ALGORITHM_ECDSAP384SHA384:
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini r = dnssec_ecdsa_verify(
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems gcry_md_algo_name(algorithm),
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini rrsig->rrsig.algorithm,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini hash, hash_size,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini rrsig,
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini dnskey);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r < 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = r ? DNSSEC_VALIDATED : DNSSEC_INVALID;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byzfinish:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_close(md);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(rrsig);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(dnskey);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Checks if the specified DNSKEY RR matches the key used for
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * the signature in the specified RRSIG RR */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rrsig->key->type != DNS_TYPE_RRSIG)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EINVAL;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (dnskey->key->type != DNS_TYPE_DNSKEY)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnskey->key->class != rrsig->key->class)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (dnskey->dnskey.protocol != 3)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnssec_keytag(dnskey) != rrsig->rrsig.key_tag)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), rrsig->rrsig.signer);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(key);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(rrsig);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rrsig->key->type != DNS_TYPE_RRSIG)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rrsig->key->class != key->class)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rrsig->rrsig.type_covered != key->type)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Make sure signer is a parent of the RRset */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rrsig->key), rrsig->rrsig.signer);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r <= 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Make sure the owner name has at least as many labels as the "label" fields indicates. */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc r = dns_name_count_labels(DNS_RESOURCE_KEY_NAME(rrsig->key));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r < rrsig->rrsig.labels)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return dns_name_equal(DNS_RESOURCE_KEY_NAME(rrsig->key), DNS_RESOURCE_KEY_NAME(key));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint dnssec_verify_rrset_search(
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsAnswer *a,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc DnsResourceKey *key,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsAnswer *validated_dnskeys,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz usec_t realtime,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnssecResult *result) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceRecord *rrsig;
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems int r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini assert(key);
3fd94f8c011031b38162a1db3b554de4371c167fam assert(result);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!a || a->n_rrs <= 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return -ENODATA;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Iterate through each RRSIG RR. */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNS_ANSWER_FOREACH(rrsig, a) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceRecord *dnskey;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini DnsAnswerFlags flags;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini /* Is this an RRSIG RR that applies to RRs matching our key? */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini r = dnssec_key_match_rrsig(key, rrsig);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (r == 0)
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini continue;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini found_rrsig = true;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Look for a matching key */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc DnssecResult one_result;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Is this a DNSKEY RR that matches they key of our RRSIG? */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dnssec_rrsig_match_dnskey(rrsig, dnskey);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Take the time here, if it isn't set yet, so
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini * that we do all validations with the same
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems * time. */
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems if (realtime == USEC_INFINITY)
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems realtime = now(CLOCK_REALTIME);
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems /* Yay, we found a matching RRSIG with a matching
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems * DNSKEY, awesome. Now let's verify all entries of
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems * the RRSet against the RRSIG and DNSKEY
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems * combination. */
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems if (r < 0)
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems return r;
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems switch (one_result) {
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems case DNSSEC_VALIDATED:
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems /* Yay, the RR has been validated,
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems * return immediately. */
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems *result = DNSSEC_VALIDATED;
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems return 0;
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems case DNSSEC_INVALID:
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems /* If the signature is invalid, let's try another
d62bc4badc1c1f1549c961cfb8b420e650e1272byz key and/or signature. After all they
d62bc4badc1c1f1549c961cfb8b420e650e1272byz key_tags and stuff are not unique, and
d62bc4badc1c1f1549c961cfb8b420e650e1272byz might be shared by multiple keys. */
13a55820e952b584554bc6b9d4e9303052a2cf29ar found_invalid = true;
13a55820e952b584554bc6b9d4e9303052a2cf29ar continue;
13a55820e952b584554bc6b9d4e9303052a2cf29ar
13a55820e952b584554bc6b9d4e9303052a2cf29ar case DNSSEC_UNSUPPORTED_ALGORITHM:
13a55820e952b584554bc6b9d4e9303052a2cf29ar /* If the key algorithm is
13a55820e952b584554bc6b9d4e9303052a2cf29ar unsupported, try another
13a55820e952b584554bc6b9d4e9303052a2cf29ar RRSIG/DNSKEY pair, but remember we
d62bc4badc1c1f1549c961cfb8b420e650e1272byz encountered this, so that we can
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return a proper error when we
d62bc4badc1c1f1549c961cfb8b420e650e1272byz encounter nothing better. */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc found_unsupported_algorithm = true;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini continue;
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini case DNSSEC_SIGNATURE_EXPIRED:
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems /* If the signature is expired, try
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini another one, but remember it, so
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini that we can return this */
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini found_expired_rrsig = true;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz default:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert_not_reached("Unexpected DNSSEC validation result");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini }
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (found_expired_rrsig)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_SIGNATURE_EXPIRED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else if (found_unsupported_algorithm)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_UNSUPPORTED_ALGORITHM;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else if (found_invalid)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_INVALID;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else if (found_rrsig)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_MISSING_KEY;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_NO_SIGNATURE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceRecord *rr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Checks whether there's at least one RRSIG in 'a' that proctects RRs of the specified key */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNS_ANSWER_FOREACH(rr, a) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dnssec_key_match_rrsig(key, rr);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r > 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz size_t c = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int r;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Converts the specified hostname into DNSSEC canonicalized
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * form. */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (buffer_max < 2)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return -ENOBUFS;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (;;) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz size_t i;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_label_unescape(&n, buffer, buffer_max);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r > 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int k;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* DNSSEC validation is always done on the ASCII version of the label */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz k = dns_label_apply_idna(buffer, r, buffer, buffer_max);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (k < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return k;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (k > 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = k;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (buffer_max < (size_t) r + 2)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -ENOBUFS;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* The DNSSEC canonical form is not clear on what to
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * do with dots appearing in labels, the way DNS-SD
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * does it. Refuse it for now. */
308903890e892f9c21ee582e3a52fdd67e52870bartem
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (memchr(buffer, '.', r))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EINVAL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (i = 0; i < (size_t) r; i ++) {
308903890e892f9c21ee582e3a52fdd67e52870bartem if (buffer[i] >= 'A' && buffer[i] <= 'Z')
d62bc4badc1c1f1549c961cfb8b420e650e1272byz buffer[i] = buffer[i] - 'A' + 'a';
308903890e892f9c21ee582e3a52fdd67e52870bartem }
308903890e892f9c21ee582e3a52fdd67e52870bartem
308903890e892f9c21ee582e3a52fdd67e52870bartem buffer[r] = '.';
308903890e892f9c21ee582e3a52fdd67e52870bartem
308903890e892f9c21ee582e3a52fdd67e52870bartem buffer += r + 1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz c += r + 1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
308903890e892f9c21ee582e3a52fdd67e52870bartem buffer_max -= r + 1;
308903890e892f9c21ee582e3a52fdd67e52870bartem }
308903890e892f9c21ee582e3a52fdd67e52870bartem
308903890e892f9c21ee582e3a52fdd67e52870bartem if (c <= 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Not even a single label: this is the root domain name */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(buffer_max > 2);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz buffer[0] = '.';
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc buffer[1] = 0;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 1;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini }
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems return (int) c;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int digest_to_gcrypt(uint8_t algorithm) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byz switch (algorithm) {
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini case DNSSEC_DIGEST_SHA1:
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini return GCRY_MD_SHA1;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNSSEC_DIGEST_SHA256:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return GCRY_MD_SHA256;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems case DNSSEC_DIGEST_SHA384:
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return GCRY_MD_SHA384;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems default:
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return -EOPNOTSUPP;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystemsint dnssec_verify_dnskey(DnsResourceRecord *dnskey, DnsResourceRecord *ds) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char owner_name[DNSSEC_CANONICAL_HOSTNAME_MAX];
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems gcry_md_hd_t md = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz size_t hash_size;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int algorithm, r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz void *result;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems assert(dnskey);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc assert(ds);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnskey->key->type != DNS_TYPE_DNSKEY)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EINVAL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ds->key->type != DNS_TYPE_DS)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EINVAL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EKEYREJECTED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnskey->dnskey.protocol != 3)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EKEYREJECTED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnskey->dnskey.algorithm != ds->ds.algorithm)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnssec_keytag(dnskey) != ds->ds.key_tag)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc initialize_libgcrypt();
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz algorithm = digest_to_gcrypt(ds->ds.digest_type);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (algorithm < 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return algorithm;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash_size = gcry_md_get_algo_dlen(algorithm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc assert(hash_size > 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ds->ds.digest_size != hash_size)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc r = dnssec_canonicalize(DNS_RESOURCE_KEY_NAME(dnskey->key), owner_name, sizeof(owner_name));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc gcry_md_open(&md, algorithm, 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!md)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_write(md, owner_name, r);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz md_add_uint16(md, dnskey->dnskey.flags);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz md_add_uint8(md, dnskey->dnskey.protocol);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc md_add_uint8(md, dnskey->dnskey.algorithm);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz result = gcry_md_read(md, 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!result) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = memcmp(result, ds->ds.digest, ds->ds.digest_size) != 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcfinish:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_close(md);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint dnssec_verify_dnskey_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsResourceRecord *ds;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DnsAnswerFlags flags;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int r;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(dnskey);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dnskey->key->type != DNS_TYPE_DNSKEY)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc continue;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (ds->key->type != DNS_TYPE_DS)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini if (ds->key->class != dnskey->key->class)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc continue;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), DNS_RESOURCE_KEY_NAME(ds->key));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r == 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems continue;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dnssec_verify_dnskey(dnskey, ds);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r > 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 1;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 0;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems}
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystemsint dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems uint8_t wire_format[DNS_WIRE_FOMAT_HOSTNAME_MAX];
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems gcry_md_hd_t md = NULL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems size_t hash_size;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems int algorithm;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems void *result;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems unsigned k;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems int r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(nsec3);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(name);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(ret);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (nsec3->key->type != DNS_TYPE_NSEC3)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return -EINVAL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems algorithm = digest_to_gcrypt(nsec3->nsec3.algorithm);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (algorithm < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return algorithm;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz initialize_libgcrypt();
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz hash_size = gcry_md_get_algo_dlen(algorithm);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc assert(hash_size > 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (nsec3->nsec3.next_hashed_name_size != hash_size)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return -EINVAL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_open(&md, algorithm, 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!md)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return -EIO;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems gcry_md_write(md, wire_format, r);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc result = gcry_md_read(md, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!result) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz for (k = 0; k < nsec3->nsec3.iterations; k++) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz uint8_t tmp[hash_size];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc memcpy(tmp, result, hash_size);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_reset(md);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gcry_md_write(md, tmp, hash_size);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz result = gcry_md_read(md, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!result) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = -EIO;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto finish;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc memcpy(ret, result, hash_size);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = (int) hash_size;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystemsfinish:
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems gcry_md_close(md);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems}
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int nsec3_is_good(DnsResourceRecord *rr, DnsAnswerFlags flags, DnsResourceRecord *nsec3) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz const char *a, *b;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems int r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
d62bc4badc1c1f1549c961cfb8b420e650e1272byz assert(rr);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rr->key->type != DNS_TYPE_NSEC3)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!IN_SET(rr->nsec3.flags, 0, 1))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!nsec3)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 1;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (nsec3 == rr) /* Shortcut */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 1;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (rr->key->class != nsec3->key->class)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rr->nsec3.iterations != nsec3->nsec3.iterations)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini return 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (memcmp(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 0;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems a = DNS_RESOURCE_KEY_NAME(rr->key);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = dns_name_parent(&a); /* strip off hash */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r == 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz b = DNS_RESOURCE_KEY_NAME(nsec3->key);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc r = dns_name_parent(&b); /* strip off hash */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r == 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return 0;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return dns_name_equal(a, b);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems}
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystemsstatic int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems _cleanup_free_ char *next_closer_domain = NULL, *l = NULL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems const char *suffix, *p, *pp = NULL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems DnsResourceRecord *rr, *suffix_rr;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems DnsAnswerFlags flags;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems int hashed_size, r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems bool a;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(key);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(result);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems assert(authenticated);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems /* First step, look for the longest common suffix we find with any NSEC3 RR in the response. */
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems suffix = DNS_RESOURCE_KEY_NAME(key);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems for (;;) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems DNS_ANSWER_FOREACH_FLAGS(suffix_rr, flags, answer) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems _cleanup_free_ char *hashed_domain = NULL, *label = NULL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = nsec3_is_good(suffix_rr, flags, NULL);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r == 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems continue;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = dns_name_equal_skip(DNS_RESOURCE_KEY_NAME(suffix_rr->key), 1, suffix);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r > 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems goto found_suffix;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems /* Strip one label from the front */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_name_parent(&suffix);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r == 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems break;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *result = DNSSEC_NSEC_NO_RR;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystemsfound_suffix:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz p = DNS_RESOURCE_KEY_NAME(key);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc for (;;) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems _cleanup_free_ char *hashed_domain = NULL, *label = NULL;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems hashed_size = dnssec_nsec3_hash(suffix_rr, p, hashed);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (hashed_size == -EOPNOTSUPP) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 0;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (hashed_size < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return hashed_size;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems label = base32hexmem(hashed, hashed_size, false);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!label)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return -ENOMEM;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc hashed_domain = strjoin(label, ".", suffix, NULL);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (!hashed_domain)
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems return -ENOMEM;
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = nsec3_is_good(rr, flags, suffix_rr);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r == 0)
3fd94f8c011031b38162a1db3b554de4371c167fam continue;
149b7eb2919570a01d698963b7ab14d45b4edda8Sowmini Varadhan
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini if (rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (r > 0) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems a = flags & DNS_ANSWER_AUTHENTICATED;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto found_closest_encloser;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* We didn't find the closest encloser with this name,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * but let's remember this domain name, it might be
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the next closer name */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems pp = p;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems /* Strip one label from the front */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_name_parent(&p);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems *result = DNSSEC_NSEC_NO_RR;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzfound_closest_encloser:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* We found a closest encloser in 'p'; next closer is 'pp' */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (bitmap_isset(rr->nsec3.types, DNS_TYPE_DNAME))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EBADMSG;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Ensure that this data is from the delegated domain
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * (i.e. originates from the "lower" DNS server), and isn't
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * just glue records (i.e. doesn't originate from the "upper"
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * DNS server). */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (bitmap_isset(rr->nsec3.types, DNS_TYPE_NS) &&
d62bc4badc1c1f1549c961cfb8b420e650e1272byz !bitmap_isset(rr->nsec3.types, DNS_TYPE_SOA))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EBADMSG;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!pp) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = bitmap_isset(rr->nsec3.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *authenticated = a;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dnssec_nsec3_hash(rr, pp, hashed);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r != hashed_size)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -EBADMSG;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc l = base32hexmem(hashed, hashed_size, false);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!l)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -ENOMEM;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
d62bc4badc1c1f1549c961cfb8b420e650e1272byz next_closer_domain = strjoin(l, ".", p, NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!next_closer_domain)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return -ENOMEM;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz _cleanup_free_ char *label = NULL, *next_hashed_domain = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = nsec3_is_good(rr, flags, suffix_rr);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return r;
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini if (r == 0)
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini continue;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
d62bc4badc1c1f1549c961cfb8b420e650e1272byz label = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!label)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -ENOMEM;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz next_hashed_domain = strjoin(label, ".", p, NULL);
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (!next_hashed_domain)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return -ENOMEM;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), next_closer_domain, next_hashed_domain);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r < 0)
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return r;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (r > 0) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems if (rr->nsec3.flags & 1)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh *result = DNSSEC_NSEC_OPTOUT;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems else
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems *result = DNSSEC_NSEC_NXDOMAIN;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems *authenticated = a && (flags & DNS_ANSWER_AUTHENTICATED);
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 1;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems }
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems *result = DNSSEC_NSEC_NO_RR;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems return 0;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh}
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystemsint dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems DnsResourceRecord *rr;
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems bool have_nsec3 = false;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh DnsAnswerFlags flags;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh int r;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(key);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan assert(result);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini assert(authenticated);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rr->key->class != key->class)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan switch (rr->key->type) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan case DNS_TYPE_NSEC:
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r > 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = bitmap_isset(rr->nsec.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh }
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh
d62bc4badc1c1f1549c961cfb8b420e650e1272byz r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key), rr->nsec.next_domain_name);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r < 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return r;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (r > 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *result = DNSSEC_NSEC_NXDOMAIN;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DNS_TYPE_NSEC3:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz have_nsec3 = true;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh /* OK, this was not sufficient. Let's see if NSEC3 can help. */
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh if (have_nsec3)
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return dnssec_test_nsec3(answer, key, result, authenticated);
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems /* No approproate NSEC RR found, report this. */
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems *result = DNSSEC_NSEC_NO_RR;
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh return 0;
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems}
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystemsstatic const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
3bc21d0a9c7b31b1132c254e389a4114c23bcf00Aruna Ramakrishna - Sun Microsystems [DNSSEC_NO] = "no",
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems [DNSSEC_DOWNGRADE_OK] = "downgrade-ok",
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini [DNSSEC_YES] = "yes",
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems};
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowminiDEFINE_STRING_TABLE_LOOKUP(dnssec_mode, DnssecMode);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
f4b3ec61df05330d25f55a36b975b4d7519fdeb1dh [DNSSEC_VALIDATED] = "validated",
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini [DNSSEC_INVALID] = "invalid",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems [DNSSEC_NO_SIGNATURE] = "no-signature",
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems [DNSSEC_MISSING_KEY] = "missing-key",
d62bc4badc1c1f1549c961cfb8b420e650e1272byz [DNSSEC_UNSIGNED] = "unsigned",
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
afdda45f890ee5dfc86e5131a30b11b354d51633Vasumathi Sundaram - Sun Microsystems [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch",
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server",
6b9e797c2ea518518cb2b57895991d8bdaa167fesowmini};
4045d94132614e1de2073685a6cdd4fbd86bec33sowminiDEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
4045d94132614e1de2073685a6cdd4fbd86bec33sowmini