xref: /openbsd-src/lib/libutil/ber.c (revision 7350f337b9e3eb4461d99580e625c7ef148d107c)
1 /*	$OpenBSD: ber.c,v 1.9 2019/06/01 19:40:05 rob Exp $ */
2 
3 /*
4  * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
5  * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 
23 #include <errno.h>
24 #include <limits.h>
25 #include <stdlib.h>
26 #include <err.h>	/* XXX for debug output */
27 #include <stdio.h>	/* XXX for debug output */
28 #include <string.h>
29 #include <unistd.h>
30 #include <stdarg.h>
31 
32 #include "ber.h"
33 
34 #define BER_TYPE_CONSTRUCTED	0x20	/* otherwise primitive */
35 #define BER_TYPE_SINGLE_MAX	30
36 #define BER_TAG_MASK		0x1f
37 #define BER_TAG_MORE		0x80	/* more subsequent octets */
38 #define BER_TAG_TYPE_MASK	0x7f
39 #define BER_CLASS_SHIFT		6
40 
41 static int	ber_dump_element(struct ber *ber, struct ber_element *root);
42 static void	ber_dump_header(struct ber *ber, struct ber_element *root);
43 static void	ber_putc(struct ber *ber, u_char c);
44 static void	ber_write(struct ber *ber, void *buf, size_t len);
45 static ssize_t	get_id(struct ber *b, unsigned int *tag, int *class,
46     int *cstruct);
47 static ssize_t	get_len(struct ber *b, ssize_t *len);
48 static ssize_t	ber_read_element(struct ber *ber, struct ber_element *elm);
49 static ssize_t	ber_getc(struct ber *b, u_char *c);
50 static ssize_t	ber_read(struct ber *ber, void *buf, size_t len);
51 
52 #ifdef DEBUG
53 #define DPRINTF(...)	printf(__VA_ARGS__)
54 #else
55 #define DPRINTF(...)	do { } while (0)
56 #endif
57 
58 struct ber_element *
59 ber_get_element(unsigned int encoding)
60 {
61 	struct ber_element *elm;
62 
63 	if ((elm = calloc(1, sizeof(*elm))) == NULL)
64 		return NULL;
65 
66 	elm->be_encoding = encoding;
67 	ber_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
68 
69 	return elm;
70 }
71 
72 void
73 ber_set_header(struct ber_element *elm, int class, unsigned int type)
74 {
75 	elm->be_class = class & BER_CLASS_MASK;
76 	if (type == BER_TYPE_DEFAULT)
77 		type = elm->be_encoding;
78 	elm->be_type = type;
79 }
80 
81 void
82 ber_link_elements(struct ber_element *prev, struct ber_element *elm)
83 {
84 	if (prev != NULL) {
85 		if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
86 		    prev->be_encoding == BER_TYPE_SET) &&
87 		    prev->be_sub == NULL)
88 			prev->be_sub = elm;
89 		else
90 			prev->be_next = elm;
91 	}
92 }
93 
94 struct ber_element *
95 ber_unlink_elements(struct ber_element *prev)
96 {
97 	struct ber_element *elm;
98 
99 	if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
100 	    prev->be_encoding == BER_TYPE_SET) &&
101 	    prev->be_sub != NULL) {
102 		elm = prev->be_sub;
103 		prev->be_sub = NULL;
104 	} else {
105 		elm = prev->be_next;
106 		prev->be_next = NULL;
107 	}
108 
109 	return (elm);
110 }
111 
112 void
113 ber_replace_elements(struct ber_element *prev, struct ber_element *new)
114 {
115 	struct ber_element *ber, *next;
116 
117 	ber = ber_unlink_elements(prev);
118 	next = ber_unlink_elements(ber);
119 	ber_link_elements(new, next);
120 	ber_link_elements(prev, new);
121 
122 	/* cleanup old element */
123 	ber_free_elements(ber);
124 }
125 
126 struct ber_element *
127 ber_add_sequence(struct ber_element *prev)
128 {
129 	struct ber_element *elm;
130 
131 	if ((elm = ber_get_element(BER_TYPE_SEQUENCE)) == NULL)
132 		return NULL;
133 
134 	ber_link_elements(prev, elm);
135 
136 	return elm;
137 }
138 
139 struct ber_element *
140 ber_add_set(struct ber_element *prev)
141 {
142 	struct ber_element *elm;
143 
144 	if ((elm = ber_get_element(BER_TYPE_SET)) == NULL)
145 		return NULL;
146 
147 	ber_link_elements(prev, elm);
148 
149 	return elm;
150 }
151 
152 struct ber_element *
153 ber_add_enumerated(struct ber_element *prev, long long val)
154 {
155 	struct ber_element *elm;
156 	u_int i, len = 0;
157 	u_char cur, last = 0;
158 
159 	if ((elm = ber_get_element(BER_TYPE_ENUMERATED)) == NULL)
160 		return NULL;
161 
162 	elm->be_numeric = val;
163 
164 	for (i = 0; i < sizeof(long long); i++) {
165 		cur = val & 0xff;
166 		if (cur != 0 && cur != 0xff)
167 			len = i;
168 		if ((cur == 0 && last & 0x80) ||
169 		    (cur == 0xff && (last & 0x80) == 0))
170 			len = i;
171 		val >>= 8;
172 		last = cur;
173 	}
174 	elm->be_len = len + 1;
175 
176 	ber_link_elements(prev, elm);
177 
178 	return elm;
179 }
180 
181 struct ber_element *
182 ber_add_integer(struct ber_element *prev, long long val)
183 {
184 	struct ber_element *elm;
185 	u_int i, len = 0;
186 	u_char cur, last = 0;
187 
188 	if ((elm = ber_get_element(BER_TYPE_INTEGER)) == NULL)
189 		return NULL;
190 
191 	elm->be_numeric = val;
192 
193 	for (i = 0; i < sizeof(long long); i++) {
194 		cur = val & 0xff;
195 		if (cur != 0 && cur != 0xff)
196 			len = i;
197 		if ((cur == 0 && last & 0x80) ||
198 		    (cur == 0xff && (last & 0x80) == 0))
199 			len = i;
200 		val >>= 8;
201 		last = cur;
202 	}
203 	elm->be_len = len + 1;
204 
205 	ber_link_elements(prev, elm);
206 
207 	return elm;
208 }
209 
210 int
211 ber_get_integer(struct ber_element *elm, long long *n)
212 {
213 	if (elm->be_encoding != BER_TYPE_INTEGER)
214 		return -1;
215 
216 	*n = elm->be_numeric;
217 	return 0;
218 }
219 
220 int
221 ber_get_enumerated(struct ber_element *elm, long long *n)
222 {
223 	if (elm->be_encoding != BER_TYPE_ENUMERATED)
224 		return -1;
225 
226 	*n = elm->be_numeric;
227 	return 0;
228 }
229 
230 struct ber_element *
231 ber_add_boolean(struct ber_element *prev, int bool)
232 {
233 	struct ber_element *elm;
234 
235 	if ((elm = ber_get_element(BER_TYPE_BOOLEAN)) == NULL)
236 		return NULL;
237 
238 	elm->be_numeric = bool ? 0xff : 0;
239 	elm->be_len = 1;
240 
241 	ber_link_elements(prev, elm);
242 
243 	return elm;
244 }
245 
246 int
247 ber_get_boolean(struct ber_element *elm, int *b)
248 {
249 	if (elm->be_encoding != BER_TYPE_BOOLEAN)
250 		return -1;
251 
252 	*b = !(elm->be_numeric == 0);
253 	return 0;
254 }
255 
256 struct ber_element *
257 ber_add_string(struct ber_element *prev, const char *string)
258 {
259 	return ber_add_nstring(prev, string, strlen(string));
260 }
261 
262 struct ber_element *
263 ber_add_nstring(struct ber_element *prev, const char *string0, size_t len)
264 {
265 	struct ber_element *elm;
266 	char *string;
267 
268 	if ((string = calloc(1, len + 1)) == NULL)
269 		return NULL;
270 	if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) {
271 		free(string);
272 		return NULL;
273 	}
274 
275 	bcopy(string0, string, len);
276 	elm->be_val = string;
277 	elm->be_len = len;
278 	elm->be_free = 1;		/* free string on cleanup */
279 
280 	ber_link_elements(prev, elm);
281 
282 	return elm;
283 }
284 
285 struct ber_element *
286 ber_add_ostring(struct ber_element *prev, struct ber_octetstring *s)
287 {
288 	return ber_add_nstring(prev, s->ostr_val, s->ostr_len);
289 }
290 
291 int
292 ber_get_string(struct ber_element *elm, char **s)
293 {
294 	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
295 		return -1;
296 	/* XXX some components use getstring on binary data containing \0 */
297 #if 0
298 	if (memchr(elm->be_val, '\0', elm->be_len) != NULL)
299 		return -1;
300 #endif
301 
302 	*s = elm->be_val;
303 	return 0;
304 }
305 
306 int
307 ber_get_nstring(struct ber_element *elm, void **p, size_t *len)
308 {
309 	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
310 		return -1;
311 
312 	*p = elm->be_val;
313 	*len = elm->be_len;
314 	return 0;
315 }
316 
317 int
318 ber_get_ostring(struct ber_element *elm, struct ber_octetstring *s)
319 {
320 	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
321 		return -1;
322 
323 	s->ostr_val = elm->be_val;
324 	s->ostr_len = elm->be_len;
325 	return 0;
326 }
327 
328 struct ber_element *
329 ber_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
330 {
331 	struct ber_element *elm;
332 	void *v;
333 
334 	if ((v = calloc(1, len)) == NULL)
335 		return NULL;
336 	if ((elm = ber_get_element(BER_TYPE_BITSTRING)) == NULL) {
337 		free(v);
338 		return NULL;
339 	}
340 
341 	bcopy(v0, v, len);
342 	elm->be_val = v;
343 	elm->be_len = len;
344 	elm->be_free = 1;		/* free string on cleanup */
345 
346 	ber_link_elements(prev, elm);
347 
348 	return elm;
349 }
350 
351 int
352 ber_get_bitstring(struct ber_element *elm, void **v, size_t *len)
353 {
354 	if (elm->be_encoding != BER_TYPE_BITSTRING)
355 		return -1;
356 
357 	*v = elm->be_val;
358 	*len = elm->be_len;
359 	return 0;
360 }
361 
362 struct ber_element *
363 ber_add_null(struct ber_element *prev)
364 {
365 	struct ber_element *elm;
366 
367 	if ((elm = ber_get_element(BER_TYPE_NULL)) == NULL)
368 		return NULL;
369 
370 	ber_link_elements(prev, elm);
371 
372 	return elm;
373 }
374 
375 int
376 ber_get_null(struct ber_element *elm)
377 {
378 	if (elm->be_encoding != BER_TYPE_NULL)
379 		return -1;
380 
381 	return 0;
382 }
383 
384 struct ber_element *
385 ber_add_eoc(struct ber_element *prev)
386 {
387 	struct ber_element *elm;
388 
389 	if ((elm = ber_get_element(BER_TYPE_EOC)) == NULL)
390 		return NULL;
391 
392 	ber_link_elements(prev, elm);
393 
394 	return elm;
395 }
396 
397 int
398 ber_get_eoc(struct ber_element *elm)
399 {
400 	if (elm->be_encoding != BER_TYPE_EOC)
401 		return -1;
402 
403 	return 0;
404 }
405 
406 size_t
407 ber_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
408 {
409 	u_int32_t	 v;
410 	u_int		 i, j = 0, k;
411 
412 	if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
413 	    o->bo_id[0] > 2 || o->bo_id[1] > 40)
414 		return (0);
415 
416 	v = (o->bo_id[0] * 40) + o->bo_id[1];
417 	for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
418 		for (k = 28; k >= 7; k -= 7) {
419 			if (v >= (u_int)(1 << k)) {
420 				if (len)
421 					buf[j] = v >> k | BER_TAG_MORE;
422 				j++;
423 			}
424 		}
425 		if (len)
426 			buf[j] = v & BER_TAG_TYPE_MASK;
427 		j++;
428 	}
429 
430 	return (j);
431 }
432 
433 int
434 ber_string2oid(const char *oidstr, struct ber_oid *o)
435 {
436 	char			*sp, *p, str[BUFSIZ];
437 	const char		*errstr;
438 
439 	if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
440 		return (-1);
441 	memset(o, 0, sizeof(*o));
442 
443 	/* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
444 	for (p = sp = str; p != NULL; sp = p) {
445 		if ((p = strpbrk(p, "._-")) != NULL)
446 			*p++ = '\0';
447 		o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
448 		if (errstr || o->bo_n > BER_MAX_OID_LEN)
449 			return (-1);
450 	}
451 
452 	return (0);
453 }
454 
455 int
456 ber_oid_cmp(struct ber_oid *a, struct ber_oid *b)
457 {
458 	size_t	 i;
459 	for (i = 0; i < BER_MAX_OID_LEN; i++) {
460 		if (a->bo_id[i] != 0) {
461 			if (a->bo_id[i] == b->bo_id[i])
462 				continue;
463 			else if (a->bo_id[i] < b->bo_id[i]) {
464 				/* b is a successor of a */
465 				return (1);
466 			} else {
467 				/* b is a predecessor of a */
468 				return (-1);
469 			}
470 		} else if (b->bo_id[i] != 0) {
471 			/* b is larger, but a child of a */
472 			return (2);
473 		} else
474 			break;
475 	}
476 
477 	/* b and a are identical */
478 	return (0);
479 }
480 
481 struct ber_element *
482 ber_add_oid(struct ber_element *prev, struct ber_oid *o)
483 {
484 	struct ber_element	*elm;
485 	u_int8_t		*buf;
486 	size_t			 len;
487 
488 	if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL)
489 		return (NULL);
490 
491 	if ((len = ber_oid2ber(o, NULL, 0)) == 0)
492 		goto fail;
493 
494 	if ((buf = calloc(1, len)) == NULL)
495 		goto fail;
496 
497 	elm->be_val = buf;
498 	elm->be_len = len;
499 	elm->be_free = 1;
500 
501 	if (ber_oid2ber(o, buf, len) != len)
502 		goto fail;
503 
504 	ber_link_elements(prev, elm);
505 
506 	return (elm);
507 
508  fail:
509 	ber_free_elements(elm);
510 	return (NULL);
511 }
512 
513 struct ber_element *
514 ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
515 {
516 	struct ber_oid		 no;
517 
518 	if (n > BER_MAX_OID_LEN)
519 		return (NULL);
520 	no.bo_n = n;
521 	bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
522 
523 	return (ber_add_oid(prev, &no));
524 }
525 
526 struct ber_element *
527 ber_add_oidstring(struct ber_element *prev, const char *oidstr)
528 {
529 	struct ber_oid		 o;
530 
531 	if (ber_string2oid(oidstr, &o) == -1)
532 		return (NULL);
533 
534 	return (ber_add_oid(prev, &o));
535 }
536 
537 int
538 ber_get_oid(struct ber_element *elm, struct ber_oid *o)
539 {
540 	u_int8_t	*buf;
541 	size_t		 len, i = 0, j = 0;
542 
543 	if (elm->be_encoding != BER_TYPE_OBJECT)
544 		return (-1);
545 
546 	buf = elm->be_val;
547 	len = elm->be_len;
548 
549 	if (!buf[i])
550 		return (-1);
551 
552 	memset(o, 0, sizeof(*o));
553 	o->bo_id[j++] = buf[i] / 40;
554 	o->bo_id[j++] = buf[i++] % 40;
555 	for (; i < len && j < BER_MAX_OID_LEN; i++) {
556 		o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
557 		if (buf[i] & 0x80)
558 			continue;
559 		j++;
560 	}
561 	o->bo_n = j;
562 
563 	return (0);
564 }
565 
566 struct ber_element *
567 ber_printf_elements(struct ber_element *ber, char *fmt, ...)
568 {
569 	va_list			 ap;
570 	int			 d, class;
571 	size_t			 len;
572 	unsigned int		 type;
573 	long long		 i;
574 	char			*s;
575 	void			*p;
576 	struct ber_oid		*o;
577 	struct ber_element	*sub = ber, *e;
578 
579 	va_start(ap, fmt);
580 	while (*fmt) {
581 		switch (*fmt++) {
582 		case 'B':
583 			p = va_arg(ap, void *);
584 			len = va_arg(ap, size_t);
585 			if ((ber = ber_add_bitstring(ber, p, len)) == NULL)
586 				goto fail;
587 			break;
588 		case 'b':
589 			d = va_arg(ap, int);
590 			if ((ber = ber_add_boolean(ber, d)) == NULL)
591 				goto fail;
592 			break;
593 		case 'd':
594 			d = va_arg(ap, int);
595 			if ((ber = ber_add_integer(ber, d)) == NULL)
596 				goto fail;
597 			break;
598 		case 'e':
599 			e = va_arg(ap, struct ber_element *);
600 			ber_link_elements(ber, e);
601 			break;
602 		case 'E':
603 			i = va_arg(ap, long long);
604 			if ((ber = ber_add_enumerated(ber, i)) == NULL)
605 				goto fail;
606 			break;
607 		case 'i':
608 			i = va_arg(ap, long long);
609 			if ((ber = ber_add_integer(ber, i)) == NULL)
610 				goto fail;
611 			break;
612 		case 'O':
613 			o = va_arg(ap, struct ber_oid *);
614 			if ((ber = ber_add_oid(ber, o)) == NULL)
615 				goto fail;
616 			break;
617 		case 'o':
618 			s = va_arg(ap, char *);
619 			if ((ber = ber_add_oidstring(ber, s)) == NULL)
620 				goto fail;
621 			break;
622 		case 's':
623 			s = va_arg(ap, char *);
624 			if ((ber = ber_add_string(ber, s)) == NULL)
625 				goto fail;
626 			break;
627 		case 't':
628 			class = va_arg(ap, int);
629 			type = va_arg(ap, unsigned int);
630 			ber_set_header(ber, class, type);
631 			break;
632 		case 'x':
633 			s = va_arg(ap, char *);
634 			len = va_arg(ap, size_t);
635 			if ((ber = ber_add_nstring(ber, s, len)) == NULL)
636 				goto fail;
637 			break;
638 		case '0':
639 			if ((ber = ber_add_null(ber)) == NULL)
640 				goto fail;
641 			break;
642 		case '{':
643 			if ((ber = sub = ber_add_sequence(ber)) == NULL)
644 				goto fail;
645 			break;
646 		case '(':
647 			if ((ber = sub = ber_add_set(ber)) == NULL)
648 				goto fail;
649 			break;
650 		case '}':
651 		case ')':
652 			ber = sub;
653 			break;
654 		case '.':
655 			if ((e = ber_add_eoc(ber)) == NULL)
656 				goto fail;
657 			ber = e;
658 			break;
659 		default:
660 			break;
661 		}
662 	}
663 	va_end(ap);
664 
665 	return (ber);
666  fail:
667 	ber_free_elements(ber);
668 	return (NULL);
669 }
670 
671 int
672 ber_scanf_elements(struct ber_element *ber, char *fmt, ...)
673 {
674 #define _MAX_SEQ		 128
675 	va_list			 ap;
676 	int			*d, level = -1;
677 	unsigned int		*t;
678 	long long		*i, l;
679 	void			**ptr;
680 	size_t			*len, ret = 0, n = strlen(fmt);
681 	char			**s;
682 	off_t			*pos;
683 	struct ber_oid		*o;
684 	struct ber_element	*parent[_MAX_SEQ], **e;
685 
686 	memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
687 
688 	va_start(ap, fmt);
689 	while (*fmt) {
690 		switch (*fmt++) {
691 		case 'B':
692 			ptr = va_arg(ap, void **);
693 			len = va_arg(ap, size_t *);
694 			if (ber_get_bitstring(ber, ptr, len) == -1)
695 				goto fail;
696 			ret++;
697 			break;
698 		case 'b':
699 			d = va_arg(ap, int *);
700 			if (ber_get_boolean(ber, d) == -1)
701 				goto fail;
702 			ret++;
703 			break;
704 		case 'd':
705 			d = va_arg(ap, int *);
706 			if (ber_get_integer(ber, &l) == -1)
707 				goto fail;
708 			*d = l;
709 			ret++;
710 			break;
711 		case 'e':
712 			e = va_arg(ap, struct ber_element **);
713 			*e = ber;
714 			ret++;
715 			continue;
716 		case 'E':
717 			i = va_arg(ap, long long *);
718 			if (ber_get_enumerated(ber, i) == -1)
719 				goto fail;
720 			ret++;
721 			break;
722 		case 'i':
723 			i = va_arg(ap, long long *);
724 			if (ber_get_integer(ber, i) == -1)
725 				goto fail;
726 			ret++;
727 			break;
728 		case 'o':
729 			o = va_arg(ap, struct ber_oid *);
730 			if (ber_get_oid(ber, o) == -1)
731 				goto fail;
732 			ret++;
733 			break;
734 		case 'S':
735 			ret++;
736 			break;
737 		case 's':
738 			s = va_arg(ap, char **);
739 			if (ber_get_string(ber, s) == -1)
740 				goto fail;
741 			ret++;
742 			break;
743 		case 't':
744 			d = va_arg(ap, int *);
745 			t = va_arg(ap, unsigned int *);
746 			*d = ber->be_class;
747 			*t = ber->be_type;
748 			ret++;
749 			continue;
750 		case 'x':
751 			ptr = va_arg(ap, void **);
752 			len = va_arg(ap, size_t *);
753 			if (ber_get_nstring(ber, ptr, len) == -1)
754 				goto fail;
755 			ret++;
756 			break;
757 		case '0':
758 			if (ber->be_encoding != BER_TYPE_NULL)
759 				goto fail;
760 			ret++;
761 			break;
762 		case '.':
763 			if (ber->be_encoding != BER_TYPE_EOC)
764 				goto fail;
765 			ret++;
766 			break;
767 		case 'p':
768 			pos = va_arg(ap, off_t *);
769 			*pos = ber_getpos(ber);
770 			ret++;
771 			continue;
772 		case '{':
773 		case '(':
774 			if (ber->be_encoding != BER_TYPE_SEQUENCE &&
775 			    ber->be_encoding != BER_TYPE_SET)
776 				goto fail;
777 			if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
778 				goto fail;
779 			parent[++level] = ber;
780 			ber = ber->be_sub;
781 			ret++;
782 			continue;
783 		case '}':
784 		case ')':
785 			if (parent[level] == NULL)
786 				goto fail;
787 			ber = parent[level--];
788 			ret++;
789 			break;
790 		default:
791 			goto fail;
792 		}
793 
794 		if (ber->be_next == NULL)
795 			continue;
796 		ber = ber->be_next;
797 	}
798 	va_end(ap);
799 	return (ret == n ? 0 : -1);
800 
801  fail:
802 	va_end(ap);
803 	return (-1);
804 
805 }
806 
807 ssize_t
808 ber_get_writebuf(struct ber *b, void **buf)
809 {
810 	if (b->br_wbuf == NULL)
811 		return -1;
812 	*buf = b->br_wbuf;
813 	return (b->br_wend - b->br_wbuf);
814 }
815 
816 /*
817  * write ber elements to the write buffer
818  *
819  * params:
820  *	ber	holds the destination write buffer byte stream
821  *	root	fully populated element tree
822  *
823  * returns:
824  *	>=0	number of bytes written
825  *	-1	on failure and sets errno
826  */
827 ssize_t
828 ber_write_elements(struct ber *ber, struct ber_element *root)
829 {
830 	size_t len;
831 
832 	/* calculate length because only the definite form is required */
833 	len = ber_calc_len(root);
834 	DPRINTF("write ber element of %zd bytes length\n", len);
835 
836 	if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
837 		free(ber->br_wbuf);
838 		ber->br_wbuf = NULL;
839 	}
840 	if (ber->br_wbuf == NULL) {
841 		if ((ber->br_wbuf = malloc(len)) == NULL)
842 			return -1;
843 		ber->br_wend = ber->br_wbuf + len;
844 	}
845 
846 	/* reset write pointer */
847 	ber->br_wptr = ber->br_wbuf;
848 
849 	if (ber_dump_element(ber, root) == -1)
850 		return -1;
851 
852 	return (len);
853 }
854 
855 void
856 ber_set_readbuf(struct ber *b, void *buf, size_t len)
857 {
858 	b->br_rbuf = b->br_rptr = buf;
859 	b->br_rend = (u_int8_t *)buf + len;
860 }
861 
862 /*
863  * read ber elements from the read buffer
864  *
865  * params:
866  *	ber	holds a fully populated read buffer byte stream
867  *	root	if NULL, build up an element tree from what we receive on
868  *		the wire. If not null, use the specified encoding for the
869  *		elements received.
870  *
871  * returns:
872  *	!=NULL, elements read and store in the ber_element tree
873  *	NULL, type mismatch or read error
874  */
875 struct ber_element *
876 ber_read_elements(struct ber *ber, struct ber_element *elm)
877 {
878 	struct ber_element *root = elm;
879 
880 	if (root == NULL) {
881 		if ((root = ber_get_element(0)) == NULL)
882 			return NULL;
883 	}
884 
885 	DPRINTF("read ber elements, root %p\n", root);
886 
887 	if (ber_read_element(ber, root) == -1) {
888 		/* Cleanup if root was allocated by us */
889 		if (elm == NULL)
890 			ber_free_elements(root);
891 		return NULL;
892 	}
893 
894 	return root;
895 }
896 
897 off_t
898 ber_getpos(struct ber_element *elm)
899 {
900 	return elm->be_offs;
901 }
902 
903 void
904 ber_free_element(struct ber_element *root)
905 {
906 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
907 	    root->be_encoding == BER_TYPE_SET))
908 		ber_free_elements(root->be_sub);
909 	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
910 	    root->be_encoding == BER_TYPE_BITSTRING ||
911 	    root->be_encoding == BER_TYPE_OBJECT))
912 		free(root->be_val);
913 	free(root);
914 }
915 
916 void
917 ber_free_elements(struct ber_element *root)
918 {
919 	if (root == NULL)
920 		return;
921 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
922 	    root->be_encoding == BER_TYPE_SET))
923 		ber_free_elements(root->be_sub);
924 	if (root->be_next)
925 		ber_free_elements(root->be_next);
926 	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
927 	    root->be_encoding == BER_TYPE_BITSTRING ||
928 	    root->be_encoding == BER_TYPE_OBJECT))
929 		free(root->be_val);
930 	free(root);
931 }
932 
933 size_t
934 ber_calc_len(struct ber_element *root)
935 {
936 	unsigned int t;
937 	size_t s;
938 	size_t size = 2;	/* minimum 1 byte head and 1 byte size */
939 
940 	/* calculate the real length of a sequence or set */
941 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
942 	    root->be_encoding == BER_TYPE_SET))
943 		root->be_len = ber_calc_len(root->be_sub);
944 
945 	/* fix header length for extended types */
946 	if (root->be_type > BER_TYPE_SINGLE_MAX)
947 		for (t = root->be_type; t > 0; t >>= 7)
948 			size++;
949 	if (root->be_len >= BER_TAG_MORE)
950 		for (s = root->be_len; s > 0; s >>= 8)
951 			size++;
952 
953 	/* calculate the length of the following elements */
954 	if (root->be_next)
955 		size += ber_calc_len(root->be_next);
956 
957 	/* This is an empty element, do not use a minimal size */
958 	if (root->be_class == BER_CLASS_UNIVERSAL &&
959 	    root->be_type == BER_TYPE_EOC && root->be_len == 0)
960 		return (0);
961 
962 	return (root->be_len + size);
963 }
964 
965 void
966 ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
967 {
968 	b->br_application = cb;
969 }
970 
971 void
972 ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
973     void *arg)
974 {
975 	elm->be_cb = cb;
976 	elm->be_cbarg = arg;
977 }
978 
979 void
980 ber_free(struct ber *b)
981 {
982 	free(b->br_wbuf);
983 }
984 
985 /*
986  * internal functions
987  */
988 
989 static int
990 ber_dump_element(struct ber *ber, struct ber_element *root)
991 {
992 	unsigned long long l;
993 	int i;
994 	uint8_t u;
995 
996 	ber_dump_header(ber, root);
997 	if (root->be_cb)
998 		root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
999 
1000 	switch (root->be_encoding) {
1001 	case BER_TYPE_BOOLEAN:
1002 	case BER_TYPE_INTEGER:
1003 	case BER_TYPE_ENUMERATED:
1004 		l = (unsigned long long)root->be_numeric;
1005 		for (i = root->be_len; i > 0; i--) {
1006 			u = (l >> ((i - 1) * 8)) & 0xff;
1007 			ber_putc(ber, u);
1008 		}
1009 		break;
1010 	case BER_TYPE_BITSTRING:
1011 	case BER_TYPE_OCTETSTRING:
1012 	case BER_TYPE_OBJECT:
1013 		ber_write(ber, root->be_val, root->be_len);
1014 		break;
1015 	case BER_TYPE_NULL:	/* no payload */
1016 	case BER_TYPE_EOC:
1017 		break;
1018 	case BER_TYPE_SEQUENCE:
1019 	case BER_TYPE_SET:
1020 		if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
1021 			return -1;
1022 		break;
1023 	}
1024 
1025 	if (root->be_next == NULL)
1026 		return 0;
1027 	return ber_dump_element(ber, root->be_next);
1028 }
1029 
1030 static void
1031 ber_dump_header(struct ber *ber, struct ber_element *root)
1032 {
1033 	u_char	id = 0, t, buf[5];
1034 	unsigned int type;
1035 	size_t size;
1036 
1037 	/* class universal, type encoding depending on type value */
1038 	/* length encoding */
1039 	if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1040 		id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1041 		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1042 		    root->be_encoding == BER_TYPE_SET)
1043 			id |= BER_TYPE_CONSTRUCTED;
1044 
1045 		ber_putc(ber, id);
1046 	} else {
1047 		id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1048 		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1049 		    root->be_encoding == BER_TYPE_SET)
1050 			id |= BER_TYPE_CONSTRUCTED;
1051 
1052 		ber_putc(ber, id);
1053 
1054 		for (t = 0, type = root->be_type; type > 0; type >>= 7)
1055 			buf[t++] = type & ~BER_TAG_MORE;
1056 
1057 		while (t-- > 0) {
1058 			if (t > 0)
1059 				buf[t] |= BER_TAG_MORE;
1060 			ber_putc(ber, buf[t]);
1061 		}
1062 	}
1063 
1064 	if (root->be_len < BER_TAG_MORE) {
1065 		/* short form */
1066 		ber_putc(ber, root->be_len);
1067 	} else {
1068 		for (t = 0, size = root->be_len; size > 0; size >>= 8)
1069 			buf[t++] = size & 0xff;
1070 
1071 		ber_putc(ber, t | BER_TAG_MORE);
1072 
1073 		while (t > 0)
1074 			ber_putc(ber, buf[--t]);
1075 	}
1076 }
1077 
1078 static void
1079 ber_putc(struct ber *ber, u_char c)
1080 {
1081 	if (ber->br_wptr + 1 <= ber->br_wend)
1082 		*ber->br_wptr = c;
1083 	ber->br_wptr++;
1084 }
1085 
1086 static void
1087 ber_write(struct ber *ber, void *buf, size_t len)
1088 {
1089 	if (ber->br_wptr + len <= ber->br_wend)
1090 		bcopy(buf, ber->br_wptr, len);
1091 	ber->br_wptr += len;
1092 }
1093 
1094 /*
1095  * extract a BER encoded tag. There are two types, a short and long form.
1096  */
1097 static ssize_t
1098 get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1099 {
1100 	u_char u;
1101 	size_t i = 0;
1102 	unsigned int t = 0;
1103 
1104 	if (ber_getc(b, &u) == -1)
1105 		return -1;
1106 
1107 	*class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1108 	*cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1109 
1110 	if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1111 		*tag = u & BER_TAG_MASK;
1112 		return 1;
1113 	}
1114 
1115 	do {
1116 		if (ber_getc(b, &u) == -1)
1117 			return -1;
1118 
1119 		/* enforce minimal number of octets for tag > 30 */
1120 		if (i == 0 && (u & ~BER_TAG_MORE) == 0) {
1121 			errno = EINVAL;
1122 			return -1;
1123 		}
1124 
1125 		t = (t << 7) | (u & ~BER_TAG_MORE);
1126 		i++;
1127 		if (i > sizeof(unsigned int)) {
1128 			errno = ERANGE;
1129 			return -1;
1130 		}
1131 	} while (u & BER_TAG_MORE);
1132 
1133 	*tag = t;
1134 	return i + 1;
1135 }
1136 
1137 /*
1138  * extract length of a ber object -- if length is unknown an error is returned.
1139  */
1140 static ssize_t
1141 get_len(struct ber *b, ssize_t *len)
1142 {
1143 	u_char	u, n;
1144 	ssize_t	s, r;
1145 
1146 	if (ber_getc(b, &u) == -1)
1147 		return -1;
1148 	if ((u & BER_TAG_MORE) == 0) {
1149 		/* short form */
1150 		*len = u;
1151 		return 1;
1152 	}
1153 
1154 	if (u == 0x80) {
1155 		/* Indefinite length not supported. */
1156 		errno = EINVAL;
1157 		return -1;
1158 	}
1159 
1160 	if (u == 0xff) {
1161 		/* Reserved for future use. */
1162 		errno = EINVAL;
1163 		return -1;
1164 	}
1165 
1166 	n = u & ~BER_TAG_MORE;
1167 	/*
1168 	 * Limit to a decent size that works on all of our architectures.
1169 	 */
1170 	if (sizeof(int32_t) < n) {
1171 		errno = ERANGE;
1172 		return -1;
1173 	}
1174 	r = n + 1;
1175 
1176 	for (s = 0; n > 0; n--) {
1177 		if (ber_getc(b, &u) == -1)
1178 			return -1;
1179 		s = (s << 8) | u;
1180 	}
1181 
1182 	if (s < 0) {
1183 		/* overflow */
1184 		errno = ERANGE;
1185 		return -1;
1186 	}
1187 
1188 	*len = s;
1189 	return r;
1190 }
1191 
1192 static ssize_t
1193 ber_read_element(struct ber *ber, struct ber_element *elm)
1194 {
1195 	long long val = 0;
1196 	struct ber_element *next;
1197 	unsigned int type;
1198 	int i, class, cstruct, elements = 0;
1199 	ssize_t len, r, totlen = 0;
1200 	u_char c, last = 0;
1201 
1202 	if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1203 		return -1;
1204 	DPRINTF("ber read got class %d type %u, %s\n",
1205 	    class, type, cstruct ? "constructed" : "primitive");
1206 	totlen += r;
1207 	if ((r = get_len(ber, &len)) == -1)
1208 		return -1;
1209 	DPRINTF("ber read element size %zd\n", len);
1210 	totlen += r + len;
1211 
1212 	/* The encoding of boolean, integer, enumerated, and null values
1213 	 * must be primitive. */
1214 	if (class == BER_CLASS_UNIVERSAL)
1215 		if (type == BER_TYPE_BOOLEAN ||
1216 		    type == BER_TYPE_INTEGER ||
1217 		    type == BER_TYPE_ENUMERATED ||
1218 		    type == BER_TYPE_NULL)
1219 			if (cstruct) {
1220 				errno = EINVAL;
1221 				return -1;
1222 			}
1223 
1224 	/* If the total size of the element is larger than the buffer
1225 	 * don't bother to continue. */
1226 	if (len > ber->br_rend - ber->br_rptr) {
1227 		errno = ECANCELED;
1228 		return -1;
1229 	}
1230 
1231 	elm->be_type = type;
1232 	elm->be_len = len;
1233 	elm->be_offs = ber->br_offs;	/* element position within stream */
1234 	elm->be_class = class;
1235 
1236 	if (elm->be_encoding == 0) {
1237 		/* try to figure out the encoding via class, type and cstruct */
1238 		if (cstruct)
1239 			elm->be_encoding = BER_TYPE_SEQUENCE;
1240 		else if (class == BER_CLASS_UNIVERSAL)
1241 			elm->be_encoding = type;
1242 		else if (ber->br_application != NULL) {
1243 			/*
1244 			 * Ask the application to map the encoding to a
1245 			 * universal type. For example, a SMI IpAddress
1246 			 * type is defined as 4 byte OCTET STRING.
1247 			 */
1248 			elm->be_encoding = (*ber->br_application)(elm);
1249 		} else
1250 			/* last resort option */
1251 			elm->be_encoding = BER_TYPE_NULL;
1252 	}
1253 
1254 	switch (elm->be_encoding) {
1255 	case BER_TYPE_EOC:	/* End-Of-Content */
1256 		break;
1257 	case BER_TYPE_BOOLEAN:
1258 		if (len != 1) {
1259 			errno = EINVAL;
1260 			return -1;
1261 		}
1262 	case BER_TYPE_INTEGER:
1263 	case BER_TYPE_ENUMERATED:
1264 		if (len > (ssize_t)sizeof(long long))
1265 			return -1;
1266 		for (i = 0; i < len; i++) {
1267 			if (ber_getc(ber, &c) != 1)
1268 				return -1;
1269 
1270 			/* smallest number of contents octets only */
1271 			if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1272 			    (i == 1 && last == 0xff && (c & 0x80) != 0))
1273 				return -1;
1274 
1275 			val <<= 8;
1276 			val |= c;
1277 			last = c;
1278 		}
1279 
1280 		/* sign extend if MSB is set */
1281 		if (len < (ssize_t)sizeof(long long) &&
1282 		    (val >> ((len - 1) * 8) & 0x80))
1283 			val |= ULLONG_MAX << (len * 8);
1284 		elm->be_numeric = val;
1285 		break;
1286 	case BER_TYPE_BITSTRING:
1287 		elm->be_val = malloc(len);
1288 		if (elm->be_val == NULL)
1289 			return -1;
1290 		elm->be_free = 1;
1291 		elm->be_len = len;
1292 		ber_read(ber, elm->be_val, len);
1293 		break;
1294 	case BER_TYPE_OCTETSTRING:
1295 	case BER_TYPE_OBJECT:
1296 		elm->be_val = malloc(len + 1);
1297 		if (elm->be_val == NULL)
1298 			return -1;
1299 		elm->be_free = 1;
1300 		elm->be_len = len;
1301 		ber_read(ber, elm->be_val, len);
1302 		((u_char *)elm->be_val)[len] = '\0';
1303 		break;
1304 	case BER_TYPE_NULL:	/* no payload */
1305 		if (len != 0)
1306 			return -1;
1307 		break;
1308 	case BER_TYPE_SEQUENCE:
1309 	case BER_TYPE_SET:
1310 		if (elm->be_sub == NULL) {
1311 			if ((elm->be_sub = ber_get_element(0)) == NULL)
1312 				return -1;
1313 		}
1314 		next = elm->be_sub;
1315 		while (len > 0) {
1316 			/*
1317 			 * Prevent stack overflow from excessive recursion
1318 			 * depth in ber_free_elements().
1319 			 */
1320 			if (elements >= BER_MAX_SEQ_ELEMENTS) {
1321 				errno = ERANGE;
1322 				return -1;
1323 			}
1324 			r = ber_read_element(ber, next);
1325 			if (r == -1)
1326 				return -1;
1327 			elements++;
1328 			len -= r;
1329 			if (len > 0 && next->be_next == NULL) {
1330 				if ((next->be_next = ber_get_element(0)) ==
1331 				    NULL)
1332 					return -1;
1333 			}
1334 			next = next->be_next;
1335 		}
1336 		break;
1337 	}
1338 	return totlen;
1339 }
1340 
1341 static ssize_t
1342 ber_getc(struct ber *b, u_char *c)
1343 {
1344 	return ber_read(b, c, 1);
1345 }
1346 
1347 static ssize_t
1348 ber_read(struct ber *ber, void *buf, size_t len)
1349 {
1350 	size_t	sz;
1351 
1352 	if (ber->br_rbuf == NULL)
1353 		return -1;
1354 
1355 	sz = ber->br_rend - ber->br_rptr;
1356 	if (len > sz) {
1357 		errno = ECANCELED;
1358 		return -1;	/* parser wants more data than available */
1359 	}
1360 
1361 	bcopy(ber->br_rptr, buf, len);
1362 	ber->br_rptr += len;
1363 	ber->br_offs += len;
1364 
1365 	return len;
1366 }
1367