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