1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /* RFC2538 */
15 
16 #ifndef RDATA_GENERIC_CERT_37_C
17 #define RDATA_GENERIC_CERT_37_C
18 
19 #define RRTYPE_CERT_ATTRIBUTES (0)
20 
21 static inline isc_result_t
fromtext_cert(ARGS_FROMTEXT)22 fromtext_cert(ARGS_FROMTEXT) {
23 	isc_token_t token;
24 	dns_secalg_t secalg;
25 	dns_cert_t cert;
26 
27 	REQUIRE(type == dns_rdatatype_cert);
28 
29 	UNUSED(type);
30 	UNUSED(rdclass);
31 	UNUSED(origin);
32 	UNUSED(options);
33 	UNUSED(callbacks);
34 
35 	/*
36 	 * Cert type.
37 	 */
38 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
39 				      false));
40 	RETTOK(dns_cert_fromtext(&cert, &token.value.as_textregion));
41 	RETERR(uint16_tobuffer(cert, target));
42 
43 	/*
44 	 * Key tag.
45 	 */
46 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
47 				      false));
48 	if (token.value.as_ulong > 0xffffU) {
49 		RETTOK(ISC_R_RANGE);
50 	}
51 	RETERR(uint16_tobuffer(token.value.as_ulong, target));
52 
53 	/*
54 	 * Algorithm.
55 	 */
56 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
57 				      false));
58 	RETTOK(dns_secalg_fromtext(&secalg, &token.value.as_textregion));
59 	RETERR(mem_tobuffer(target, &secalg, 1));
60 
61 	return (isc_base64_tobuffer(lexer, target, -2));
62 }
63 
64 static inline isc_result_t
totext_cert(ARGS_TOTEXT)65 totext_cert(ARGS_TOTEXT) {
66 	isc_region_t sr;
67 	char buf[sizeof("64000 ")];
68 	unsigned int n;
69 
70 	REQUIRE(rdata->type == dns_rdatatype_cert);
71 	REQUIRE(rdata->length != 0);
72 
73 	UNUSED(tctx);
74 
75 	dns_rdata_toregion(rdata, &sr);
76 
77 	/*
78 	 * Type.
79 	 */
80 	n = uint16_fromregion(&sr);
81 	isc_region_consume(&sr, 2);
82 	RETERR(dns_cert_totext((dns_cert_t)n, target));
83 	RETERR(str_totext(" ", target));
84 
85 	/*
86 	 * Key tag.
87 	 */
88 	n = uint16_fromregion(&sr);
89 	isc_region_consume(&sr, 2);
90 	snprintf(buf, sizeof(buf), "%u ", n);
91 	RETERR(str_totext(buf, target));
92 
93 	/*
94 	 * Algorithm.
95 	 */
96 	RETERR(dns_secalg_totext(sr.base[0], target));
97 	isc_region_consume(&sr, 1);
98 
99 	/*
100 	 * Cert.
101 	 */
102 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
103 		RETERR(str_totext(" (", target));
104 	}
105 	RETERR(str_totext(tctx->linebreak, target));
106 	if (tctx->width == 0) { /* No splitting */
107 		RETERR(isc_base64_totext(&sr, 60, "", target));
108 	} else {
109 		RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
110 					 target));
111 	}
112 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
113 		RETERR(str_totext(" )", target));
114 	}
115 	return (ISC_R_SUCCESS);
116 }
117 
118 static inline isc_result_t
fromwire_cert(ARGS_FROMWIRE)119 fromwire_cert(ARGS_FROMWIRE) {
120 	isc_region_t sr;
121 
122 	REQUIRE(type == dns_rdatatype_cert);
123 
124 	UNUSED(type);
125 	UNUSED(rdclass);
126 	UNUSED(dctx);
127 	UNUSED(options);
128 
129 	isc_buffer_activeregion(source, &sr);
130 	if (sr.length < 6) {
131 		return (ISC_R_UNEXPECTEDEND);
132 	}
133 
134 	isc_buffer_forward(source, sr.length);
135 	return (mem_tobuffer(target, sr.base, sr.length));
136 }
137 
138 static inline isc_result_t
towire_cert(ARGS_TOWIRE)139 towire_cert(ARGS_TOWIRE) {
140 	isc_region_t sr;
141 
142 	REQUIRE(rdata->type == dns_rdatatype_cert);
143 	REQUIRE(rdata->length != 0);
144 
145 	UNUSED(cctx);
146 
147 	dns_rdata_toregion(rdata, &sr);
148 	return (mem_tobuffer(target, sr.base, sr.length));
149 }
150 
151 static inline int
compare_cert(ARGS_COMPARE)152 compare_cert(ARGS_COMPARE) {
153 	isc_region_t r1;
154 	isc_region_t r2;
155 
156 	REQUIRE(rdata1->type == rdata2->type);
157 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
158 	REQUIRE(rdata1->type == dns_rdatatype_cert);
159 	REQUIRE(rdata1->length != 0);
160 	REQUIRE(rdata2->length != 0);
161 
162 	dns_rdata_toregion(rdata1, &r1);
163 	dns_rdata_toregion(rdata2, &r2);
164 	return (isc_region_compare(&r1, &r2));
165 }
166 
167 static inline isc_result_t
fromstruct_cert(ARGS_FROMSTRUCT)168 fromstruct_cert(ARGS_FROMSTRUCT) {
169 	dns_rdata_cert_t *cert = source;
170 
171 	REQUIRE(type == dns_rdatatype_cert);
172 	REQUIRE(cert != NULL);
173 	REQUIRE(cert->common.rdtype == type);
174 	REQUIRE(cert->common.rdclass == rdclass);
175 
176 	UNUSED(type);
177 	UNUSED(rdclass);
178 
179 	RETERR(uint16_tobuffer(cert->type, target));
180 	RETERR(uint16_tobuffer(cert->key_tag, target));
181 	RETERR(uint8_tobuffer(cert->algorithm, target));
182 
183 	return (mem_tobuffer(target, cert->certificate, cert->length));
184 }
185 
186 static inline isc_result_t
tostruct_cert(ARGS_TOSTRUCT)187 tostruct_cert(ARGS_TOSTRUCT) {
188 	dns_rdata_cert_t *cert = target;
189 	isc_region_t region;
190 
191 	REQUIRE(rdata->type == dns_rdatatype_cert);
192 	REQUIRE(cert != NULL);
193 	REQUIRE(rdata->length != 0);
194 
195 	cert->common.rdclass = rdata->rdclass;
196 	cert->common.rdtype = rdata->type;
197 	ISC_LINK_INIT(&cert->common, link);
198 
199 	dns_rdata_toregion(rdata, &region);
200 
201 	cert->type = uint16_fromregion(&region);
202 	isc_region_consume(&region, 2);
203 	cert->key_tag = uint16_fromregion(&region);
204 	isc_region_consume(&region, 2);
205 	cert->algorithm = uint8_fromregion(&region);
206 	isc_region_consume(&region, 1);
207 	cert->length = region.length;
208 
209 	cert->certificate = mem_maybedup(mctx, region.base, region.length);
210 	if (cert->certificate == NULL) {
211 		return (ISC_R_NOMEMORY);
212 	}
213 
214 	cert->mctx = mctx;
215 	return (ISC_R_SUCCESS);
216 }
217 
218 static inline void
freestruct_cert(ARGS_FREESTRUCT)219 freestruct_cert(ARGS_FREESTRUCT) {
220 	dns_rdata_cert_t *cert = source;
221 
222 	REQUIRE(cert != NULL);
223 	REQUIRE(cert->common.rdtype == dns_rdatatype_cert);
224 
225 	if (cert->mctx == NULL) {
226 		return;
227 	}
228 
229 	if (cert->certificate != NULL) {
230 		isc_mem_free(cert->mctx, cert->certificate);
231 	}
232 	cert->mctx = NULL;
233 }
234 
235 static inline isc_result_t
additionaldata_cert(ARGS_ADDLDATA)236 additionaldata_cert(ARGS_ADDLDATA) {
237 	REQUIRE(rdata->type == dns_rdatatype_cert);
238 
239 	UNUSED(rdata);
240 	UNUSED(add);
241 	UNUSED(arg);
242 
243 	return (ISC_R_SUCCESS);
244 }
245 
246 static inline isc_result_t
digest_cert(ARGS_DIGEST)247 digest_cert(ARGS_DIGEST) {
248 	isc_region_t r;
249 
250 	REQUIRE(rdata->type == dns_rdatatype_cert);
251 
252 	dns_rdata_toregion(rdata, &r);
253 
254 	return ((digest)(arg, &r));
255 }
256 
257 static inline bool
checkowner_cert(ARGS_CHECKOWNER)258 checkowner_cert(ARGS_CHECKOWNER) {
259 	REQUIRE(type == dns_rdatatype_cert);
260 
261 	UNUSED(name);
262 	UNUSED(type);
263 	UNUSED(rdclass);
264 	UNUSED(wildcard);
265 
266 	return (true);
267 }
268 
269 static inline bool
checknames_cert(ARGS_CHECKNAMES)270 checknames_cert(ARGS_CHECKNAMES) {
271 	REQUIRE(rdata->type == dns_rdatatype_cert);
272 
273 	UNUSED(rdata);
274 	UNUSED(owner);
275 	UNUSED(bad);
276 
277 	return (true);
278 }
279 
280 static inline int
casecompare_cert(ARGS_COMPARE)281 casecompare_cert(ARGS_COMPARE) {
282 	return (compare_cert(rdata1, rdata2));
283 }
284 #endif /* RDATA_GENERIC_CERT_37_C */
285