]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/bind9/lib/dns/ds.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / bind9 / lib / dns / ds.c
1 /*
2  * Copyright (C) 2004-2007, 2010  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2002, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: ds.c,v 1.13 2010-12-23 23:47:08 tbox Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <string.h>
25
26 #include <isc/buffer.h>
27 #include <isc/region.h>
28 #include <isc/sha1.h>
29 #include <isc/sha2.h>
30 #include <isc/util.h>
31
32 #include <dns/ds.h>
33 #include <dns/fixedname.h>
34 #include <dns/name.h>
35 #include <dns/rdata.h>
36 #include <dns/rdatastruct.h>
37 #include <dns/result.h>
38
39 #include <dst/dst.h>
40
41 #ifdef HAVE_OPENSSL_GOST
42 #include <dst/result.h>
43 #include <openssl/evp.h>
44
45 extern const EVP_MD * EVP_gost(void);
46 #endif
47
48 isc_result_t
49 dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
50                   unsigned int digest_type, unsigned char *buffer,
51                   dns_rdata_t *rdata)
52 {
53         dns_fixedname_t fname;
54         dns_name_t *name;
55         unsigned char digest[ISC_SHA256_DIGESTLENGTH];
56         isc_region_t r;
57         isc_buffer_t b;
58         dns_rdata_ds_t ds;
59         isc_sha1_t sha1;
60         isc_sha256_t sha256;
61 #ifdef HAVE_OPENSSL_GOST
62         EVP_MD_CTX ctx;
63         const EVP_MD *md;
64 #endif
65
66         REQUIRE(key != NULL);
67         REQUIRE(key->type == dns_rdatatype_dnskey);
68
69         if (!dns_ds_digest_supported(digest_type))
70                 return (ISC_R_NOTIMPLEMENTED);
71
72         dns_fixedname_init(&fname);
73         name = dns_fixedname_name(&fname);
74         (void)dns_name_downcase(owner, name, NULL);
75
76         memset(buffer, 0, DNS_DS_BUFFERSIZE);
77         isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
78
79         switch (digest_type) {
80         case DNS_DSDIGEST_SHA1:
81                 isc_sha1_init(&sha1);
82                 dns_name_toregion(name, &r);
83                 isc_sha1_update(&sha1, r.base, r.length);
84                 dns_rdata_toregion(key, &r);
85                 INSIST(r.length >= 4);
86                 isc_sha1_update(&sha1, r.base, r.length);
87                 isc_sha1_final(&sha1, digest);
88                 break;
89 #ifdef HAVE_OPENSSL_GOST
90 #define CHECK(x)                                        \
91         if ((x) != 1) {                                 \
92                 EVP_MD_CTX_cleanup(&ctx);               \
93                 return (DST_R_OPENSSLFAILURE);          \
94         }
95
96         case DNS_DSDIGEST_GOST:
97                 md = EVP_gost();
98                 if (md == NULL)
99                         return (DST_R_OPENSSLFAILURE);
100                 EVP_MD_CTX_init(&ctx);
101                 CHECK(EVP_DigestInit(&ctx, md));
102                 dns_name_toregion(name, &r);
103                 CHECK(EVP_DigestUpdate(&ctx,
104                                        (const void *) r.base,
105                                        (size_t) r.length));
106                 dns_rdata_toregion(key, &r);
107                 INSIST(r.length >= 4);
108                 CHECK(EVP_DigestUpdate(&ctx,
109                                        (const void *) r.base,
110                                        (size_t) r.length));
111                 CHECK(EVP_DigestFinal(&ctx, digest, NULL));
112                 break;
113 #endif
114         default:
115                 isc_sha256_init(&sha256);
116                 dns_name_toregion(name, &r);
117                 isc_sha256_update(&sha256, r.base, r.length);
118                 dns_rdata_toregion(key, &r);
119                 INSIST(r.length >= 4);
120                 isc_sha256_update(&sha256, r.base, r.length);
121                 isc_sha256_final(digest, &sha256);
122                 break;
123         }
124
125         ds.mctx = NULL;
126         ds.common.rdclass = key->rdclass;
127         ds.common.rdtype = dns_rdatatype_ds;
128         ds.algorithm = r.base[3];
129         ds.key_tag = dst_region_computeid(&r, ds.algorithm);
130         ds.digest_type = digest_type;
131         switch (digest_type) {
132         case DNS_DSDIGEST_SHA1:
133                 ds.length = ISC_SHA1_DIGESTLENGTH;
134                 break;
135 #ifdef HAVE_OPENSSL_GOST
136         case DNS_DSDIGEST_GOST:
137                 ds.length = ISC_GOST_DIGESTLENGTH;
138                 break;
139 #endif
140         default:
141                 ds.length = ISC_SHA256_DIGESTLENGTH;
142                 break;
143         }
144         ds.digest = digest;
145
146         return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
147                                      &ds, &b));
148 }
149
150 isc_boolean_t
151 dns_ds_digest_supported(unsigned int digest_type) {
152 #ifdef HAVE_OPENSSL_GOST
153         return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
154                         digest_type == DNS_DSDIGEST_SHA256 ||
155                         digest_type == DNS_DSDIGEST_GOST));
156 #else
157         return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
158                         digest_type == DNS_DSDIGEST_SHA256));
159 #endif
160 }