1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /* $Id: ds_43.c,v 1.13 2020/02/26 18:47:59 florian Exp $ */
18
19 /* RFC3658 */
20
21 #ifndef RDATA_GENERIC_DS_43_C
22 #define RDATA_GENERIC_DS_43_C
23
24 #include <isc/sha1.h>
25 #include <isc/sha2.h>
26
27 #include <dns/ds.h>
28
29 static inline isc_result_t
generic_totext_ds(ARGS_TOTEXT)30 generic_totext_ds(ARGS_TOTEXT) {
31 isc_region_t sr;
32 char buf[sizeof("64000 ")];
33 unsigned int n;
34
35 REQUIRE(rdata->length != 0);
36
37 UNUSED(tctx);
38
39 dns_rdata_toregion(rdata, &sr);
40
41 /*
42 * Key tag.
43 */
44 n = uint16_fromregion(&sr);
45 isc_region_consume(&sr, 2);
46 snprintf(buf, sizeof(buf), "%u ", n);
47 RETERR(isc_str_tobuffer(buf, target));
48
49 /*
50 * Algorithm.
51 */
52 n = uint8_fromregion(&sr);
53 isc_region_consume(&sr, 1);
54 snprintf(buf, sizeof(buf), "%u ", n);
55 RETERR(isc_str_tobuffer(buf, target));
56
57 /*
58 * Digest type.
59 */
60 n = uint8_fromregion(&sr);
61 isc_region_consume(&sr, 1);
62 snprintf(buf, sizeof(buf), "%u", n);
63 RETERR(isc_str_tobuffer(buf, target));
64
65 /*
66 * Digest.
67 */
68 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
69 RETERR(isc_str_tobuffer(" (", target));
70 RETERR(isc_str_tobuffer(tctx->linebreak, target));
71 if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
72 if (tctx->width == 0) /* No splitting */
73 RETERR(isc_hex_totext(&sr, 0, "", target));
74 else
75 RETERR(isc_hex_totext(&sr, tctx->width - 2,
76 tctx->linebreak, target));
77 } else
78 RETERR(isc_str_tobuffer("[omitted]", target));
79 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
80 RETERR(isc_str_tobuffer(" )", target));
81 return (ISC_R_SUCCESS);
82 }
83
84 static inline isc_result_t
totext_ds(ARGS_TOTEXT)85 totext_ds(ARGS_TOTEXT) {
86
87 REQUIRE(rdata->type == dns_rdatatype_ds);
88
89 return (generic_totext_ds(rdata, tctx, target));
90 }
91
92 static inline isc_result_t
generic_fromwire_ds(ARGS_FROMWIRE)93 generic_fromwire_ds(ARGS_FROMWIRE) {
94 isc_region_t sr;
95
96 UNUSED(type);
97 UNUSED(rdclass);
98 UNUSED(dctx);
99 UNUSED(options);
100
101 isc_buffer_activeregion(source, &sr);
102
103 /*
104 * Check digest lengths if we know them.
105 */
106 if (sr.length < 4 ||
107 (sr.base[3] == DNS_DSDIGEST_SHA1 &&
108 sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
109 (sr.base[3] == DNS_DSDIGEST_SHA256 &&
110 sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
111 (sr.base[3] == DNS_DSDIGEST_SHA384 &&
112 sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
113 return (ISC_R_UNEXPECTEDEND);
114
115 /*
116 * Only copy digest lengths if we know them.
117 * If there is extra data dns_rdata_fromwire() will
118 * detect that.
119 */
120 if (sr.base[3] == DNS_DSDIGEST_SHA1)
121 sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
122 else if (sr.base[3] == DNS_DSDIGEST_SHA256)
123 sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
124 else if (sr.base[3] == DNS_DSDIGEST_SHA384)
125 sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
126
127 isc_buffer_forward(source, sr.length);
128 return (isc_mem_tobuffer(target, sr.base, sr.length));
129 }
130
131 static inline isc_result_t
fromwire_ds(ARGS_FROMWIRE)132 fromwire_ds(ARGS_FROMWIRE) {
133
134 REQUIRE(type == dns_rdatatype_ds);
135
136 return (generic_fromwire_ds(rdclass, type, source, dctx, options,
137 target));
138 }
139
140 static inline isc_result_t
towire_ds(ARGS_TOWIRE)141 towire_ds(ARGS_TOWIRE) {
142 isc_region_t sr;
143
144 REQUIRE(rdata->type == dns_rdatatype_ds);
145 REQUIRE(rdata->length != 0);
146
147 UNUSED(cctx);
148
149 dns_rdata_toregion(rdata, &sr);
150 return (isc_mem_tobuffer(target, sr.base, sr.length));
151 }
152
153 #endif /* RDATA_GENERIC_DS_43_C */
154