ber.c revision 1.20
1/*	$OpenBSD: ber.c,v 1.20 2021/01/28 19:56:33 martijn 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	*n = elm->be_numeric;
217	return 0;
218}
219
220int
221ober_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
230struct ber_element *
231ober_add_boolean(struct ber_element *prev, int bool)
232{
233	struct ber_element *elm;
234
235	if ((elm = ober_get_element(BER_TYPE_BOOLEAN)) == NULL)
236		return NULL;
237
238	elm->be_numeric = bool ? 0xff : 0;
239	elm->be_len = 1;
240
241	ober_link_elements(prev, elm);
242
243	return elm;
244}
245
246int
247ober_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
256struct ber_element *
257ober_add_string(struct ber_element *prev, const char *string)
258{
259	return ober_add_nstring(prev, string, strlen(string));
260}
261
262struct ber_element *
263ober_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 = ober_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	ober_link_elements(prev, elm);
281
282	return elm;
283}
284
285struct ber_element *
286ober_add_ostring(struct ber_element *prev, struct ber_octetstring *s)
287{
288	return ober_add_nstring(prev, s->ostr_val, s->ostr_len);
289}
290
291int
292ober_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
306int
307ober_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
317int
318ober_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
328struct ber_element *
329ober_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 = ober_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	ober_link_elements(prev, elm);
347
348	return elm;
349}
350
351int
352ober_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
362struct ber_element *
363ober_add_null(struct ber_element *prev)
364{
365	struct ber_element *elm;
366
367	if ((elm = ober_get_element(BER_TYPE_NULL)) == NULL)
368		return NULL;
369
370	ober_link_elements(prev, elm);
371
372	return elm;
373}
374
375int
376ober_get_null(struct ber_element *elm)
377{
378	if (elm->be_encoding != BER_TYPE_NULL)
379		return -1;
380
381	return 0;
382}
383
384struct ber_element *
385ober_add_eoc(struct ber_element *prev)
386{
387	struct ber_element *elm;
388
389	if ((elm = ober_get_element(BER_TYPE_EOC)) == NULL)
390		return NULL;
391
392	ober_link_elements(prev, elm);
393
394	return elm;
395}
396
397int
398ober_get_eoc(struct ber_element *elm)
399{
400	if (elm->be_encoding != BER_TYPE_EOC)
401		return -1;
402
403	return 0;
404}
405
406size_t
407ober_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
433int
434ober_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
455int
456ober_oid_cmp(struct ber_oid *a, struct ber_oid *b)
457{
458	size_t	 i;
459	for (i = 0; i < a->bo_n && i < b->bo_n; i++) {
460		if (a->bo_id[i] == b->bo_id[i])
461			continue;
462		else if (a->bo_id[i] < b->bo_id[i]) {
463			/* b is a successor of a */
464			return (1);
465		} else {
466			/* b is a predecessor of a */
467			return (-1);
468		}
469	}
470	/* b is larger, but a child of a */
471	if (a->bo_n < b->bo_n)
472		return (2);
473	/* b is a predecessor of a */
474	if (a->bo_n > b->bo_n)
475		return -1;
476
477	/* b and a are identical */
478	return (0);
479}
480
481struct ber_element *
482ober_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 = ober_get_element(BER_TYPE_OBJECT)) == NULL)
489		return (NULL);
490
491	if ((len = ober_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 (ober_oid2ber(o, buf, len) != len)
502		goto fail;
503
504	ober_link_elements(prev, elm);
505
506	return (elm);
507
508 fail:
509	ober_free_elements(elm);
510	return (NULL);
511}
512
513struct ber_element *
514ober_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 (ober_add_oid(prev, &no));
524}
525
526struct ber_element *
527ober_add_oidstring(struct ber_element *prev, const char *oidstr)
528{
529	struct ber_oid		 o;
530
531	if (ober_string2oid(oidstr, &o) == -1)
532		return (NULL);
533
534	return (ober_add_oid(prev, &o));
535}
536
537int
538ober_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	memset(o, 0, sizeof(*o));
550	o->bo_id[j++] = buf[i] / 40;
551	o->bo_id[j++] = buf[i++] % 40;
552	for (; i < len && j < BER_MAX_OID_LEN; i++) {
553		o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
554		if (buf[i] & 0x80)
555			continue;
556		j++;
557	}
558	o->bo_n = j;
559
560	return (0);
561}
562
563struct ber_element *
564ober_printf_elements(struct ber_element *ber, char *fmt, ...)
565{
566	va_list			 ap;
567	int			 d, class;
568	size_t			 len;
569	unsigned int		 type;
570	long long		 i;
571	char			*s;
572	void			*p;
573	struct ber_oid		*o;
574	struct ber_element	*sub = ber, *e;
575
576	va_start(ap, fmt);
577	while (*fmt) {
578		switch (*fmt++) {
579		case 'B':
580			p = va_arg(ap, void *);
581			len = va_arg(ap, size_t);
582			if ((ber = ober_add_bitstring(ber, p, len)) == NULL)
583				goto fail;
584			break;
585		case 'b':
586			d = va_arg(ap, int);
587			if ((ber = ober_add_boolean(ber, d)) == NULL)
588				goto fail;
589			break;
590		case 'd':
591			d = va_arg(ap, int);
592			if ((ber = ober_add_integer(ber, d)) == NULL)
593				goto fail;
594			break;
595		case 'e':
596			e = va_arg(ap, struct ber_element *);
597			ober_link_elements(ber, e);
598			break;
599		case 'E':
600			i = va_arg(ap, long long);
601			if ((ber = ober_add_enumerated(ber, i)) == NULL)
602				goto fail;
603			break;
604		case 'i':
605			i = va_arg(ap, long long);
606			if ((ber = ober_add_integer(ber, i)) == NULL)
607				goto fail;
608			break;
609		case 'O':
610			o = va_arg(ap, struct ber_oid *);
611			if ((ber = ober_add_oid(ber, o)) == NULL)
612				goto fail;
613			break;
614		case 'o':
615			s = va_arg(ap, char *);
616			if ((ber = ober_add_oidstring(ber, s)) == NULL)
617				goto fail;
618			break;
619		case 's':
620			s = va_arg(ap, char *);
621			if ((ber = ober_add_string(ber, s)) == NULL)
622				goto fail;
623			break;
624		case 't':
625			class = va_arg(ap, int);
626			type = va_arg(ap, unsigned int);
627			ober_set_header(ber, class, type);
628			break;
629		case 'x':
630			s = va_arg(ap, char *);
631			len = va_arg(ap, size_t);
632			if ((ber = ober_add_nstring(ber, s, len)) == NULL)
633				goto fail;
634			break;
635		case '0':
636			if ((ber = ober_add_null(ber)) == NULL)
637				goto fail;
638			break;
639		case '{':
640			if ((ber = sub = ober_add_sequence(ber)) == NULL)
641				goto fail;
642			break;
643		case '(':
644			if ((ber = sub = ober_add_set(ber)) == NULL)
645				goto fail;
646			break;
647		case '}':
648		case ')':
649			ber = sub;
650			break;
651		case '.':
652			if ((e = ober_add_eoc(ber)) == NULL)
653				goto fail;
654			ber = e;
655			break;
656		default:
657			break;
658		}
659	}
660	va_end(ap);
661
662	return (ber);
663 fail:
664	ober_free_elements(ber);
665	return (NULL);
666}
667
668int
669ober_scanf_elements(struct ber_element *ber, char *fmt, ...)
670{
671#define _MAX_SEQ		 128
672	va_list			 ap;
673	int			*d, level = -1;
674	unsigned int		*t;
675	long long		*i, l;
676	void			**ptr;
677	size_t			*len, ret = 0, n = strlen(fmt);
678	char			**s;
679	off_t			*pos;
680	struct ber_oid		*o;
681	struct ber_element	*parent[_MAX_SEQ], **e;
682
683	memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
684
685	va_start(ap, fmt);
686	while (*fmt) {
687		if (ber == NULL && *fmt != '$' && *fmt != '}' && *fmt != ')')
688			goto fail;
689		switch (*fmt++) {
690		case '$':
691			if (ber != NULL)
692				goto fail;
693			ret++;
694			continue;
695		case 'B':
696			ptr = va_arg(ap, void **);
697			len = va_arg(ap, size_t *);
698			if (ober_get_bitstring(ber, ptr, len) == -1)
699				goto fail;
700			ret++;
701			break;
702		case 'b':
703			d = va_arg(ap, int *);
704			if (ober_get_boolean(ber, d) == -1)
705				goto fail;
706			ret++;
707			break;
708		case 'd':
709			d = va_arg(ap, int *);
710			if (ober_get_integer(ber, &l) == -1)
711				goto fail;
712			*d = l;
713			ret++;
714			break;
715		case 'e':
716			e = va_arg(ap, struct ber_element **);
717			*e = ber;
718			ret++;
719			continue;
720		case 'E':
721			i = va_arg(ap, long long *);
722			if (ober_get_enumerated(ber, i) == -1)
723				goto fail;
724			ret++;
725			break;
726		case 'i':
727			i = va_arg(ap, long long *);
728			if (ober_get_integer(ber, i) == -1)
729				goto fail;
730			ret++;
731			break;
732		case 'o':
733			o = va_arg(ap, struct ber_oid *);
734			if (ober_get_oid(ber, o) == -1)
735				goto fail;
736			ret++;
737			break;
738		case 'S':
739			ret++;
740			break;
741		case 's':
742			s = va_arg(ap, char **);
743			if (ober_get_string(ber, s) == -1)
744				goto fail;
745			ret++;
746			break;
747		case 't':
748			d = va_arg(ap, int *);
749			t = va_arg(ap, unsigned int *);
750			*d = ber->be_class;
751			*t = ber->be_type;
752			ret++;
753			continue;
754		case 'x':
755			ptr = va_arg(ap, void **);
756			len = va_arg(ap, size_t *);
757			if (ober_get_nstring(ber, ptr, len) == -1)
758				goto fail;
759			ret++;
760			break;
761		case '0':
762			if (ber->be_encoding != BER_TYPE_NULL)
763				goto fail;
764			ret++;
765			break;
766		case '.':
767			if (ber->be_encoding != BER_TYPE_EOC)
768				goto fail;
769			ret++;
770			break;
771		case 'p':
772			pos = va_arg(ap, off_t *);
773			*pos = ober_getpos(ber);
774			ret++;
775			continue;
776		case '{':
777		case '(':
778			if (ber->be_encoding != BER_TYPE_SEQUENCE &&
779			    ber->be_encoding != BER_TYPE_SET)
780				goto fail;
781			if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
782				goto fail;
783			parent[++level] = ber;
784			ber = ber->be_sub;
785			ret++;
786			continue;
787		case '}':
788		case ')':
789			if (level < 0 || parent[level] == NULL)
790				goto fail;
791			ber = parent[level--];
792			ret++;
793			break;
794		default:
795			goto fail;
796		}
797
798		ber = ber->be_next;
799	}
800	va_end(ap);
801	return (ret == n ? 0 : -1);
802
803 fail:
804	va_end(ap);
805	return (-1);
806
807}
808
809ssize_t
810ober_get_writebuf(struct ber *b, void **buf)
811{
812	if (b->br_wbuf == NULL)
813		return -1;
814	*buf = b->br_wbuf;
815	return (b->br_wend - b->br_wbuf);
816}
817
818/*
819 * write ber elements to the write buffer
820 *
821 * params:
822 *	ber	holds the destination write buffer byte stream
823 *	root	fully populated element tree
824 *
825 * returns:
826 *	>=0	number of bytes written
827 *	-1	on failure and sets errno
828 */
829ssize_t
830ober_write_elements(struct ber *ber, struct ber_element *root)
831{
832	size_t len;
833
834	/* calculate length because only the definite form is required */
835	len = ober_calc_len(root);
836	DPRINTF("write ber element of %zd bytes length\n", len);
837
838	if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
839		free(ber->br_wbuf);
840		ber->br_wbuf = NULL;
841	}
842	if (ber->br_wbuf == NULL) {
843		if ((ber->br_wbuf = malloc(len)) == NULL)
844			return -1;
845		ber->br_wend = ber->br_wbuf + len;
846	}
847
848	/* reset write pointer */
849	ber->br_wptr = ber->br_wbuf;
850
851	if (ober_dump_element(ber, root) == -1)
852		return -1;
853
854	return (len);
855}
856
857void
858ober_set_readbuf(struct ber *b, void *buf, size_t len)
859{
860	b->br_rbuf = b->br_rptr = buf;
861	b->br_rend = (u_int8_t *)buf + len;
862}
863
864/*
865 * read ber elements from the read buffer
866 *
867 * params:
868 *	ber	holds a fully populated read buffer byte stream
869 *	root	if NULL, build up an element tree from what we receive on
870 *		the wire. If not null, use the specified encoding for the
871 *		elements received.
872 *
873 * returns:
874 *	!=NULL, elements read and store in the ber_element tree
875 *	NULL, type mismatch or read error
876 */
877struct ber_element *
878ober_read_elements(struct ber *ber, struct ber_element *elm)
879{
880	struct ber_element *root = elm;
881
882	if (root == NULL) {
883		if ((root = ober_get_element(0)) == NULL)
884			return NULL;
885	}
886
887	DPRINTF("read ber elements, root %p\n", root);
888
889	if (ober_read_element(ber, root) == -1) {
890		/* Cleanup if root was allocated by us */
891		if (elm == NULL)
892			ober_free_elements(root);
893		return NULL;
894	}
895
896	return root;
897}
898
899off_t
900ober_getpos(struct ber_element *elm)
901{
902	return elm->be_offs;
903}
904
905void
906ober_free_element(struct ber_element *root)
907{
908	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
909	    root->be_encoding == BER_TYPE_SET))
910		ober_free_elements(root->be_sub);
911	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
912	    root->be_encoding == BER_TYPE_BITSTRING ||
913	    root->be_encoding == BER_TYPE_OBJECT))
914		free(root->be_val);
915	free(root);
916}
917
918void
919ober_free_elements(struct ber_element *root)
920{
921	if (root == NULL)
922		return;
923	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
924	    root->be_encoding == BER_TYPE_SET))
925		ober_free_elements(root->be_sub);
926	if (root->be_next)
927		ober_free_elements(root->be_next);
928	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
929	    root->be_encoding == BER_TYPE_BITSTRING ||
930	    root->be_encoding == BER_TYPE_OBJECT))
931		free(root->be_val);
932	free(root);
933}
934
935size_t
936ober_calc_len(struct ber_element *root)
937{
938	unsigned int t;
939	size_t s;
940	size_t size = 2;	/* minimum 1 byte head and 1 byte size */
941
942	/* calculate the real length of a sequence or set */
943	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
944	    root->be_encoding == BER_TYPE_SET))
945		root->be_len = ober_calc_len(root->be_sub);
946
947	/* fix header length for extended types */
948	if (root->be_type > BER_TYPE_SINGLE_MAX)
949		for (t = root->be_type; t > 0; t >>= 7)
950			size++;
951	if (root->be_len >= BER_TAG_MORE)
952		for (s = root->be_len; s > 0; s >>= 8)
953			size++;
954
955	/* calculate the length of the following elements */
956	if (root->be_next)
957		size += ober_calc_len(root->be_next);
958
959	/* This is an empty element, do not use a minimal size */
960	if (root->be_class == BER_CLASS_UNIVERSAL &&
961	    root->be_type == BER_TYPE_EOC && root->be_len == 0)
962		return (0);
963
964	return (root->be_len + size);
965}
966
967void
968ober_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
969{
970	b->br_application = cb;
971}
972
973void
974ober_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
975    void *arg)
976{
977	elm->be_cb = cb;
978	elm->be_cbarg = arg;
979}
980
981void
982ober_free(struct ber *b)
983{
984	free(b->br_wbuf);
985}
986
987/*
988 * internal functions
989 */
990
991static int
992ober_dump_element(struct ber *ber, struct ber_element *root)
993{
994	unsigned long long l;
995	int i;
996	uint8_t u;
997
998	ober_dump_header(ber, root);
999	if (root->be_cb)
1000		root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1001
1002	switch (root->be_encoding) {
1003	case BER_TYPE_BOOLEAN:
1004	case BER_TYPE_INTEGER:
1005	case BER_TYPE_ENUMERATED:
1006		l = (unsigned long long)root->be_numeric;
1007		for (i = root->be_len; i > 0; i--) {
1008			u = (l >> ((i - 1) * 8)) & 0xff;
1009			ober_putc(ber, u);
1010		}
1011		break;
1012	case BER_TYPE_BITSTRING:
1013	case BER_TYPE_OCTETSTRING:
1014	case BER_TYPE_OBJECT:
1015		ober_write(ber, root->be_val, root->be_len);
1016		break;
1017	case BER_TYPE_NULL:	/* no payload */
1018	case BER_TYPE_EOC:
1019		break;
1020	case BER_TYPE_SEQUENCE:
1021	case BER_TYPE_SET:
1022		if (root->be_sub && ober_dump_element(ber, root->be_sub) == -1)
1023			return -1;
1024		break;
1025	}
1026
1027	if (root->be_next == NULL)
1028		return 0;
1029	return ober_dump_element(ber, root->be_next);
1030}
1031
1032static void
1033ober_dump_header(struct ber *ber, struct ber_element *root)
1034{
1035	u_char	id = 0, t, buf[5];
1036	unsigned int type;
1037	size_t size;
1038
1039	/* class universal, type encoding depending on type value */
1040	/* length encoding */
1041	if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1042		id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1043		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1044		    root->be_encoding == BER_TYPE_SET)
1045			id |= BER_TYPE_CONSTRUCTED;
1046
1047		ober_putc(ber, id);
1048	} else {
1049		id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1050		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1051		    root->be_encoding == BER_TYPE_SET)
1052			id |= BER_TYPE_CONSTRUCTED;
1053
1054		ober_putc(ber, id);
1055
1056		for (t = 0, type = root->be_type; type > 0; type >>= 7)
1057			buf[t++] = type & ~BER_TAG_MORE;
1058
1059		while (t-- > 0) {
1060			if (t > 0)
1061				buf[t] |= BER_TAG_MORE;
1062			ober_putc(ber, buf[t]);
1063		}
1064	}
1065
1066	if (root->be_len < BER_TAG_MORE) {
1067		/* short form */
1068		ober_putc(ber, root->be_len);
1069	} else {
1070		for (t = 0, size = root->be_len; size > 0; size >>= 8)
1071			buf[t++] = size & 0xff;
1072
1073		ober_putc(ber, t | BER_TAG_MORE);
1074
1075		while (t > 0)
1076			ober_putc(ber, buf[--t]);
1077	}
1078}
1079
1080static void
1081ober_putc(struct ber *ber, u_char c)
1082{
1083	if (ber->br_wptr + 1 <= ber->br_wend)
1084		*ber->br_wptr = c;
1085	ber->br_wptr++;
1086}
1087
1088static void
1089ober_write(struct ber *ber, void *buf, size_t len)
1090{
1091	if (ber->br_wptr + len <= ber->br_wend)
1092		bcopy(buf, ber->br_wptr, len);
1093	ber->br_wptr += len;
1094}
1095
1096/*
1097 * extract a BER encoded tag. There are two types, a short and long form.
1098 */
1099static ssize_t
1100get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1101{
1102	u_char u;
1103	size_t i = 0;
1104	unsigned int t = 0;
1105
1106	if (ober_getc(b, &u) == -1)
1107		return -1;
1108
1109	*class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1110	*cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1111
1112	if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1113		*tag = u & BER_TAG_MASK;
1114		return 1;
1115	}
1116
1117	do {
1118		if (ober_getc(b, &u) == -1)
1119			return -1;
1120
1121		/* enforce minimal number of octets for tag > 30 */
1122		if (i == 0 && (u & ~BER_TAG_MORE) == 0) {
1123			errno = EINVAL;
1124			return -1;
1125		}
1126
1127		t = (t << 7) | (u & ~BER_TAG_MORE);
1128		i++;
1129		if (i > sizeof(unsigned int)) {
1130			errno = ERANGE;
1131			return -1;
1132		}
1133	} while (u & BER_TAG_MORE);
1134
1135	*tag = t;
1136	return i + 1;
1137}
1138
1139/*
1140 * extract length of a ber object -- if length is unknown an error is returned.
1141 */
1142static ssize_t
1143get_len(struct ber *b, ssize_t *len)
1144{
1145	u_char	u, n;
1146	ssize_t	s, r;
1147
1148	if (ober_getc(b, &u) == -1)
1149		return -1;
1150	if ((u & BER_TAG_MORE) == 0) {
1151		/* short form */
1152		*len = u;
1153		return 1;
1154	}
1155
1156	if (u == 0x80) {
1157		/* Indefinite length not supported. */
1158		errno = EINVAL;
1159		return -1;
1160	}
1161
1162	if (u == 0xff) {
1163		/* Reserved for future use. */
1164		errno = EINVAL;
1165		return -1;
1166	}
1167
1168	n = u & ~BER_TAG_MORE;
1169	/*
1170	 * Limit to a decent size that works on all of our architectures.
1171	 */
1172	if (sizeof(int32_t) < n) {
1173		errno = ERANGE;
1174		return -1;
1175	}
1176	r = n + 1;
1177
1178	for (s = 0; n > 0; n--) {
1179		if (ober_getc(b, &u) == -1)
1180			return -1;
1181		s = (s << 8) | u;
1182	}
1183
1184	if (s < 0) {
1185		/* overflow */
1186		errno = ERANGE;
1187		return -1;
1188	}
1189
1190	*len = s;
1191	return r;
1192}
1193
1194static ssize_t
1195ober_read_element(struct ber *ber, struct ber_element *elm)
1196{
1197	long long val = 0;
1198	struct ber_element *next;
1199	unsigned int type;
1200	int i, class, cstruct, elements = 0;
1201	ssize_t len, r, totlen = 0;
1202	u_char c, last = 0;
1203
1204	if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1205		return -1;
1206	DPRINTF("ber read got class %d type %u, %s\n",
1207	    class, type, cstruct ? "constructed" : "primitive");
1208	totlen += r;
1209	if ((r = get_len(ber, &len)) == -1)
1210		return -1;
1211	DPRINTF("ber read element size %zd\n", len);
1212	totlen += r + len;
1213
1214	/* The encoding of boolean, integer, enumerated, and null values
1215	 * must be primitive. */
1216	if (class == BER_CLASS_UNIVERSAL)
1217		if (type == BER_TYPE_BOOLEAN ||
1218		    type == BER_TYPE_INTEGER ||
1219		    type == BER_TYPE_ENUMERATED ||
1220		    type == BER_TYPE_NULL)
1221			if (cstruct) {
1222				errno = EINVAL;
1223				return -1;
1224			}
1225
1226	/* If the total size of the element is larger than the buffer
1227	 * don't bother to continue. */
1228	if (len > ber->br_rend - ber->br_rptr) {
1229		errno = ECANCELED;
1230		return -1;
1231	}
1232
1233	elm->be_type = type;
1234	elm->be_len = len;
1235	elm->be_offs = ber->br_offs;	/* element position within stream */
1236	elm->be_class = class;
1237
1238	if (elm->be_encoding == 0) {
1239		/* try to figure out the encoding via class, type and cstruct */
1240		if (cstruct)
1241			elm->be_encoding = BER_TYPE_SEQUENCE;
1242		else if (class == BER_CLASS_UNIVERSAL)
1243			elm->be_encoding = type;
1244		else if (ber->br_application != NULL) {
1245			/*
1246			 * Ask the application to map the encoding to a
1247			 * universal type. For example, a SMI IpAddress
1248			 * type is defined as 4 byte OCTET STRING.
1249			 */
1250			elm->be_encoding = (*ber->br_application)(elm);
1251		} else
1252			/* last resort option */
1253			elm->be_encoding = BER_TYPE_NULL;
1254	}
1255
1256	switch (elm->be_encoding) {
1257	case BER_TYPE_EOC:	/* End-Of-Content */
1258		break;
1259	case BER_TYPE_BOOLEAN:
1260		if (len != 1) {
1261			errno = EINVAL;
1262			return -1;
1263		}
1264	case BER_TYPE_INTEGER:
1265	case BER_TYPE_ENUMERATED:
1266		if (len < 1) {
1267			errno = EINVAL;
1268			return -1;
1269		}
1270		if (len > (ssize_t)sizeof(long long)) {
1271			errno = ERANGE;
1272			return -1;
1273		}
1274		for (i = 0; i < len; i++) {
1275			if (ober_getc(ber, &c) != 1)
1276				return -1;
1277
1278			/* smallest number of contents octets only */
1279			if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1280			    (i == 1 && last == 0xff && (c & 0x80) != 0)) {
1281				errno = EINVAL;
1282				return -1;
1283			}
1284
1285			val <<= 8;
1286			val |= c;
1287			last = c;
1288		}
1289
1290		/* sign extend if MSB is set */
1291		if (len < (ssize_t)sizeof(long long) &&
1292		    (val >> ((len - 1) * 8) & 0x80))
1293			val |= ULLONG_MAX << (len * 8);
1294		elm->be_numeric = val;
1295		break;
1296	case BER_TYPE_BITSTRING:
1297		elm->be_val = malloc(len);
1298		if (elm->be_val == NULL)
1299			return -1;
1300		elm->be_free = 1;
1301		elm->be_len = len;
1302		ober_read(ber, elm->be_val, len);
1303		break;
1304	case BER_TYPE_OCTETSTRING:
1305	case BER_TYPE_OBJECT:
1306		elm->be_val = malloc(len + 1);
1307		if (elm->be_val == NULL)
1308			return -1;
1309		elm->be_free = 1;
1310		elm->be_len = len;
1311		ober_read(ber, elm->be_val, len);
1312		((u_char *)elm->be_val)[len] = '\0';
1313		break;
1314	case BER_TYPE_NULL:	/* no payload */
1315		if (len != 0) {
1316			errno = EINVAL;
1317			return -1;
1318		}
1319		break;
1320	case BER_TYPE_SEQUENCE:
1321	case BER_TYPE_SET:
1322		if (elm->be_sub == NULL) {
1323			if ((elm->be_sub = ober_get_element(0)) == NULL)
1324				return -1;
1325		}
1326		next = elm->be_sub;
1327		while (len > 0) {
1328			/*
1329			 * Prevent stack overflow from excessive recursion
1330			 * depth in ober_free_elements().
1331			 */
1332			if (elements >= BER_MAX_SEQ_ELEMENTS) {
1333				errno = ERANGE;
1334				return -1;
1335			}
1336			r = ober_read_element(ber, next);
1337			if (r == -1)
1338				return -1;
1339			elements++;
1340			len -= r;
1341			if (len > 0 && next->be_next == NULL) {
1342				if ((next->be_next = ober_get_element(0)) ==
1343				    NULL)
1344					return -1;
1345			}
1346			next = next->be_next;
1347		}
1348		break;
1349	}
1350	return totlen;
1351}
1352
1353static ssize_t
1354ober_getc(struct ber *b, u_char *c)
1355{
1356	return ober_read(b, c, 1);
1357}
1358
1359static ssize_t
1360ober_read(struct ber *ber, void *buf, size_t len)
1361{
1362	size_t	sz;
1363
1364	if (ber->br_rbuf == NULL) {
1365		errno = ENOBUFS;
1366		return -1;
1367	}
1368
1369	sz = ber->br_rend - ber->br_rptr;
1370	if (len > sz) {
1371		errno = ECANCELED;
1372		return -1;	/* parser wants more data than available */
1373	}
1374
1375	bcopy(ber->br_rptr, buf, len);
1376	ber->br_rptr += len;
1377	ber->br_offs += len;
1378
1379	return len;
1380}
1381