0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2002-2007, 2010, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
a094c46640de70bb03a9351211fb17c41b6fbbb5Automatic Updater/* $Id: ds.c,v 1.13 2010/12/23 23:47:08 tbox Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <config.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <string.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <isc/buffer.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <isc/region.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <isc/sha1.h>
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews#include <isc/sha2.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <isc/util.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dns/ds.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dns/fixedname.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dns/name.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dns/rdata.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dns/rdatastruct.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dns/result.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <dst/dst.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#include "dst_gost.h"
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews#endif
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsisc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int digest_type, unsigned char *buffer,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_t *rdata)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_fixedname_t fname;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *name;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews unsigned char digest[ISC_SHA384_DIGESTLENGTH];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_region_t r;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_t b;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_ds_t ds;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews isc_sha1_t sha1;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews isc_sha256_t sha256;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews isc_sha384_t sha384;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_gost_t gost;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews REQUIRE(key != NULL);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews REQUIRE(key->type == dns_rdatatype_dnskey);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
058e44186b74531402c1f99088eb9dbe4926f8daMark Andrews if (!dst_ds_digest_supported(digest_type))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_NOTIMPLEMENTED);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_fixedname_init(&fname);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews name = dns_fixedname_name(&fname);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (void)dns_name_downcase(owner, name, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews memset(buffer, 0, DNS_DS_BUFFERSIZE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews switch (digest_type) {
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews case DNS_DSDIGEST_SHA1:
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha1_init(&sha1);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews dns_name_toregion(name, &r);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha1_update(&sha1, r.base, r.length);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews dns_rdata_toregion(key, &r);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews INSIST(r.length >= 4);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha1_update(&sha1, r.base, r.length);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha1_final(&sha1, digest);
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews break;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#define RETERR(x) do { \
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_result_t ret = (x); \
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt if (ret != ISC_R_SUCCESS) { \
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_gost_invalidate(&gost); \
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt return (ret); \
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt } \
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt} while (0)
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews case DNS_DSDIGEST_GOST:
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt RETERR(isc_gost_init(&gost));
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews dns_name_toregion(name, &r);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt RETERR(isc_gost_update(&gost, r.base, r.length));
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews dns_rdata_toregion(key, &r);
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews INSIST(r.length >= 4);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt RETERR(isc_gost_update(&gost, r.base, r.length));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt RETERR(isc_gost_final(&gost, digest));
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews break;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews#endif
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews case DNS_DSDIGEST_SHA384:
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews isc_sha384_init(&sha384);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews dns_name_toregion(name, &r);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews isc_sha384_update(&sha384, r.base, r.length);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews dns_rdata_toregion(key, &r);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews INSIST(r.length >= 4);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews isc_sha384_update(&sha384, r.base, r.length);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews isc_sha384_final(digest, &sha384);
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews break;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews case DNS_DSDIGEST_SHA256:
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews default:
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha256_init(&sha256);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews dns_name_toregion(name, &r);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha256_update(&sha256, r.base, r.length);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews dns_rdata_toregion(key, &r);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews INSIST(r.length >= 4);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha256_update(&sha256, r.base, r.length);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_sha256_final(digest, &sha256);
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews break;
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ds.mctx = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ds.common.rdclass = key->rdclass;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ds.common.rdtype = dns_rdatatype_ds;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ds.algorithm = r.base[3];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ds.key_tag = dst_region_computeid(&r, ds.algorithm);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews ds.digest_type = digest_type;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews switch (digest_type) {
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews case DNS_DSDIGEST_SHA1:
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews ds.length = ISC_SHA1_DIGESTLENGTH;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews break;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews case DNS_DSDIGEST_GOST:
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews ds.length = ISC_GOST_DIGESTLENGTH;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews break;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews#endif
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews case DNS_DSDIGEST_SHA384:
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews ds.length = ISC_SHA384_DIGESTLENGTH;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews break;
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews case DNS_DSDIGEST_SHA256:
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews default:
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews ds.length = ISC_SHA256_DIGESTLENGTH;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews break;
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ds.digest = digest;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &ds, &b));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}