]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/ds.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / ds.c
1 /*
2  * Copyright (C) 2004-2007, 2010, 2012  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_SHA384_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         isc_sha384_t sha384;
62 #ifdef HAVE_OPENSSL_GOST
63         EVP_MD_CTX ctx;
64         const EVP_MD *md;
65 #endif
66
67         REQUIRE(key != NULL);
68         REQUIRE(key->type == dns_rdatatype_dnskey);
69
70         if (!dns_ds_digest_supported(digest_type))
71                 return (ISC_R_NOTIMPLEMENTED);
72
73         dns_fixedname_init(&fname);
74         name = dns_fixedname_name(&fname);
75         (void)dns_name_downcase(owner, name, NULL);
76
77         memset(buffer, 0, DNS_DS_BUFFERSIZE);
78         isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
79
80         switch (digest_type) {
81         case DNS_DSDIGEST_SHA1:
82                 isc_sha1_init(&sha1);
83                 dns_name_toregion(name, &r);
84                 isc_sha1_update(&sha1, r.base, r.length);
85                 dns_rdata_toregion(key, &r);
86                 INSIST(r.length >= 4);
87                 isc_sha1_update(&sha1, r.base, r.length);
88                 isc_sha1_final(&sha1, digest);
89                 break;
90
91 #ifdef HAVE_OPENSSL_GOST
92 #define CHECK(x)                                        \
93         if ((x) != 1) {                                 \
94                 EVP_MD_CTX_cleanup(&ctx);               \
95                 return (DST_R_CRYPTOFAILURE);           \
96         }
97
98         case DNS_DSDIGEST_GOST:
99                 md = EVP_gost();
100                 if (md == NULL)
101                         return (DST_R_CRYPTOFAILURE);
102                 EVP_MD_CTX_init(&ctx);
103                 CHECK(EVP_DigestInit(&ctx, md));
104                 dns_name_toregion(name, &r);
105                 CHECK(EVP_DigestUpdate(&ctx,
106                                        (const void *) r.base,
107                                        (size_t) r.length));
108                 dns_rdata_toregion(key, &r);
109                 INSIST(r.length >= 4);
110                 CHECK(EVP_DigestUpdate(&ctx,
111                                        (const void *) r.base,
112                                        (size_t) r.length));
113                 CHECK(EVP_DigestFinal(&ctx, digest, NULL));
114                 break;
115 #endif
116
117         case DNS_DSDIGEST_SHA384:
118                 isc_sha384_init(&sha384);
119                 dns_name_toregion(name, &r);
120                 isc_sha384_update(&sha384, r.base, r.length);
121                 dns_rdata_toregion(key, &r);
122                 INSIST(r.length >= 4);
123                 isc_sha384_update(&sha384, r.base, r.length);
124                 isc_sha384_final(digest, &sha384);
125                 break;
126
127         case DNS_DSDIGEST_SHA256:
128         default:
129                 isc_sha256_init(&sha256);
130                 dns_name_toregion(name, &r);
131                 isc_sha256_update(&sha256, r.base, r.length);
132                 dns_rdata_toregion(key, &r);
133                 INSIST(r.length >= 4);
134                 isc_sha256_update(&sha256, r.base, r.length);
135                 isc_sha256_final(digest, &sha256);
136                 break;
137         }
138
139         ds.mctx = NULL;
140         ds.common.rdclass = key->rdclass;
141         ds.common.rdtype = dns_rdatatype_ds;
142         ds.algorithm = r.base[3];
143         ds.key_tag = dst_region_computeid(&r, ds.algorithm);
144         ds.digest_type = digest_type;
145         switch (digest_type) {
146         case DNS_DSDIGEST_SHA1:
147                 ds.length = ISC_SHA1_DIGESTLENGTH;
148                 break;
149
150 #ifdef HAVE_OPENSSL_GOST
151         case DNS_DSDIGEST_GOST:
152                 ds.length = ISC_GOST_DIGESTLENGTH;
153                 break;
154 #endif
155
156         case DNS_DSDIGEST_SHA384:
157                 ds.length = ISC_SHA384_DIGESTLENGTH;
158                 break;
159
160         case DNS_DSDIGEST_SHA256:
161         default:
162                 ds.length = ISC_SHA256_DIGESTLENGTH;
163                 break;
164         }
165         ds.digest = digest;
166
167         return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
168                                      &ds, &b));
169 }
170
171 isc_boolean_t
172 dns_ds_digest_supported(unsigned int digest_type) {
173 #ifdef HAVE_OPENSSL_GOST
174         return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
175                         digest_type == DNS_DSDIGEST_SHA256 ||
176                         digest_type == DNS_DSDIGEST_GOST ||
177                         digest_type == DNS_DSDIGEST_SHA384));
178 #else
179         return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
180                         digest_type == DNS_DSDIGEST_SHA256 ||
181                         digest_type == DNS_DSDIGEST_SHA384));
182 #endif
183 }