ber.c revision 1.25
1/*	$OpenBSD: ber.c,v 1.25 2023/08/22 12:50:27 gerhard 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
41static int	ober_dump_element(struct ber *ber, struct ber_element *root);
42static void	ober_dump_header(struct ber *ber, struct ber_element *root);
43static void	ober_putc(struct ber *ber, u_char c);
44static void	ober_write(struct ber *ber, void *buf, size_t len);
45static ssize_t	get_id(struct ber *b, unsigned int *tag, int *class,
46    int *cstruct);
47static ssize_t	get_len(struct ber *b, ssize_t *len);
48static ssize_t	ober_read_element(struct ber *ber, struct ber_element *elm);
49static ssize_t	ober_getc(struct ber *b, u_char *c);
50static ssize_t	ober_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
58struct ber_element *
59ober_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	ober_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
68
69	return elm;
70}
71
72void
73ober_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
81void
82ober_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
94struct ber_element *
95ober_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
112void
113ober_replace_elements(struct ber_element *prev, struct ber_element *new)
114{
115	struct ber_element *ber, *next;
116
117	ber = ober_unlink_elements(prev);
118	next = ober_unlink_elements(ber);
119	ober_link_elements(new, next);
120	ober_link_elements(prev, new);
121
122	/* cleanup old element */
123	ober_free_elements(ber);
124}
125
126struct ber_element *
127ober_add_sequence(struct ber_element *prev)
128{
129	struct ber_element *elm;
130
131	if ((elm = ober_get_element(BER_TYPE_SEQUENCE)) == NULL)
132		return NULL;
133
134	ober_link_elements(prev, elm);
135
136	return elm;
137}
138
139struct ber_element *
140ober_add_set(struct ber_element *prev)
141{
142	struct ber_element *elm;
143
144	if ((elm = ober_get_element(BER_TYPE_SET)) == NULL)
145		return NULL;
146
147	ober_link_elements(prev, elm);
148
149	return elm;
150}
151
152struct ber_element *
153ober_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 = ober_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	ober_link_elements(prev, elm);
177
178	return elm;
179}
180
181struct ber_element *
182ober_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 = ober_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	ober_link_elements(prev, elm);
206
207	return elm;
208}
209
210int
211ober_get_integer(struct ber_element *elm, long long *n)
212{
213	if (elm->be_encoding != BER_TYPE_INTEGER)
214		return -1;
215
216	if (n != NULL)
217		*n = elm->be_numeric;
218	return 0;
219}
220
221int
222ober_get_enumerated(struct ber_element *elm, long long *n)
223{
224	if (elm->be_encoding != BER_TYPE_ENUMERATED)
225		return -1;
226
227	if (n != NULL)
228		*n = elm->be_numeric;
229	return 0;
230}
231
232struct ber_element *
233ober_add_boolean(struct ber_element *prev, int bool)
234{
235	struct ber_element *elm;
236
237	if ((elm = ober_get_element(BER_TYPE_BOOLEAN)) == NULL)
238		return NULL;
239
240	elm->be_numeric = bool ? 0xff : 0;
241	elm->be_len = 1;
242
243	ober_link_elements(prev, elm);
244
245	return elm;
246}
247
248int
249ober_get_boolean(struct ber_element *elm, int *b)
250{
251	if (elm->be_encoding != BER_TYPE_BOOLEAN)
252		return -1;
253
254	if (b != NULL)
255		*b = !(elm->be_numeric == 0);
256	return 0;
257}
258
259struct ber_element *
260ober_add_string(struct ber_element *prev, const char *string)
261{
262	return ober_add_nstring(prev, string, strlen(string));
263}
264
265struct ber_element *
266ober_add_nstring(struct ber_element *prev, const char *string0, size_t len)
267{
268	struct ber_element *elm;
269	char *string;
270
271	if ((string = calloc(1, len + 1)) == NULL)
272		return NULL;
273	if ((elm = ober_get_element(BER_TYPE_OCTETSTRING)) == NULL) {
274		free(string);
275		return NULL;
276	}
277
278	bcopy(string0, string, len);
279	elm->be_val = string;
280	elm->be_len = len;
281	elm->be_free = 1;		/* free string on cleanup */
282
283	ober_link_elements(prev, elm);
284
285	return elm;
286}
287
288struct ber_element *
289ober_add_ostring(struct ber_element *prev, struct ber_octetstring *s)
290{
291	return ober_add_nstring(prev, s->ostr_val, s->ostr_len);
292}
293
294int
295ober_get_string(struct ber_element *elm, char **s)
296{
297	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
298		return -1;
299	/* XXX some components use getstring on binary data containing \0 */
300#if 0
301	if (memchr(elm->be_val, '\0', elm->be_len) != NULL)
302		return -1;
303#endif
304
305	if (s != NULL)
306		*s = elm->be_val;
307	return 0;
308}
309
310int
311ober_get_nstring(struct ber_element *elm, void **p, size_t *len)
312{
313	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
314		return -1;
315
316	if (len != NULL)
317		*len = elm->be_len;
318	if (p != NULL) {
319		if (len != NULL)
320			*p = elm->be_val;
321		else
322			*p = NULL;
323	}
324	return 0;
325}
326
327int
328ober_get_ostring(struct ber_element *elm, struct ber_octetstring *s)
329{
330	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
331		return -1;
332
333	if (s != NULL) {
334		s->ostr_val = elm->be_val;
335		s->ostr_len = elm->be_len;
336	}
337	return 0;
338}
339
340struct ber_element *
341ober_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
342{
343	struct ber_element *elm;
344	void *v;
345
346	if ((v = calloc(1, len)) == NULL)
347		return NULL;
348	if ((elm = ober_get_element(BER_TYPE_BITSTRING)) == NULL) {
349		free(v);
350		return NULL;
351	}
352
353	bcopy(v0, v, len);
354	elm->be_val = v;
355	elm->be_len = len;
356	elm->be_free = 1;		/* free string on cleanup */
357
358	ober_link_elements(prev, elm);
359
360	return elm;
361}
362
363int
364ober_get_bitstring(struct ber_element *elm, void **v, size_t *len)
365{
366	if (elm->be_encoding != BER_TYPE_BITSTRING)
367		return -1;
368
369	if (len != NULL)
370		*len = elm->be_len;
371	if (v != NULL) {
372		if (len != NULL)
373			*v = elm->be_val;
374		else
375			*v = NULL;
376	}
377	return 0;
378}
379
380struct ber_element *
381ober_add_null(struct ber_element *prev)
382{
383	struct ber_element *elm;
384
385	if ((elm = ober_get_element(BER_TYPE_NULL)) == NULL)
386		return NULL;
387
388	ober_link_elements(prev, elm);
389
390	return elm;
391}
392
393int
394ober_get_null(struct ber_element *elm)
395{
396	if (elm->be_encoding != BER_TYPE_NULL)
397		return -1;
398
399	return 0;
400}
401
402struct ber_element *
403ober_add_eoc(struct ber_element *prev)
404{
405	struct ber_element *elm;
406
407	if ((elm = ober_get_element(BER_TYPE_EOC)) == NULL)
408		return NULL;
409
410	ober_link_elements(prev, elm);
411
412	return elm;
413}
414
415int
416ober_get_eoc(struct ber_element *elm)
417{
418	if (elm->be_encoding != BER_TYPE_EOC)
419		return -1;
420
421	return 0;
422}
423
424size_t
425ober_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
426{
427	u_int32_t	 v;
428	u_int		 i, j = 0, k;
429
430	if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
431	    o->bo_id[0] > 2 || o->bo_id[1] > 40)
432		return (0);
433
434	v = (o->bo_id[0] * 40) + o->bo_id[1];
435	for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
436		for (k = 28; k >= 7; k -= 7) {
437			if (v >= (u_int)(1 << k)) {
438				if (len)
439					buf[j] = v >> k | BER_TAG_MORE;
440				j++;
441			}
442		}
443		if (len)
444			buf[j] = v & BER_TAG_TYPE_MASK;
445		j++;
446	}
447
448	return (j);
449}
450
451int
452ober_string2oid(const char *oidstr, struct ber_oid *o)
453{
454	char			*sp, *p, str[BUFSIZ];
455	const char		*errstr;
456
457	if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
458		return (-1);
459	memset(o, 0, sizeof(*o));
460
461	/* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
462	for (p = sp = str; p != NULL; sp = p) {
463		if ((p = strpbrk(p, "._-")) != NULL)
464			*p++ = '\0';
465		o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
466		if (errstr || o->bo_n > BER_MAX_OID_LEN)
467			return (-1);
468	}
469
470	return (0);
471}
472
473int
474ober_oid_cmp(struct ber_oid *a, struct ber_oid *b)
475{
476	size_t	 i, min;
477
478	min = a->bo_n < b->bo_n ? a->bo_n : b->bo_n;
479	for (i = 0; i < min; i++) {
480		if (a->bo_id[i] < b->bo_id[i])
481			return (-1);
482		if (a->bo_id[i] > b->bo_id[i])
483			return (1);
484	}
485	/* a is parent of b */
486	if (a->bo_n < b->bo_n)
487		return (-2);
488	/* a is child of b */
489	if (a->bo_n > b->bo_n)
490		return 2;
491	return (0);
492}
493
494struct ber_element *
495ober_add_oid(struct ber_element *prev, struct ber_oid *o)
496{
497	struct ber_element	*elm;
498	u_int8_t		*buf;
499	size_t			 len;
500
501	if ((elm = ober_get_element(BER_TYPE_OBJECT)) == NULL)
502		return (NULL);
503
504	if ((len = ober_oid2ber(o, NULL, 0)) == 0)
505		goto fail;
506
507	if ((buf = calloc(1, len)) == NULL)
508		goto fail;
509
510	elm->be_val = buf;
511	elm->be_len = len;
512	elm->be_free = 1;
513
514	if (ober_oid2ber(o, buf, len) != len)
515		goto fail;
516
517	ober_link_elements(prev, elm);
518
519	return (elm);
520
521 fail:
522	ober_free_elements(elm);
523	return (NULL);
524}
525
526struct ber_element *
527ober_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
528{
529	struct ber_oid		 no;
530
531	if (n > BER_MAX_OID_LEN)
532		return (NULL);
533	no.bo_n = n;
534	bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
535
536	return (ober_add_oid(prev, &no));
537}
538
539struct ber_element *
540ober_add_oidstring(struct ber_element *prev, const char *oidstr)
541{
542	struct ber_oid		 o;
543
544	if (ober_string2oid(oidstr, &o) == -1)
545		return (NULL);
546
547	return (ober_add_oid(prev, &o));
548}
549
550int
551ober_get_oid(struct ber_element *elm, struct ber_oid *o)
552{
553	u_int8_t	*buf;
554	size_t		 len, i = 0, j = 0;
555
556	if (elm->be_encoding != BER_TYPE_OBJECT)
557		return (-1);
558
559	if (o == NULL)
560		return 0;
561
562	buf = elm->be_val;
563	len = elm->be_len;
564
565	memset(o, 0, sizeof(*o));
566	o->bo_id[j++] = buf[i] / 40;
567	o->bo_id[j++] = buf[i++] % 40;
568	for (; i < len && j < BER_MAX_OID_LEN; i++) {
569		o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
570		if (buf[i] & 0x80)
571			continue;
572		j++;
573	}
574	o->bo_n = j;
575
576	return (0);
577}
578
579struct ber_element *
580ober_printf_elements(struct ber_element *ber, char *fmt, ...)
581{
582	va_list			 ap;
583	int			 d, class;
584	size_t			 len;
585	unsigned int		 type;
586	long long		 i;
587	char			*s;
588	void			*p;
589	struct ber_oid		*o;
590	struct ber_element	*sub = ber, *e;
591
592	va_start(ap, fmt);
593	while (*fmt) {
594		switch (*fmt++) {
595		case 'B':
596			p = va_arg(ap, void *);
597			len = va_arg(ap, size_t);
598			if ((ber = ober_add_bitstring(ber, p, len)) == NULL)
599				goto fail;
600			break;
601		case 'b':
602			d = va_arg(ap, int);
603			if ((ber = ober_add_boolean(ber, d)) == NULL)
604				goto fail;
605			break;
606		case 'd':
607			d = va_arg(ap, int);
608			if ((ber = ober_add_integer(ber, d)) == NULL)
609				goto fail;
610			break;
611		case 'e':
612			e = va_arg(ap, struct ber_element *);
613			ober_link_elements(ber, e);
614			break;
615		case 'E':
616			i = va_arg(ap, long long);
617			if ((ber = ober_add_enumerated(ber, i)) == NULL)
618				goto fail;
619			break;
620		case 'i':
621			i = va_arg(ap, long long);
622			if ((ber = ober_add_integer(ber, i)) == NULL)
623				goto fail;
624			break;
625		case 'O':
626			o = va_arg(ap, struct ber_oid *);
627			if ((ber = ober_add_oid(ber, o)) == NULL)
628				goto fail;
629			break;
630		case 'o':
631			s = va_arg(ap, char *);
632			if ((ber = ober_add_oidstring(ber, s)) == NULL)
633				goto fail;
634			break;
635		case 's':
636			s = va_arg(ap, char *);
637			if ((ber = ober_add_string(ber, s)) == NULL)
638				goto fail;
639			break;
640		case 't':
641			class = va_arg(ap, int);
642			type = va_arg(ap, unsigned int);
643			ober_set_header(ber, class, type);
644			break;
645		case 'x':
646			s = va_arg(ap, char *);
647			len = va_arg(ap, size_t);
648			if ((ber = ober_add_nstring(ber, s, len)) == NULL)
649				goto fail;
650			break;
651		case '0':
652			if ((ber = ober_add_null(ber)) == NULL)
653				goto fail;
654			break;
655		case '{':
656			if ((ber = sub = ober_add_sequence(ber)) == NULL)
657				goto fail;
658			break;
659		case '(':
660			if ((ber = sub = ober_add_set(ber)) == NULL)
661				goto fail;
662			break;
663		case '}':
664		case ')':
665			ber = sub;
666			break;
667		case '.':
668			if ((e = ober_add_eoc(ber)) == NULL)
669				goto fail;
670			ber = e;
671			break;
672		default:
673			break;
674		}
675	}
676	va_end(ap);
677
678	return (ber);
679 fail:
680	ober_free_elements(ber);
681	return (NULL);
682}
683
684int
685ober_scanf_elements(struct ber_element *ber, char *fmt, ...)
686{
687#define _MAX_SEQ		 128
688	va_list			 ap;
689	int			*d, level = -1;
690	unsigned int		*t;
691	long long		*i, l;
692	void			**ptr;
693	size_t			*len, ret = 0, n = strlen(fmt);
694	char			**s;
695	off_t			*pos;
696	struct ber_oid		*o;
697	struct ber_element	*parent[_MAX_SEQ], **e;
698
699	memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
700
701	va_start(ap, fmt);
702	while (*fmt) {
703		if (ber == NULL && *fmt != '$' && *fmt != '}' && *fmt != ')')
704			goto fail;
705		switch (*fmt++) {
706		case '$':
707			if (ber != NULL)
708				goto fail;
709			ret++;
710			continue;
711		case 'B':
712			ptr = va_arg(ap, void **);
713			len = va_arg(ap, size_t *);
714			if (ober_get_bitstring(ber, ptr, len) == -1)
715				goto fail;
716			ret++;
717			break;
718		case 'b':
719			d = va_arg(ap, int *);
720			if (ober_get_boolean(ber, d) == -1)
721				goto fail;
722			ret++;
723			break;
724		case 'd':
725			d = va_arg(ap, int *);
726			if (ober_get_integer(ber, &l) == -1)
727				goto fail;
728			if (d != NULL)
729				*d = l;
730			ret++;
731			break;
732		case 'e':
733			e = va_arg(ap, struct ber_element **);
734			*e = ber;
735			ret++;
736			continue;
737		case 'E':
738			i = va_arg(ap, long long *);
739			if (ober_get_enumerated(ber, i) == -1)
740				goto fail;
741			ret++;
742			break;
743		case 'i':
744			i = va_arg(ap, long long *);
745			if (ober_get_integer(ber, i) == -1)
746				goto fail;
747			ret++;
748			break;
749		case 'o':
750			o = va_arg(ap, struct ber_oid *);
751			if (ober_get_oid(ber, o) == -1)
752				goto fail;
753			ret++;
754			break;
755		case 'S':
756			ret++;
757			break;
758		case 's':
759			s = va_arg(ap, char **);
760			if (ober_get_string(ber, s) == -1)
761				goto fail;
762			ret++;
763			break;
764		case 't':
765			d = va_arg(ap, int *);
766			t = va_arg(ap, unsigned int *);
767			if (d != NULL)
768				*d = ber->be_class;
769			if (t != NULL)
770				*t = ber->be_type;
771			ret++;
772			continue;
773		case 'x':
774			ptr = va_arg(ap, void **);
775			len = va_arg(ap, size_t *);
776			if (ober_get_nstring(ber, ptr, len) == -1)
777				goto fail;
778			ret++;
779			break;
780		case '0':
781			if (ber->be_encoding != BER_TYPE_NULL)
782				goto fail;
783			ret++;
784			break;
785		case '.':
786			if (ber->be_encoding != BER_TYPE_EOC)
787				goto fail;
788			ret++;
789			break;
790		case 'p':
791			pos = va_arg(ap, off_t *);
792			*pos = ober_getpos(ber);
793			ret++;
794			continue;
795		case '{':
796		case '(':
797			if (ber->be_encoding != BER_TYPE_SEQUENCE &&
798			    ber->be_encoding != BER_TYPE_SET)
799				goto fail;
800			if (level >= _MAX_SEQ-1)
801				goto fail;
802			parent[++level] = ber;
803			ber = ber->be_sub;
804			ret++;
805			continue;
806		case '}':
807		case ')':
808			if (level < 0 || parent[level] == NULL)
809				goto fail;
810			ber = parent[level--];
811			ret++;
812			break;
813		default:
814			goto fail;
815		}
816
817		ber = ber->be_next;
818	}
819	va_end(ap);
820	return (ret == n ? 0 : -1);
821
822 fail:
823	va_end(ap);
824	return (-1);
825
826}
827
828ssize_t
829ober_get_writebuf(struct ber *b, void **buf)
830{
831	if (b->br_wbuf == NULL)
832		return -1;
833	*buf = b->br_wbuf;
834	return (b->br_wend - b->br_wbuf);
835}
836
837/*
838 * write ber elements to the write buffer
839 *
840 * params:
841 *	ber	holds the destination write buffer byte stream
842 *	root	fully populated element tree
843 *
844 * returns:
845 *	>=0	number of bytes written
846 *	-1	on failure and sets errno
847 */
848ssize_t
849ober_write_elements(struct ber *ber, struct ber_element *root)
850{
851	size_t len;
852
853	/* calculate length because only the definite form is required */
854	len = ober_calc_len(root);
855	DPRINTF("write ber element of %zd bytes length\n", len);
856
857	if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
858		free(ber->br_wbuf);
859		ber->br_wbuf = NULL;
860	}
861	if (ber->br_wbuf == NULL) {
862		if ((ber->br_wbuf = malloc(len)) == NULL)
863			return -1;
864		ber->br_wend = ber->br_wbuf + len;
865	}
866
867	/* reset write pointer */
868	ber->br_wptr = ber->br_wbuf;
869
870	if (ober_dump_element(ber, root) == -1)
871		return -1;
872
873	return (len);
874}
875
876void
877ober_set_readbuf(struct ber *b, void *buf, size_t len)
878{
879	b->br_rbuf = b->br_rptr = buf;
880	b->br_rend = (u_int8_t *)buf + len;
881}
882
883/*
884 * read ber elements from the read buffer
885 *
886 * params:
887 *	ber	holds a fully populated read buffer byte stream
888 *	root	if NULL, build up an element tree from what we receive on
889 *		the wire. If not null, use the specified encoding for the
890 *		elements received.
891 *
892 * returns:
893 *	!=NULL, elements read and store in the ber_element tree
894 *	NULL, type mismatch or read error
895 */
896struct ber_element *
897ober_read_elements(struct ber *ber, struct ber_element *elm)
898{
899	struct ber_element *root = elm;
900
901	if (root == NULL) {
902		if ((root = ober_get_element(0)) == NULL)
903			return NULL;
904	}
905
906	DPRINTF("read ber elements, root %p\n", root);
907
908	if (ober_read_element(ber, root) == -1) {
909		/* Cleanup if root was allocated by us */
910		if (elm == NULL)
911			ober_free_elements(root);
912		return NULL;
913	}
914
915	return root;
916}
917
918off_t
919ober_getpos(struct ber_element *elm)
920{
921	return elm->be_offs;
922}
923
924struct ber_element *
925ober_dup(struct ber_element *orig)
926{
927	struct ber_element *new;
928
929	if ((new = malloc(sizeof(*new))) == NULL)
930		return NULL;
931	memcpy(new, orig, sizeof(*new));
932	new->be_next = NULL;
933	new->be_sub = NULL;
934
935	if (orig->be_next != NULL) {
936		if ((new->be_next = ober_dup(orig->be_next)) == NULL)
937			goto fail;
938	}
939	if (orig->be_encoding == BER_TYPE_SEQUENCE ||
940	    orig->be_encoding == BER_TYPE_SET) {
941		if (orig->be_sub != NULL) {
942			if ((new->be_sub = ober_dup(orig->be_sub)) == NULL)
943				goto fail;
944		}
945	} else if (orig->be_encoding == BER_TYPE_OCTETSTRING ||
946	    orig->be_encoding == BER_TYPE_BITSTRING ||
947	    orig->be_encoding == BER_TYPE_OBJECT) {
948		if (orig->be_val != NULL) {
949			if ((new->be_val = malloc(orig->be_len)) == NULL)
950				goto fail;
951			memcpy(new->be_val, orig->be_val, orig->be_len);
952		}
953	} else
954		new->be_numeric = orig->be_numeric;
955	return new;
956 fail:
957	ober_free_elements(new);
958	return NULL;
959}
960
961void
962ober_free_element(struct ber_element *root)
963{
964	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
965	    root->be_encoding == BER_TYPE_SET))
966		ober_free_elements(root->be_sub);
967	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
968	    root->be_encoding == BER_TYPE_BITSTRING ||
969	    root->be_encoding == BER_TYPE_OBJECT))
970		free(root->be_val);
971	free(root);
972}
973
974void
975ober_free_elements(struct ber_element *root)
976{
977	if (root == NULL)
978		return;
979	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
980	    root->be_encoding == BER_TYPE_SET))
981		ober_free_elements(root->be_sub);
982	if (root->be_next)
983		ober_free_elements(root->be_next);
984	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
985	    root->be_encoding == BER_TYPE_BITSTRING ||
986	    root->be_encoding == BER_TYPE_OBJECT))
987		free(root->be_val);
988	free(root);
989}
990
991size_t
992ober_calc_len(struct ber_element *root)
993{
994	unsigned int t;
995	size_t s;
996	size_t size = 2;	/* minimum 1 byte head and 1 byte size */
997
998	/* calculate the real length of a sequence or set */
999	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
1000	    root->be_encoding == BER_TYPE_SET))
1001		root->be_len = ober_calc_len(root->be_sub);
1002
1003	/* fix header length for extended types */
1004	if (root->be_type > BER_TYPE_SINGLE_MAX)
1005		for (t = root->be_type; t > 0; t >>= 7)
1006			size++;
1007	if (root->be_len >= BER_TAG_MORE)
1008		for (s = root->be_len; s > 0; s >>= 8)
1009			size++;
1010
1011	/* calculate the length of the following elements */
1012	if (root->be_next)
1013		size += ober_calc_len(root->be_next);
1014
1015	/* This is an empty element, do not use a minimal size */
1016	if (root->be_class == BER_CLASS_UNIVERSAL &&
1017	    root->be_type == BER_TYPE_EOC && root->be_len == 0)
1018		return (0);
1019
1020	return (root->be_len + size);
1021}
1022
1023void
1024ober_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
1025{
1026	b->br_application = cb;
1027}
1028
1029void
1030ober_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
1031    void *arg)
1032{
1033	elm->be_cb = cb;
1034	elm->be_cbarg = arg;
1035}
1036
1037void
1038ober_free(struct ber *b)
1039{
1040	free(b->br_wbuf);
1041}
1042
1043/*
1044 * internal functions
1045 */
1046
1047static int
1048ober_dump_element(struct ber *ber, struct ber_element *root)
1049{
1050	unsigned long long l;
1051	int i;
1052	uint8_t u;
1053
1054	ober_dump_header(ber, root);
1055	if (root->be_cb)
1056		root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1057
1058	switch (root->be_encoding) {
1059	case BER_TYPE_BOOLEAN:
1060	case BER_TYPE_INTEGER:
1061	case BER_TYPE_ENUMERATED:
1062		l = (unsigned long long)root->be_numeric;
1063		for (i = root->be_len; i > 0; i--) {
1064			u = (l >> ((i - 1) * 8)) & 0xff;
1065			ober_putc(ber, u);
1066		}
1067		break;
1068	case BER_TYPE_BITSTRING:
1069	case BER_TYPE_OCTETSTRING:
1070	case BER_TYPE_OBJECT:
1071		ober_write(ber, root->be_val, root->be_len);
1072		break;
1073	case BER_TYPE_NULL:	/* no payload */
1074	case BER_TYPE_EOC:
1075		break;
1076	case BER_TYPE_SEQUENCE:
1077	case BER_TYPE_SET:
1078		if (root->be_sub && ober_dump_element(ber, root->be_sub) == -1)
1079			return -1;
1080		break;
1081	}
1082
1083	if (root->be_next == NULL)
1084		return 0;
1085	return ober_dump_element(ber, root->be_next);
1086}
1087
1088static void
1089ober_dump_header(struct ber *ber, struct ber_element *root)
1090{
1091	u_char	id = 0, t, buf[5];
1092	unsigned int type;
1093	size_t size;
1094
1095	/* class universal, type encoding depending on type value */
1096	/* length encoding */
1097	if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1098		id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1099		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1100		    root->be_encoding == BER_TYPE_SET)
1101			id |= BER_TYPE_CONSTRUCTED;
1102
1103		ober_putc(ber, id);
1104	} else {
1105		id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1106		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1107		    root->be_encoding == BER_TYPE_SET)
1108			id |= BER_TYPE_CONSTRUCTED;
1109
1110		ober_putc(ber, id);
1111
1112		for (t = 0, type = root->be_type; type > 0; type >>= 7)
1113			buf[t++] = type & ~BER_TAG_MORE;
1114
1115		while (t-- > 0) {
1116			if (t > 0)
1117				buf[t] |= BER_TAG_MORE;
1118			ober_putc(ber, buf[t]);
1119		}
1120	}
1121
1122	if (root->be_len < BER_TAG_MORE) {
1123		/* short form */
1124		ober_putc(ber, root->be_len);
1125	} else {
1126		for (t = 0, size = root->be_len; size > 0; size >>= 8)
1127			buf[t++] = size & 0xff;
1128
1129		ober_putc(ber, t | BER_TAG_MORE);
1130
1131		while (t > 0)
1132			ober_putc(ber, buf[--t]);
1133	}
1134}
1135
1136static void
1137ober_putc(struct ber *ber, u_char c)
1138{
1139	if (ber->br_wptr + 1 <= ber->br_wend)
1140		*ber->br_wptr = c;
1141	ber->br_wptr++;
1142}
1143
1144static void
1145ober_write(struct ber *ber, void *buf, size_t len)
1146{
1147	if (ber->br_wptr + len <= ber->br_wend)
1148		bcopy(buf, ber->br_wptr, len);
1149	ber->br_wptr += len;
1150}
1151
1152/*
1153 * extract a BER encoded tag. There are two types, a short and long form.
1154 */
1155static ssize_t
1156get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1157{
1158	u_char u;
1159	size_t i = 0;
1160	unsigned int t = 0;
1161
1162	if (ober_getc(b, &u) == -1)
1163		return -1;
1164
1165	*class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1166	*cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1167
1168	if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1169		*tag = u & BER_TAG_MASK;
1170		return 1;
1171	}
1172
1173	do {
1174		if (ober_getc(b, &u) == -1)
1175			return -1;
1176
1177		/* enforce minimal number of octets for tag > 30 */
1178		if (i == 0 && (u & ~BER_TAG_MORE) == 0) {
1179			errno = EINVAL;
1180			return -1;
1181		}
1182
1183		t = (t << 7) | (u & ~BER_TAG_MORE);
1184		i++;
1185		if (i > sizeof(unsigned int)) {
1186			errno = ERANGE;
1187			return -1;
1188		}
1189	} while (u & BER_TAG_MORE);
1190
1191	*tag = t;
1192	return i + 1;
1193}
1194
1195/*
1196 * extract length of a ber object -- if length is unknown an error is returned.
1197 */
1198static ssize_t
1199get_len(struct ber *b, ssize_t *len)
1200{
1201	u_char	u, n;
1202	ssize_t	s, r;
1203
1204	if (ober_getc(b, &u) == -1)
1205		return -1;
1206	if ((u & BER_TAG_MORE) == 0) {
1207		/* short form */
1208		*len = u;
1209		return 1;
1210	}
1211
1212	if (u == 0x80) {
1213		/* Indefinite length not supported. */
1214		errno = EINVAL;
1215		return -1;
1216	}
1217
1218	if (u == 0xff) {
1219		/* Reserved for future use. */
1220		errno = EINVAL;
1221		return -1;
1222	}
1223
1224	n = u & ~BER_TAG_MORE;
1225	/*
1226	 * Limit to a decent size that works on all of our architectures.
1227	 */
1228	if (sizeof(int32_t) < n) {
1229		errno = ERANGE;
1230		return -1;
1231	}
1232	r = n + 1;
1233
1234	for (s = 0; n > 0; n--) {
1235		if (ober_getc(b, &u) == -1)
1236			return -1;
1237		s = (s << 8) | u;
1238	}
1239
1240	if (s < 0) {
1241		/* overflow */
1242		errno = ERANGE;
1243		return -1;
1244	}
1245
1246	*len = s;
1247	return r;
1248}
1249
1250static ssize_t
1251ober_read_element(struct ber *ber, struct ber_element *elm)
1252{
1253	long long val = 0;
1254	struct ber_element *next;
1255	unsigned int type;
1256	int i, class, cstruct, elements = 0;
1257	ssize_t len, r, totlen = 0;
1258	u_char c, last = 0;
1259
1260	if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1261		return -1;
1262	DPRINTF("ber read got class %d type %u, %s\n",
1263	    class, type, cstruct ? "constructed" : "primitive");
1264	totlen += r;
1265	if ((r = get_len(ber, &len)) == -1)
1266		return -1;
1267	DPRINTF("ber read element size %zd\n", len);
1268	totlen += r + len;
1269
1270	/* The encoding of boolean, integer, enumerated, and null values
1271	 * must be primitive. */
1272	if (class == BER_CLASS_UNIVERSAL)
1273		if (type == BER_TYPE_BOOLEAN ||
1274		    type == BER_TYPE_INTEGER ||
1275		    type == BER_TYPE_ENUMERATED ||
1276		    type == BER_TYPE_NULL)
1277			if (cstruct) {
1278				errno = EINVAL;
1279				return -1;
1280			}
1281
1282	/* If the total size of the element is larger than the buffer
1283	 * don't bother to continue. */
1284	if (len > ber->br_rend - ber->br_rptr) {
1285		errno = ECANCELED;
1286		return -1;
1287	}
1288
1289	elm->be_type = type;
1290	elm->be_len = len;
1291	elm->be_offs = ber->br_offs;	/* element position within stream */
1292	elm->be_class = class;
1293
1294	if (elm->be_encoding == 0) {
1295		/* try to figure out the encoding via class, type and cstruct */
1296		if (cstruct)
1297			elm->be_encoding = BER_TYPE_SEQUENCE;
1298		else if (class == BER_CLASS_UNIVERSAL)
1299			elm->be_encoding = type;
1300		else if (ber->br_application != NULL) {
1301			/*
1302			 * Ask the application to map the encoding to a
1303			 * universal type. For example, a SMI IpAddress
1304			 * type is defined as 4 byte OCTET STRING.
1305			 */
1306			elm->be_encoding = (*ber->br_application)(elm);
1307		} else
1308			/* last resort option */
1309			elm->be_encoding = BER_TYPE_NULL;
1310	}
1311
1312	switch (elm->be_encoding) {
1313	case BER_TYPE_EOC:	/* End-Of-Content */
1314		break;
1315	case BER_TYPE_BOOLEAN:
1316		if (len != 1) {
1317			errno = EINVAL;
1318			return -1;
1319		}
1320	case BER_TYPE_INTEGER:
1321	case BER_TYPE_ENUMERATED:
1322		if (len < 1) {
1323			errno = EINVAL;
1324			return -1;
1325		}
1326		if (len > (ssize_t)sizeof(long long)) {
1327			errno = ERANGE;
1328			return -1;
1329		}
1330		for (i = 0; i < len; i++) {
1331			if (ober_getc(ber, &c) != 1)
1332				return -1;
1333
1334			/* smallest number of contents octets only */
1335			if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1336			    (i == 1 && last == 0xff && (c & 0x80) != 0)) {
1337				errno = EINVAL;
1338				return -1;
1339			}
1340
1341			val <<= 8;
1342			val |= c;
1343			last = c;
1344		}
1345
1346		/* sign extend if MSB is set */
1347		if (len < (ssize_t)sizeof(long long) &&
1348		    (val >> ((len - 1) * 8) & 0x80))
1349			val |= ULLONG_MAX << (len * 8);
1350		elm->be_numeric = val;
1351		break;
1352	case BER_TYPE_BITSTRING:
1353		elm->be_val = malloc(len);
1354		if (elm->be_val == NULL)
1355			return -1;
1356		elm->be_free = 1;
1357		elm->be_len = len;
1358		ober_read(ber, elm->be_val, len);
1359		break;
1360	case BER_TYPE_OCTETSTRING:
1361	case BER_TYPE_OBJECT:
1362		elm->be_val = malloc(len + 1);
1363		if (elm->be_val == NULL)
1364			return -1;
1365		elm->be_free = 1;
1366		elm->be_len = len;
1367		ober_read(ber, elm->be_val, len);
1368		((u_char *)elm->be_val)[len] = '\0';
1369		break;
1370	case BER_TYPE_NULL:	/* no payload */
1371		if (len != 0) {
1372			errno = EINVAL;
1373			return -1;
1374		}
1375		break;
1376	case BER_TYPE_SEQUENCE:
1377	case BER_TYPE_SET:
1378		if (len > 0 && elm->be_sub == NULL) {
1379			if ((elm->be_sub = ober_get_element(0)) == NULL)
1380				return -1;
1381		}
1382		next = elm->be_sub;
1383		while (len > 0) {
1384			/*
1385			 * Prevent stack overflow from excessive recursion
1386			 * depth in ober_free_elements().
1387			 */
1388			if (elements >= BER_MAX_SEQ_ELEMENTS) {
1389				errno = ERANGE;
1390				return -1;
1391			}
1392			r = ober_read_element(ber, next);
1393			if (r == -1) {
1394				/* sub-element overflows sequence/set */
1395				if (errno == ECANCELED)
1396					errno = EINVAL;
1397				return -1;
1398			}
1399			if (r > len) {
1400				errno = EINVAL;
1401				return -1;
1402			}
1403			elements++;
1404			len -= r;
1405			if (len > 0 && next->be_next == NULL) {
1406				next->be_next = ober_get_element(0);
1407				if (next->be_next == NULL)
1408					return -1;
1409			}
1410			next = next->be_next;
1411		}
1412		break;
1413	}
1414	return totlen;
1415}
1416
1417static ssize_t
1418ober_getc(struct ber *b, u_char *c)
1419{
1420	return ober_read(b, c, 1);
1421}
1422
1423static ssize_t
1424ober_read(struct ber *ber, void *buf, size_t len)
1425{
1426	size_t	sz;
1427
1428	if (ber->br_rbuf == NULL) {
1429		errno = ENOBUFS;
1430		return -1;
1431	}
1432
1433	sz = ber->br_rend - ber->br_rptr;
1434	if (len > sz) {
1435		errno = ECANCELED;
1436		return -1;	/* parser wants more data than available */
1437	}
1438
1439	bcopy(ber->br_rptr, buf, len);
1440	ber->br_rptr += len;
1441	ber->br_offs += len;
1442
1443	return len;
1444}
1445