1 /*	$NetBSD: rrsig_46.c,v 1.7 2015/07/08 17:28:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007, 2009, 2011-2015  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 2003  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id */
21 
22 /* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
23 
24 /* RFC2535 */
25 
26 #ifndef RDATA_GENERIC_RRSIG_46_C
27 #define RDATA_GENERIC_RRSIG_46_C
28 
29 #define RRTYPE_RRSIG_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
30 
31 static inline isc_result_t
32 fromtext_rrsig(ARGS_FROMTEXT) {
33 	isc_token_t token;
34 	unsigned char c;
35 	long i;
36 	dns_rdatatype_t covered;
37 	char *e;
38 	isc_result_t result;
39 	dns_name_t name;
40 	isc_buffer_t buffer;
41 	isc_uint32_t time_signed, time_expire;
42 
43 	REQUIRE(type == 46);
44 
45 	UNUSED(type);
46 	UNUSED(rdclass);
47 	UNUSED(callbacks);
48 
49 	/*
50 	 * Type covered.
51 	 */
52 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
53 				      ISC_FALSE));
54 	result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion);
55 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
56 		i = strtol(DNS_AS_STR(token), &e, 10);
57 		if (i < 0 || i > 65535)
58 			RETTOK(ISC_R_RANGE);
59 		if (*e != 0)
60 			RETTOK(result);
61 		covered = (dns_rdatatype_t)i;
62 	}
63 	RETERR(uint16_tobuffer(covered, target));
64 
65 	/*
66 	 * Algorithm.
67 	 */
68 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
69 				      ISC_FALSE));
70 	RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
71 	RETERR(mem_tobuffer(target, &c, 1));
72 
73 	/*
74 	 * Labels.
75 	 */
76 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
77 				      ISC_FALSE));
78 	if (token.value.as_ulong > 0xffU)
79 		RETTOK(ISC_R_RANGE);
80 	c = (unsigned char)token.value.as_ulong;
81 	RETERR(mem_tobuffer(target, &c, 1));
82 
83 	/*
84 	 * Original ttl.
85 	 */
86 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
87 				      ISC_FALSE));
88 	RETERR(uint32_tobuffer(token.value.as_ulong, target));
89 
90 	/*
91 	 * Signature expiration.
92 	 */
93 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
94 				      ISC_FALSE));
95 	if (strlen(DNS_AS_STR(token)) <= 10U &&
96 	    *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') {
97 		char *end;
98 		unsigned long u;
99 		isc_uint64_t u64;
100 
101 		u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
102 		if (u == ULONG_MAX || *end != 0)
103 			RETTOK(DNS_R_SYNTAX);
104 		if (u64 > 0xffffffffUL)
105 			RETTOK(ISC_R_RANGE);
106 		time_expire = u;
107 	} else
108 		RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
109 	RETERR(uint32_tobuffer(time_expire, target));
110 
111 	/*
112 	 * Time signed.
113 	 */
114 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
115 				      ISC_FALSE));
116 	if (strlen(DNS_AS_STR(token)) <= 10U &&
117 	    *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') {
118 		char *end;
119 		unsigned long u;
120 		isc_uint64_t u64;
121 
122 		u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
123 		if (u == ULONG_MAX || *end != 0)
124 			RETTOK(DNS_R_SYNTAX);
125 		if (u64 > 0xffffffffUL)
126 			RETTOK(ISC_R_RANGE);
127 		time_signed = u;
128 	} else
129 		RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
130 	RETERR(uint32_tobuffer(time_signed, target));
131 
132 	/*
133 	 * Key footprint.
134 	 */
135 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
136 				      ISC_FALSE));
137 	RETERR(uint16_tobuffer(token.value.as_ulong, target));
138 
139 	/*
140 	 * Signer.
141 	 */
142 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
143 				      ISC_FALSE));
144 	dns_name_init(&name, NULL);
145 	buffer_fromregion(&buffer, &token.value.as_region);
146 	origin = (origin != NULL) ? origin : dns_rootname;
147 	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
148 
149 	/*
150 	 * Sig.
151 	 */
152 	return (isc_base64_tobuffer(lexer, target, -1));
153 }
154 
155 static inline isc_result_t
156 totext_rrsig(ARGS_TOTEXT) {
157 	isc_region_t sr;
158 	char buf[sizeof("4294967295")];
159 	dns_rdatatype_t covered;
160 	unsigned long ttl;
161 	unsigned long when;
162 	unsigned long exp;
163 	unsigned long foot;
164 	dns_name_t name;
165 
166 	REQUIRE(rdata->type == 46);
167 	REQUIRE(rdata->length != 0);
168 
169 	dns_rdata_toregion(rdata, &sr);
170 
171 	/*
172 	 * Type covered.
173 	 */
174 	covered = uint16_fromregion(&sr);
175 	isc_region_consume(&sr, 2);
176 	/*
177 	 * XXXAG We should have something like dns_rdatatype_isknown()
178 	 * that does the right thing with type 0.
179 	 */
180 	if (dns_rdatatype_isknown(covered) && covered != 0) {
181 		RETERR(dns_rdatatype_totext(covered, target));
182 	} else {
183 		sprintf(buf, "TYPE%u", covered);
184 		RETERR(str_totext(buf, target));
185 	}
186 	RETERR(str_totext(" ", target));
187 
188 	/*
189 	 * Algorithm.
190 	 */
191 	sprintf(buf, "%u", sr.base[0]);
192 	isc_region_consume(&sr, 1);
193 	RETERR(str_totext(buf, target));
194 	RETERR(str_totext(" ", target));
195 
196 	/*
197 	 * Labels.
198 	 */
199 	sprintf(buf, "%u", sr.base[0]);
200 	isc_region_consume(&sr, 1);
201 	RETERR(str_totext(buf, target));
202 	RETERR(str_totext(" ", target));
203 
204 	/*
205 	 * Ttl.
206 	 */
207 	ttl = uint32_fromregion(&sr);
208 	isc_region_consume(&sr, 4);
209 	sprintf(buf, "%lu", ttl);
210 	RETERR(str_totext(buf, target));
211 
212 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
213 		RETERR(str_totext(" (", target));
214 	RETERR(str_totext(tctx->linebreak, target));
215 
216 	/*
217 	 * Sig exp.
218 	 */
219 	exp = uint32_fromregion(&sr);
220 	isc_region_consume(&sr, 4);
221 	RETERR(dns_time32_totext(exp, target));
222 	RETERR(str_totext(" ", target));
223 
224 	/*
225 	 * Time signed.
226 	 */
227 	when = uint32_fromregion(&sr);
228 	isc_region_consume(&sr, 4);
229 	RETERR(dns_time32_totext(when, target));
230 	RETERR(str_totext(" ", target));
231 
232 	/*
233 	 * Footprint.
234 	 */
235 	foot = uint16_fromregion(&sr);
236 	isc_region_consume(&sr, 2);
237 	sprintf(buf, "%lu", foot);
238 	RETERR(str_totext(buf, target));
239 	RETERR(str_totext(" ", target));
240 
241 	/*
242 	 * Signer.
243 	 */
244 	dns_name_init(&name, NULL);
245 	dns_name_fromregion(&name, &sr);
246 	isc_region_consume(&sr, name_length(&name));
247 	RETERR(dns_name_totext(&name, ISC_FALSE, target));
248 
249 	/*
250 	 * Sig.
251 	 */
252 	RETERR(str_totext(tctx->linebreak, target));
253 	if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
254 		if (tctx->width == 0)   /* No splitting */
255 			RETERR(isc_base64_totext(&sr, 60, "", target));
256 		else
257 			RETERR(isc_base64_totext(&sr, tctx->width - 2,
258 						 tctx->linebreak, target));
259 	} else
260 		RETERR(str_totext("[omitted]", target));
261 
262 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
263 		RETERR(str_totext(" )", target));
264 
265 	return (ISC_R_SUCCESS);
266 }
267 
268 static inline isc_result_t
269 fromwire_rrsig(ARGS_FROMWIRE) {
270 	isc_region_t sr;
271 	dns_name_t name;
272 
273 	REQUIRE(type == 46);
274 
275 	UNUSED(type);
276 	UNUSED(rdclass);
277 
278 	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
279 
280 	isc_buffer_activeregion(source, &sr);
281 	/*
282 	 * type covered: 2
283 	 * algorithm: 1
284 	 * labels: 1
285 	 * original ttl: 4
286 	 * signature expiration: 4
287 	 * time signed: 4
288 	 * key footprint: 2
289 	 */
290 	if (sr.length < 18)
291 		return (ISC_R_UNEXPECTEDEND);
292 
293 	isc_buffer_forward(source, 18);
294 	RETERR(mem_tobuffer(target, sr.base, 18));
295 
296 	/*
297 	 * Signer.
298 	 */
299 	dns_name_init(&name, NULL);
300 	RETERR(dns_name_fromwire(&name, source, dctx, options, target));
301 
302 	/*
303 	 * Sig.
304 	 */
305 	isc_buffer_activeregion(source, &sr);
306 	isc_buffer_forward(source, sr.length);
307 	return (mem_tobuffer(target, sr.base, sr.length));
308 }
309 
310 static inline isc_result_t
311 towire_rrsig(ARGS_TOWIRE) {
312 	isc_region_t sr;
313 	dns_name_t name;
314 	dns_offsets_t offsets;
315 
316 	REQUIRE(rdata->type == 46);
317 	REQUIRE(rdata->length != 0);
318 
319 	dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
320 	dns_rdata_toregion(rdata, &sr);
321 	/*
322 	 * type covered: 2
323 	 * algorithm: 1
324 	 * labels: 1
325 	 * original ttl: 4
326 	 * signature expiration: 4
327 	 * time signed: 4
328 	 * key footprint: 2
329 	 */
330 	RETERR(mem_tobuffer(target, sr.base, 18));
331 	isc_region_consume(&sr, 18);
332 
333 	/*
334 	 * Signer.
335 	 */
336 	dns_name_init(&name, offsets);
337 	dns_name_fromregion(&name, &sr);
338 	isc_region_consume(&sr, name_length(&name));
339 	RETERR(dns_name_towire(&name, cctx, target));
340 
341 	/*
342 	 * Signature.
343 	 */
344 	return (mem_tobuffer(target, sr.base, sr.length));
345 }
346 
347 static inline int
348 compare_rrsig(ARGS_COMPARE) {
349 	isc_region_t r1;
350 	isc_region_t r2;
351 
352 	REQUIRE(rdata1->type == rdata2->type);
353 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
354 	REQUIRE(rdata1->type == 46);
355 	REQUIRE(rdata1->length != 0);
356 	REQUIRE(rdata2->length != 0);
357 
358 	dns_rdata_toregion(rdata1, &r1);
359 	dns_rdata_toregion(rdata2, &r2);
360 	return (isc_region_compare(&r1, &r2));
361 }
362 
363 static inline isc_result_t
364 fromstruct_rrsig(ARGS_FROMSTRUCT) {
365 	dns_rdata_rrsig_t *sig = source;
366 
367 	REQUIRE(type == 46);
368 	REQUIRE(source != NULL);
369 	REQUIRE(sig->common.rdtype == type);
370 	REQUIRE(sig->common.rdclass == rdclass);
371 	REQUIRE(sig->signature != NULL || sig->siglen == 0);
372 
373 	UNUSED(type);
374 	UNUSED(rdclass);
375 
376 	/*
377 	 * Type covered.
378 	 */
379 	RETERR(uint16_tobuffer(sig->covered, target));
380 
381 	/*
382 	 * Algorithm.
383 	 */
384 	RETERR(uint8_tobuffer(sig->algorithm, target));
385 
386 	/*
387 	 * Labels.
388 	 */
389 	RETERR(uint8_tobuffer(sig->labels, target));
390 
391 	/*
392 	 * Original TTL.
393 	 */
394 	RETERR(uint32_tobuffer(sig->originalttl, target));
395 
396 	/*
397 	 * Expire time.
398 	 */
399 	RETERR(uint32_tobuffer(sig->timeexpire, target));
400 
401 	/*
402 	 * Time signed.
403 	 */
404 	RETERR(uint32_tobuffer(sig->timesigned, target));
405 
406 	/*
407 	 * Key ID.
408 	 */
409 	RETERR(uint16_tobuffer(sig->keyid, target));
410 
411 	/*
412 	 * Signer name.
413 	 */
414 	RETERR(name_tobuffer(&sig->signer, target));
415 
416 	/*
417 	 * Signature.
418 	 */
419 	return (mem_tobuffer(target, sig->signature, sig->siglen));
420 }
421 
422 static inline isc_result_t
423 tostruct_rrsig(ARGS_TOSTRUCT) {
424 	isc_region_t sr;
425 	dns_rdata_rrsig_t *sig = target;
426 	dns_name_t signer;
427 
428 	REQUIRE(rdata->type == 46);
429 	REQUIRE(target != NULL);
430 	REQUIRE(rdata->length != 0);
431 
432 	sig->common.rdclass = rdata->rdclass;
433 	sig->common.rdtype = rdata->type;
434 	ISC_LINK_INIT(&sig->common, link);
435 
436 	dns_rdata_toregion(rdata, &sr);
437 
438 	/*
439 	 * Type covered.
440 	 */
441 	sig->covered = uint16_fromregion(&sr);
442 	isc_region_consume(&sr, 2);
443 
444 	/*
445 	 * Algorithm.
446 	 */
447 	sig->algorithm = uint8_fromregion(&sr);
448 	isc_region_consume(&sr, 1);
449 
450 	/*
451 	 * Labels.
452 	 */
453 	sig->labels = uint8_fromregion(&sr);
454 	isc_region_consume(&sr, 1);
455 
456 	/*
457 	 * Original TTL.
458 	 */
459 	sig->originalttl = uint32_fromregion(&sr);
460 	isc_region_consume(&sr, 4);
461 
462 	/*
463 	 * Expire time.
464 	 */
465 	sig->timeexpire = uint32_fromregion(&sr);
466 	isc_region_consume(&sr, 4);
467 
468 	/*
469 	 * Time signed.
470 	 */
471 	sig->timesigned = uint32_fromregion(&sr);
472 	isc_region_consume(&sr, 4);
473 
474 	/*
475 	 * Key ID.
476 	 */
477 	sig->keyid = uint16_fromregion(&sr);
478 	isc_region_consume(&sr, 2);
479 
480 	dns_name_init(&signer, NULL);
481 	dns_name_fromregion(&signer, &sr);
482 	dns_name_init(&sig->signer, NULL);
483 	RETERR(name_duporclone(&signer, mctx, &sig->signer));
484 	isc_region_consume(&sr, name_length(&sig->signer));
485 
486 	/*
487 	 * Signature.
488 	 */
489 	sig->siglen = sr.length;
490 	sig->signature = mem_maybedup(mctx, sr.base, sig->siglen);
491 	if (sig->signature == NULL)
492 		goto cleanup;
493 
494 
495 	sig->mctx = mctx;
496 	return (ISC_R_SUCCESS);
497 
498  cleanup:
499 	if (mctx != NULL)
500 		dns_name_free(&sig->signer, mctx);
501 	return (ISC_R_NOMEMORY);
502 }
503 
504 static inline void
505 freestruct_rrsig(ARGS_FREESTRUCT) {
506 	dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *) source;
507 
508 	REQUIRE(source != NULL);
509 	REQUIRE(sig->common.rdtype == 46);
510 
511 	if (sig->mctx == NULL)
512 		return;
513 
514 	dns_name_free(&sig->signer, sig->mctx);
515 	if (sig->signature != NULL)
516 		isc_mem_free(sig->mctx, sig->signature);
517 	sig->mctx = NULL;
518 }
519 
520 static inline isc_result_t
521 additionaldata_rrsig(ARGS_ADDLDATA) {
522 	REQUIRE(rdata->type == 46);
523 
524 	UNUSED(rdata);
525 	UNUSED(add);
526 	UNUSED(arg);
527 
528 	return (ISC_R_SUCCESS);
529 }
530 
531 static inline isc_result_t
532 digest_rrsig(ARGS_DIGEST) {
533 
534 	REQUIRE(rdata->type == 46);
535 
536 	UNUSED(rdata);
537 	UNUSED(digest);
538 	UNUSED(arg);
539 
540 	return (ISC_R_NOTIMPLEMENTED);
541 }
542 
543 static inline dns_rdatatype_t
544 covers_rrsig(dns_rdata_t *rdata) {
545 	dns_rdatatype_t type;
546 	isc_region_t r;
547 
548 	REQUIRE(rdata->type == 46);
549 
550 	dns_rdata_toregion(rdata, &r);
551 	type = uint16_fromregion(&r);
552 
553 	return (type);
554 }
555 
556 static inline isc_boolean_t
557 checkowner_rrsig(ARGS_CHECKOWNER) {
558 
559 	REQUIRE(type == 46);
560 
561 	UNUSED(name);
562 	UNUSED(type);
563 	UNUSED(rdclass);
564 	UNUSED(wildcard);
565 
566 	return (ISC_TRUE);
567 }
568 
569 static inline isc_boolean_t
570 checknames_rrsig(ARGS_CHECKNAMES) {
571 
572 	REQUIRE(rdata->type == 46);
573 
574 	UNUSED(rdata);
575 	UNUSED(owner);
576 	UNUSED(bad);
577 
578 	return (ISC_TRUE);
579 }
580 
581 static inline int
582 casecompare_rrsig(ARGS_COMPARE) {
583 	isc_region_t r1;
584 	isc_region_t r2;
585 	dns_name_t name1;
586 	dns_name_t name2;
587 	int order;
588 
589 	REQUIRE(rdata1->type == rdata2->type);
590 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
591 	REQUIRE(rdata1->type == 46);
592 	REQUIRE(rdata1->length != 0);
593 	REQUIRE(rdata2->length != 0);
594 
595 	dns_rdata_toregion(rdata1, &r1);
596 	dns_rdata_toregion(rdata2, &r2);
597 
598 	INSIST(r1.length > 18);
599 	INSIST(r2.length > 18);
600 	r1.length = 18;
601 	r2.length = 18;
602 	order = isc_region_compare(&r1, &r2);
603 	if (order != 0)
604 		return (order);
605 
606 	dns_name_init(&name1, NULL);
607 	dns_name_init(&name2, NULL);
608 	dns_rdata_toregion(rdata1, &r1);
609 	dns_rdata_toregion(rdata2, &r2);
610 	isc_region_consume(&r1, 18);
611 	isc_region_consume(&r2, 18);
612 	dns_name_fromregion(&name1, &r1);
613 	dns_name_fromregion(&name2, &r2);
614 	order = dns_name_rdatacompare(&name1, &name2);
615 	if (order != 0)
616 		return (order);
617 
618 	isc_region_consume(&r1, name_length(&name1));
619 	isc_region_consume(&r2, name_length(&name2));
620 
621 	return (isc_region_compare(&r1, &r2));
622 }
623 
624 #endif	/* RDATA_GENERIC_RRSIG_46_C */
625