xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/sshfp_44.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: sshfp_44.c,v 1.11 2025/01/26 16:25:33 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 /* RFC 4255 */
17 
18 #ifndef RDATA_GENERIC_SSHFP_44_C
19 #define RDATA_GENERIC_SSHFP_44_C
20 
21 #define RRTYPE_SSHFP_ATTRIBUTES (0)
22 
23 static isc_result_t
24 fromtext_sshfp(ARGS_FROMTEXT) {
25 	isc_token_t token;
26 	int len = -1;
27 
28 	REQUIRE(type == dns_rdatatype_sshfp);
29 
30 	UNUSED(type);
31 	UNUSED(rdclass);
32 	UNUSED(origin);
33 	UNUSED(options);
34 	UNUSED(callbacks);
35 
36 	/*
37 	 * Algorithm.
38 	 */
39 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
40 				      false));
41 	if (token.value.as_ulong > 0xffU) {
42 		RETTOK(ISC_R_RANGE);
43 	}
44 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
45 
46 	/*
47 	 * Digest type.
48 	 */
49 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
50 				      false));
51 	if (token.value.as_ulong > 0xffU) {
52 		RETTOK(ISC_R_RANGE);
53 	}
54 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
55 
56 	/*
57 	 * Enforce known digest lengths.
58 	 */
59 	switch (token.value.as_ulong) {
60 	case 1:
61 		len = ISC_SHA1_DIGESTLENGTH;
62 		break;
63 	case 2:
64 		len = ISC_SHA256_DIGESTLENGTH;
65 		break;
66 	default:
67 		break;
68 	}
69 
70 	/*
71 	 * Digest.
72 	 */
73 	return isc_hex_tobuffer(lexer, target, len);
74 }
75 
76 static isc_result_t
77 totext_sshfp(ARGS_TOTEXT) {
78 	isc_region_t sr;
79 	char buf[sizeof("64000 ")];
80 	unsigned int n;
81 
82 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
83 	REQUIRE(rdata->length != 0);
84 
85 	UNUSED(tctx);
86 
87 	dns_rdata_toregion(rdata, &sr);
88 
89 	/*
90 	 * Algorithm.
91 	 */
92 	n = uint8_fromregion(&sr);
93 	isc_region_consume(&sr, 1);
94 	snprintf(buf, sizeof(buf), "%u ", n);
95 	RETERR(str_totext(buf, target));
96 
97 	/*
98 	 * Digest type.
99 	 */
100 	n = uint8_fromregion(&sr);
101 	isc_region_consume(&sr, 1);
102 	snprintf(buf, sizeof(buf), "%u", n);
103 	RETERR(str_totext(buf, target));
104 
105 	if (sr.length == 0U) {
106 		return ISC_R_SUCCESS;
107 	}
108 
109 	/*
110 	 * Digest.
111 	 */
112 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
113 		RETERR(str_totext(" (", target));
114 	}
115 	RETERR(str_totext(tctx->linebreak, target));
116 	if (tctx->width == 0) { /* No splitting */
117 		RETERR(isc_hex_totext(&sr, 0, "", target));
118 	} else {
119 		RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak,
120 				      target));
121 	}
122 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
123 		RETERR(str_totext(" )", target));
124 	}
125 	return ISC_R_SUCCESS;
126 }
127 
128 static isc_result_t
129 fromwire_sshfp(ARGS_FROMWIRE) {
130 	isc_region_t sr;
131 
132 	REQUIRE(type == dns_rdatatype_sshfp);
133 
134 	UNUSED(type);
135 	UNUSED(rdclass);
136 	UNUSED(dctx);
137 
138 	isc_buffer_activeregion(source, &sr);
139 	if (sr.length < 2) {
140 		return ISC_R_UNEXPECTEDEND;
141 	}
142 
143 	if ((sr.base[1] == 1 && sr.length != ISC_SHA1_DIGESTLENGTH + 2) ||
144 	    (sr.base[1] == 2 && sr.length != ISC_SHA256_DIGESTLENGTH + 2))
145 	{
146 		return DNS_R_FORMERR;
147 	}
148 
149 	isc_buffer_forward(source, sr.length);
150 	return mem_tobuffer(target, sr.base, sr.length);
151 }
152 
153 static isc_result_t
154 towire_sshfp(ARGS_TOWIRE) {
155 	isc_region_t sr;
156 
157 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
158 	REQUIRE(rdata->length != 0);
159 
160 	UNUSED(cctx);
161 
162 	dns_rdata_toregion(rdata, &sr);
163 	return mem_tobuffer(target, sr.base, sr.length);
164 }
165 
166 static int
167 compare_sshfp(ARGS_COMPARE) {
168 	isc_region_t r1;
169 	isc_region_t r2;
170 
171 	REQUIRE(rdata1->type == rdata2->type);
172 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
173 	REQUIRE(rdata1->type == dns_rdatatype_sshfp);
174 	REQUIRE(rdata1->length != 0);
175 	REQUIRE(rdata2->length != 0);
176 
177 	dns_rdata_toregion(rdata1, &r1);
178 	dns_rdata_toregion(rdata2, &r2);
179 	return isc_region_compare(&r1, &r2);
180 }
181 
182 static isc_result_t
183 fromstruct_sshfp(ARGS_FROMSTRUCT) {
184 	dns_rdata_sshfp_t *sshfp = source;
185 
186 	REQUIRE(type == dns_rdatatype_sshfp);
187 	REQUIRE(sshfp != NULL);
188 	REQUIRE(sshfp->common.rdtype == type);
189 	REQUIRE(sshfp->common.rdclass == rdclass);
190 
191 	UNUSED(type);
192 	UNUSED(rdclass);
193 
194 	RETERR(uint8_tobuffer(sshfp->algorithm, target));
195 	RETERR(uint8_tobuffer(sshfp->digest_type, target));
196 
197 	return mem_tobuffer(target, sshfp->digest, sshfp->length);
198 }
199 
200 static isc_result_t
201 tostruct_sshfp(ARGS_TOSTRUCT) {
202 	dns_rdata_sshfp_t *sshfp = target;
203 	isc_region_t region;
204 
205 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
206 	REQUIRE(sshfp != NULL);
207 	REQUIRE(rdata->length != 0);
208 
209 	sshfp->common.rdclass = rdata->rdclass;
210 	sshfp->common.rdtype = rdata->type;
211 	ISC_LINK_INIT(&sshfp->common, link);
212 
213 	dns_rdata_toregion(rdata, &region);
214 
215 	sshfp->algorithm = uint8_fromregion(&region);
216 	isc_region_consume(&region, 1);
217 	sshfp->digest_type = uint8_fromregion(&region);
218 	isc_region_consume(&region, 1);
219 	sshfp->length = region.length;
220 
221 	sshfp->digest = mem_maybedup(mctx, region.base, region.length);
222 	sshfp->mctx = mctx;
223 	return ISC_R_SUCCESS;
224 }
225 
226 static void
227 freestruct_sshfp(ARGS_FREESTRUCT) {
228 	dns_rdata_sshfp_t *sshfp = source;
229 
230 	REQUIRE(sshfp != NULL);
231 	REQUIRE(sshfp->common.rdtype == dns_rdatatype_sshfp);
232 
233 	if (sshfp->mctx == NULL) {
234 		return;
235 	}
236 
237 	if (sshfp->digest != NULL) {
238 		isc_mem_free(sshfp->mctx, sshfp->digest);
239 	}
240 	sshfp->mctx = NULL;
241 }
242 
243 static isc_result_t
244 additionaldata_sshfp(ARGS_ADDLDATA) {
245 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
246 
247 	UNUSED(rdata);
248 	UNUSED(owner);
249 	UNUSED(add);
250 	UNUSED(arg);
251 
252 	return ISC_R_SUCCESS;
253 }
254 
255 static isc_result_t
256 digest_sshfp(ARGS_DIGEST) {
257 	isc_region_t r;
258 
259 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
260 
261 	dns_rdata_toregion(rdata, &r);
262 
263 	return (digest)(arg, &r);
264 }
265 
266 static bool
267 checkowner_sshfp(ARGS_CHECKOWNER) {
268 	REQUIRE(type == dns_rdatatype_sshfp);
269 
270 	UNUSED(name);
271 	UNUSED(type);
272 	UNUSED(rdclass);
273 	UNUSED(wildcard);
274 
275 	return true;
276 }
277 
278 static bool
279 checknames_sshfp(ARGS_CHECKNAMES) {
280 	REQUIRE(rdata->type == dns_rdatatype_sshfp);
281 
282 	UNUSED(rdata);
283 	UNUSED(owner);
284 	UNUSED(bad);
285 
286 	return true;
287 }
288 
289 static int
290 casecompare_sshfp(ARGS_COMPARE) {
291 	return compare_sshfp(rdata1, rdata2);
292 }
293 
294 #endif /* RDATA_GENERIC_SSHFP_44_C */
295