xref: /freebsd/contrib/bsnmp/lib/asn1.c (revision c697fb7f)
1 /*
2  * Copyright (c) 2001-2003
3  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *	All rights reserved.
5  *
6  * Author: Harti Brandt <harti@freebsd.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $Begemot: bsnmp/lib/asn1.c,v 1.31 2005/10/06 07:14:58 brandt_h Exp $
30  *
31  * ASN.1 for SNMP.
32  */
33 #include <sys/types.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #ifdef HAVE_STDINT_H
39 #include <stdint.h>
40 #elif defined(HAVE_INTTYPES_H)
41 #include <inttypes.h>
42 #endif
43 #include <assert.h>
44 
45 #include "support.h"
46 #include "asn1.h"
47 
48 static void asn_error_func(const struct asn_buf *, const char *, ...);
49 
50 void (*asn_error)(const struct asn_buf *, const char *, ...) = asn_error_func;
51 
52 /*
53  * Read the next header. This reads the tag (note, that only single
54  * byte tags are supported for now) and the length field. The length field
55  * is restricted to a 32-bit value.
56  * All errors of this function stop the decoding.
57  */
58 enum asn_err
59 asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len)
60 {
61 	u_int length;
62 
63 	if (b->asn_len == 0) {
64 		asn_error(b, "no identifier for header");
65 		return (ASN_ERR_EOBUF);
66 	}
67 	*type = *b->asn_cptr;
68 	if ((*type & ASN_TYPE_MASK) > 0x30) {
69 		asn_error(b, "types > 0x30 not supported (%u)",
70 		    *type & ASN_TYPE_MASK);
71 		return (ASN_ERR_FAILED);
72 	}
73 	b->asn_cptr++;
74 	b->asn_len--;
75 	if (b->asn_len == 0) {
76 		asn_error(b, "no length field");
77 		return (ASN_ERR_EOBUF);
78 	}
79 	if (*b->asn_cptr & 0x80) {
80 		length = *b->asn_cptr++ & 0x7f;
81 		b->asn_len--;
82 		if (length == 0) {
83 			asn_error(b, "indefinite length not supported");
84 			return (ASN_ERR_FAILED);
85 		}
86 		if (length > ASN_MAXLENLEN) {
87 			asn_error(b, "long length too long (%u)", length);
88 			return (ASN_ERR_FAILED);
89 		}
90 		if (length > b->asn_len) {
91 			asn_error(b, "long length truncated");
92 			return (ASN_ERR_EOBUF);
93 		}
94 		*len = 0;
95 		while (length--) {
96 			*len = (*len << 8) | *b->asn_cptr++;
97 			b->asn_len--;
98 		}
99 	} else {
100 		*len = *b->asn_cptr++;
101 		b->asn_len--;
102 	}
103 	if (*len > b->asn_len) {
104 		asn_error(b, "len %u exceeding asn_len %u", *len, b->asn_len);
105 		return (ASN_ERR_EOBUF);
106 	}
107 
108 	return (ASN_ERR_OK);
109 }
110 
111 /*
112  * Write a length field (restricted to values < 2^32-1) and return the
113  * number of bytes this field takes. If ptr is NULL, the length is computed
114  * but nothing is written. If the length would be too large return 0.
115  */
116 static u_int
117 asn_put_len(u_char *ptr, asn_len_t len)
118 {
119 	u_int lenlen, lenlen1;
120 	asn_len_t tmp;
121 
122 	if (len > ASN_MAXLEN) {
123 		asn_error(NULL, "encoding length too long: (%u)", len);
124 		return (0);
125 	}
126 
127 	if (len <= 127) {
128 		if (ptr)
129 			*ptr++ = (u_char)len;
130 		return (1);
131 	} else {
132 		lenlen = 0;
133 		/* compute number of bytes for value (is at least 1) */
134 		for (tmp = len; tmp != 0; tmp >>= 8)
135 			lenlen++;
136 		if (ptr != NULL) {
137 			*ptr++ = (u_char)lenlen | 0x80;
138 			lenlen1 = lenlen;
139 			while (lenlen1-- > 0) {
140 				ptr[lenlen1] = len & 0xff;
141 				len >>= 8;
142 			}
143 		}
144 		return (lenlen + 1);
145 	}
146 }
147 
148 /*
149  * Write a header (tag and length fields).
150  * Tags are restricted to one byte tags (value <= 0x30) and the
151  * lenght field to 16-bit. All errors stop the encoding.
152  */
153 enum asn_err
154 asn_put_header(struct asn_buf *b, u_char type, asn_len_t len)
155 {
156 	u_int lenlen;
157 
158 	/* tag field */
159 	if ((type & ASN_TYPE_MASK) > 0x30) {
160 		asn_error(NULL, "types > 0x30 not supported (%u)",
161 		    type & ASN_TYPE_MASK);
162 		return (ASN_ERR_FAILED);
163 	}
164 	if (b->asn_len == 0)
165 		return (ASN_ERR_EOBUF);
166 
167 	*b->asn_ptr++ = type;
168 	b->asn_len--;
169 
170 	/* length field */
171 	if ((lenlen = asn_put_len(NULL, len)) == 0)
172 		return (ASN_ERR_FAILED);
173 	if (b->asn_len < lenlen)
174 		return (ASN_ERR_EOBUF);
175 
176 	(void)asn_put_len(b->asn_ptr, len);
177 	b->asn_ptr += lenlen;
178 	b->asn_len -= lenlen;
179 	return (ASN_ERR_OK);
180 }
181 
182 
183 /*
184  * This constructs a temporary sequence header with space for the maximum
185  * length field (three byte). Set the pointer that ptr points to to the
186  * start of the encoded header. This is used for a later call to
187  * asn_commit_header which will fix-up the length field and move the
188  * value if needed. All errors should stop the encoding.
189  */
190 #define	TEMP_LEN (1 + ASN_MAXLENLEN + 1)
191 enum asn_err
192 asn_put_temp_header(struct asn_buf *b, u_char type, u_char **ptr)
193 {
194 	int ret;
195 
196 	if (b->asn_len < TEMP_LEN)
197 		return (ASN_ERR_EOBUF);
198 	*ptr = b->asn_ptr;
199 	if ((ret = asn_put_header(b, type, ASN_MAXLEN)) == ASN_ERR_OK)
200 		assert(b->asn_ptr == *ptr + TEMP_LEN);
201 	return (ret);
202 }
203 enum asn_err
204 asn_commit_header(struct asn_buf *b, u_char *ptr, size_t *moved)
205 {
206 	asn_len_t len;
207 	u_int lenlen, shift;
208 
209 	/* compute length of encoded value without header */
210 	len = b->asn_ptr - (ptr + TEMP_LEN);
211 
212 	/* insert length. may not fail. */
213 	lenlen = asn_put_len(ptr + 1, len);
214 	if (lenlen > TEMP_LEN - 1)
215 		return (ASN_ERR_FAILED);
216 
217 	if (lenlen < TEMP_LEN - 1) {
218 		/* shift value down */
219 		shift = (TEMP_LEN - 1) - lenlen;
220 		memmove(ptr + 1 + lenlen, ptr + TEMP_LEN, len);
221 		b->asn_ptr -= shift;
222 		b->asn_len += shift;
223 		if (moved != NULL)
224 			*moved = shift;
225 	}
226 	return (ASN_ERR_OK);
227 }
228 #undef TEMP_LEN
229 
230 /*
231  * BER integer. This may be used to get a signed 64 bit integer at maximum.
232  * The maximum length should be checked by the caller. This cannot overflow
233  * if the caller ensures that len is at maximum 8.
234  *
235  * <bytes>
236  */
237 static enum asn_err
238 asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp)
239 {
240 	uint64_t val;
241 	int neg = 0;
242 	enum asn_err err;
243 
244 	if (b->asn_len < len) {
245 		asn_error(b, "truncated integer");
246 		return (ASN_ERR_EOBUF);
247 	}
248 	if (len == 0) {
249 		asn_error(b, "zero-length integer");
250 		*vp = 0;
251 		return (ASN_ERR_BADLEN);
252 	}
253 	err = ASN_ERR_OK;
254 	if (len > 8)
255 		err = ASN_ERR_RANGE;
256 	else if (len > 1 &&
257 	    ((*b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) ||
258 	    (*b->asn_cptr == 0xff && (b->asn_cptr[1] & 0x80) == 0x80))) {
259 		asn_error(b, "non-minimal integer");
260 		err = ASN_ERR_BADLEN;
261 	}
262 
263 	if (*b->asn_cptr & 0x80)
264 		neg = 1;
265 	val = 0;
266 	while (len--) {
267 		val <<= 8;
268 		val |= neg ? (u_char)~*b->asn_cptr : *b->asn_cptr;
269 		b->asn_len--;
270 		b->asn_cptr++;
271 	}
272 	if (neg) {
273 		*vp = -(int64_t)val - 1;
274 	} else
275 		*vp = (int64_t)val;
276 	return (err);
277 }
278 
279 /*
280  * Write a signed integer with the given type. The caller has to ensure
281  * that the actual value is ok for this type.
282  */
283 static enum asn_err
284 asn_put_real_integer(struct asn_buf *b, u_char type, int64_t ival)
285 {
286 	int i, neg = 0;
287 # define OCTETS 8
288 	u_char buf[OCTETS];
289 	uint64_t val;
290 	enum asn_err ret;
291 
292 	if (ival < 0) {
293 		/* this may fail if |INT64_MIN| > |INT64_MAX| and
294 		 * the value is between * INT64_MIN <= ival < -(INT64_MAX+1) */
295 		val = (uint64_t)-(ival + 1);
296 		neg = 1;
297 	} else
298 		val = (uint64_t)ival;
299 
300 	/* split the value into octets */
301 	for (i = OCTETS - 1; i >= 0; i--) {
302 		buf[i] = val & 0xff;
303 		if (neg)
304 			buf[i] = ~buf[i];
305 		val >>= 8;
306 	}
307 	/* no leading 9 zeroes or ones */
308 	for (i = 0; i < OCTETS - 1; i++)
309 		if (!((buf[i] == 0xff && (buf[i + 1] & 0x80) != 0) ||
310 		    (buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0)))
311 			break;
312 	if ((ret = asn_put_header(b, type, OCTETS - i)))
313 		return (ret);
314 	if (OCTETS - (u_int)i > b->asn_len)
315 		return (ASN_ERR_EOBUF);
316 
317 	while (i < OCTETS) {
318 		*b->asn_ptr++ = buf[i++];
319 		b->asn_len--;
320 	}
321 	return (ASN_ERR_OK);
322 # undef OCTETS
323 }
324 
325 
326 /*
327  * The same for unsigned 64-bitters. Here we have the problem, that overflow
328  * can happen, because the value maybe 9 bytes long. In this case the
329  * first byte must be 0.
330  */
331 static enum asn_err
332 asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, uint64_t *vp)
333 {
334 	enum asn_err err;
335 
336 	if (b->asn_len < len) {
337 		asn_error(b, "truncated integer");
338 		return (ASN_ERR_EOBUF);
339 	}
340 	if (len == 0) {
341 		asn_error(b, "zero-length integer");
342 		*vp = 0;
343 		return (ASN_ERR_BADLEN);
344 	}
345 	err = ASN_ERR_OK;
346 	*vp = 0;
347 	if ((*b->asn_cptr & 0x80) || (len == 9 && *b->asn_cptr != 0)) {
348 		/* negative integer or too larger */
349 		*vp = 0xffffffffffffffffULL;
350 		err = ASN_ERR_RANGE;
351 	} else if (len > 1 &&
352 	    *b->asn_cptr == 0x00 && (b->asn_cptr[1] & 0x80) == 0) {
353 		asn_error(b, "non-minimal unsigned");
354 		err = ASN_ERR_BADLEN;
355 	}
356 
357 	while (len--) {
358 		*vp = (*vp << 8) | *b->asn_cptr++;
359 		b->asn_len--;
360 	}
361 	return (err);
362 }
363 
364 
365 /*
366  * Values with the msb on need 9 octets.
367  */
368 static int
369 asn_put_real_unsigned(struct asn_buf *b, u_char type, uint64_t val)
370 {
371 	int i;
372 # define OCTETS 9
373 	u_char buf[OCTETS];
374 	enum asn_err ret;
375 
376 	/* split the value into octets */
377 	for (i = OCTETS - 1; i >= 0; i--) {
378 		buf[i] = val & 0xff;
379 		val >>= 8;
380 	}
381 	/* no leading 9 zeroes */
382 	for (i = 0; i < OCTETS - 1; i++)
383 		if (!(buf[i] == 0x00 && (buf[i + 1] & 0x80) == 0))
384 			break;
385 	if ((ret = asn_put_header(b, type, OCTETS - i)))
386 		return (ret);
387 	if (OCTETS - (u_int)i > b->asn_len)
388 		return (ASN_ERR_EOBUF);
389 
390 	while (i < OCTETS) {
391 		*b->asn_ptr++ = buf[i++];
392 		b->asn_len--;
393 	}
394 #undef OCTETS
395 	return (ASN_ERR_OK);
396 }
397 
398 /*
399  * The ASN.1 INTEGER type is restricted to 32-bit signed by the SMI.
400  */
401 enum asn_err
402 asn_get_integer_raw(struct asn_buf *b, asn_len_t len, int32_t *vp)
403 {
404 	int64_t val;
405 	enum asn_err ret;
406 
407 	if ((ret = asn_get_real_integer(b, len, &val)) == ASN_ERR_OK) {
408 		if (len > 4)
409 			ret = ASN_ERR_BADLEN;
410 		else if (val > INT32_MAX || val < INT32_MIN)
411 			/* may not happen */
412 			ret = ASN_ERR_RANGE;
413 		*vp = (int32_t)val;
414 	}
415 	return (ret);
416 }
417 
418 enum asn_err
419 asn_get_integer(struct asn_buf *b, int32_t *vp)
420 {
421 	asn_len_t len;
422 	u_char type;
423 	enum asn_err err;
424 
425 	if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
426 		return (err);
427 	if (type != ASN_TYPE_INTEGER) {
428 		asn_error(b, "bad type for integer (%u)", type);
429 		return (ASN_ERR_TAG);
430 	}
431 
432 	return (asn_get_integer_raw(b, len, vp));
433 }
434 
435 enum asn_err
436 asn_put_integer(struct asn_buf *b, int32_t val)
437 {
438 	return (asn_put_real_integer(b, ASN_TYPE_INTEGER, val));
439 }
440 
441 /*
442  * OCTETSTRING
443  *
444  * <0x04> <len> <data ...>
445  *
446  * Get an octetstring. noctets must point to the buffer size and on
447  * return will contain the size of the octetstring, regardless of the
448  * buffer size.
449  */
450 enum asn_err
451 asn_get_octetstring_raw(struct asn_buf *b, asn_len_t len, u_char *octets,
452     u_int *noctets)
453 {
454 	enum asn_err err = ASN_ERR_OK;
455 
456 	if (*noctets < len) {
457 		asn_error(b, "octetstring truncated");
458 		err = ASN_ERR_RANGE;
459 	}
460 	if (b->asn_len < len) {
461 		asn_error(b, "truncatet octetstring");
462 		return (ASN_ERR_EOBUF);
463 	}
464 	if (*noctets < len)
465 		memcpy(octets, b->asn_cptr, *noctets);
466 	else
467 		memcpy(octets, b->asn_cptr, len);
468 	*noctets = len;
469 	b->asn_cptr += len;
470 	b->asn_len -= len;
471 	return (err);
472 }
473 
474 enum asn_err
475 asn_get_octetstring(struct asn_buf *b, u_char *octets, u_int *noctets)
476 {
477 	enum asn_err err;
478 	u_char type;
479 	asn_len_t len;
480 
481 	if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
482 		return (err);
483 	if (type != ASN_TYPE_OCTETSTRING) {
484 		asn_error(b, "bad type for octetstring (%u)", type);
485 		return (ASN_ERR_TAG);
486 	}
487 	return (asn_get_octetstring_raw(b, len, octets, noctets));
488 }
489 
490 enum asn_err
491 asn_put_octetstring(struct asn_buf *b, const u_char *octets, u_int noctets)
492 {
493 	enum asn_err ret;
494 
495 	if ((ret = asn_put_header(b, ASN_TYPE_OCTETSTRING, noctets)) != ASN_ERR_OK)
496 		return (ret);
497 	if (b->asn_len < noctets)
498 		return (ASN_ERR_EOBUF);
499 
500 	memcpy(b->asn_ptr, octets, noctets);
501 	b->asn_ptr += noctets;
502 	b->asn_len -= noctets;
503 	return (ASN_ERR_OK);
504 }
505 
506 /*
507  * NULL
508  *
509  * <0x05> <0x00>
510  */
511 enum asn_err
512 asn_get_null_raw(struct asn_buf *b, asn_len_t len)
513 {
514 	if (len != 0) {
515 		if (b->asn_len < len) {
516 			asn_error(b, "truncated NULL");
517 			return (ASN_ERR_EOBUF);
518 		}
519 		asn_error(b, "bad length for NULL (%u)", len);
520 		b->asn_len -= len;
521 		b->asn_ptr += len;
522 		return (ASN_ERR_BADLEN);
523 	}
524 	return (ASN_ERR_OK);
525 }
526 
527 enum asn_err
528 asn_get_null(struct asn_buf *b)
529 {
530 	u_char type;
531 	asn_len_t len;
532 	enum asn_err err;
533 
534 	if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
535 		return (err);
536 	if (type != ASN_TYPE_NULL) {
537 		asn_error(b, "bad type for NULL (%u)", type);
538 		return (ASN_ERR_TAG);
539 	}
540 	return (asn_get_null_raw(b, len));
541 }
542 
543 enum asn_err
544 asn_put_null(struct asn_buf *b)
545 {
546 	return (asn_put_header(b, ASN_TYPE_NULL, 0));
547 }
548 
549 enum asn_err
550 asn_put_exception(struct asn_buf *b, u_int except)
551 {
552 	return (asn_put_header(b, ASN_CLASS_CONTEXT | except, 0));
553 }
554 
555 /*
556  * OBJID
557  *
558  * <0x06> <len> <subid...>
559  */
560 enum asn_err
561 asn_get_objid_raw(struct asn_buf *b, asn_len_t len, struct asn_oid *oid)
562 {
563 	asn_subid_t subid;
564 	enum asn_err err;
565 
566 	if (b->asn_len < len) {
567 		asn_error(b, "truncated OBJID");
568 		return (ASN_ERR_EOBUF);
569 	}
570 	oid->len = 0;
571 	if (len == 0) {
572 		asn_error(b, "short OBJID");
573 		oid->subs[oid->len++] = 0;
574 		oid->subs[oid->len++] = 0;
575 		return (ASN_ERR_BADLEN);
576 	}
577 	err = ASN_ERR_OK;
578 	while (len != 0) {
579 		if (oid->len == ASN_MAXOIDLEN) {
580 			asn_error(b, "OID too long (%u)", oid->len);
581 			b->asn_cptr += len;
582 			b->asn_len -= len;
583 			return (ASN_ERR_BADLEN);
584 		}
585 		subid = 0;
586 		do {
587 			if (len == 0) {
588 				asn_error(b, "unterminated subid");
589 				return (ASN_ERR_EOBUF);
590 			}
591 			if (subid > (ASN_MAXID >> 7)) {
592 				asn_error(b, "OBID subid too larger");
593 				err = ASN_ERR_RANGE;
594 			}
595 			subid = (subid << 7) | (*b->asn_cptr & 0x7f);
596 			len--;
597 			b->asn_len--;
598 		} while (*b->asn_cptr++ & 0x80);
599 		if (oid->len == 0) {
600 			if (subid < 80) {
601 				oid->subs[oid->len++] = subid / 40;
602 				oid->subs[oid->len++] = subid % 40;
603 			} else {
604 				oid->subs[oid->len++] = 2;
605 				oid->subs[oid->len++] = subid - 80;
606 			}
607 		} else {
608 			oid->subs[oid->len++] = subid;
609 		}
610 	}
611 	return (err);
612 
613 }
614 
615 enum asn_err
616 asn_get_objid(struct asn_buf *b, struct asn_oid *oid)
617 {
618 	u_char type;
619 	asn_len_t len;
620 	enum asn_err err;
621 
622 	if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
623 		return (err);
624 	if (type != ASN_TYPE_OBJID) {
625 		asn_error(b, "bad type for OBJID (%u)", type);
626 		return (ASN_ERR_TAG);
627 	}
628 	return (asn_get_objid_raw(b, len, oid));
629 }
630 
631 enum asn_err
632 asn_put_objid(struct asn_buf *b, const struct asn_oid *oid)
633 {
634 	asn_subid_t first, sub;
635 	enum asn_err err, err1;
636 	u_int i, oidlen;
637 	asn_len_t len;
638 
639 	err = ASN_ERR_OK;
640 	if (oid->len == 0) {
641 		/* illegal */
642 		asn_error(NULL, "short oid");
643 		err = ASN_ERR_RANGE;
644 		first = 0;
645 		oidlen = 2;
646 	} else if (oid->len == 1) {
647 		/* illegal */
648 		asn_error(b, "short oid");
649 		if (oid->subs[0] > 2)
650 			asn_error(NULL, "oid[0] too large (%u)", oid->subs[0]);
651 		err = ASN_ERR_RANGE;
652 		first = oid->subs[0] * 40;
653 		oidlen = 2;
654 	} else {
655 		if (oid->len > ASN_MAXOIDLEN) {
656 			asn_error(NULL, "oid too long %u", oid->len);
657 			err = ASN_ERR_RANGE;
658 		}
659 		if (oid->subs[0] > 2 ||
660 		    (oid->subs[0] < 2 && oid->subs[1] >= 40)) {
661 			asn_error(NULL, "oid out of range (%u,%u)",
662 			    oid->subs[0], oid->subs[1]);
663 			err = ASN_ERR_RANGE;
664 		}
665 		first = 40 * oid->subs[0] + oid->subs[1];
666 		oidlen = oid->len;
667 	}
668 	len = 0;
669 	for (i = 1; i < oidlen; i++) {
670 		sub = (i == 1) ? first : oid->subs[i];
671 		if (sub > ASN_MAXID) {
672 			asn_error(NULL, "oid subid too large");
673 			err = ASN_ERR_RANGE;
674 		}
675 		len += (sub <= 0x7f) ? 1
676 		    : (sub <= 0x3fff) ? 2
677 		    : (sub <= 0x1fffff) ? 3
678 		    : (sub <= 0xfffffff) ? 4
679 		    : 5;
680 	}
681 	if ((err1 = asn_put_header(b, ASN_TYPE_OBJID, len)) != ASN_ERR_OK)
682 		return (err1);
683 	if (b->asn_len < len)
684 		return (ASN_ERR_EOBUF);
685 
686 	for (i = 1; i < oidlen; i++) {
687 		sub = (i == 1) ? first : oid->subs[i];
688 		if (sub <= 0x7f) {
689 			*b->asn_ptr++ = sub;
690 			b->asn_len--;
691 		} else if (sub <= 0x3fff) {
692 			*b->asn_ptr++ = (sub >> 7) | 0x80;
693 			*b->asn_ptr++ = sub & 0x7f;
694 			b->asn_len -= 2;
695 		} else if (sub <= 0x1fffff) {
696 			*b->asn_ptr++ = (sub >> 14) | 0x80;
697 			*b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
698 			*b->asn_ptr++ = sub & 0x7f;
699 			b->asn_len -= 3;
700 		} else if (sub <= 0xfffffff) {
701 			*b->asn_ptr++ = (sub >> 21) | 0x80;
702 			*b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80;
703 			*b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
704 			*b->asn_ptr++ = sub & 0x7f;
705 			b->asn_len -= 4;
706 		} else {
707 			*b->asn_ptr++ = (sub >> 28) | 0x80;
708 			*b->asn_ptr++ = ((sub >> 21) & 0x7f) | 0x80;
709 			*b->asn_ptr++ = ((sub >> 14) & 0x7f) | 0x80;
710 			*b->asn_ptr++ = ((sub >> 7) & 0x7f) | 0x80;
711 			*b->asn_ptr++ = sub & 0x7f;
712 			b->asn_len -= 5;
713 		}
714 	}
715 	return (err);
716 }
717 /*
718  * SEQUENCE header
719  *
720  * <0x10|0x20> <len> <data...>
721  */
722 enum asn_err
723 asn_get_sequence(struct asn_buf *b, asn_len_t *len)
724 {
725 	u_char type;
726 	enum asn_err err;
727 
728 	if ((err = asn_get_header(b, &type, len)) != ASN_ERR_OK)
729 		return (err);
730 	if (type != (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED)) {
731 		asn_error(b, "bad sequence type %u", type);
732 		return (ASN_ERR_TAG);
733 	}
734 	if (*len > b->asn_len) {
735 		asn_error(b, "truncated sequence");
736 		return (ASN_ERR_EOBUF);
737 	}
738 	return (ASN_ERR_OK);
739 }
740 
741 /*
742  * Application types
743  *
744  * 0x40 4 MSB 2MSB 2LSB LSB
745  */
746 enum asn_err
747 asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr)
748 {
749 	u_int i;
750 
751 	if (b->asn_len < len) {
752 		asn_error(b, "truncated ip-address");
753 		return (ASN_ERR_EOBUF);
754 	}
755 	if (len < 4) {
756 		asn_error(b, "short length for ip-Address %u", len);
757 		for (i = 0; i < len; i++)
758 			*addr++ = *b->asn_cptr++;
759 		while (i++ < len)
760 			*addr++ = 0;
761 		b->asn_len -= len;
762 		return (ASN_ERR_BADLEN);
763 	}
764 	for (i = 0; i < 4; i++)
765 		*addr++ = *b->asn_cptr++;
766 	b->asn_cptr += len - 4;
767 	b->asn_len -= len;
768 	return (ASN_ERR_OK);
769 }
770 
771 enum asn_err
772 asn_get_ipaddress(struct asn_buf *b, u_char *addr)
773 {
774 	u_char type;
775 	asn_len_t len;
776 	enum asn_err err;
777 
778 	if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
779 		return (err);
780 	if (type != (ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS)) {
781 		asn_error(b, "bad type for ip-address %u", type);
782 		return (ASN_ERR_TAG);
783 	}
784 	return (asn_get_ipaddress_raw(b, len, addr));
785 }
786 
787 enum asn_err
788 asn_put_ipaddress(struct asn_buf *b, const u_char *addr)
789 {
790 	enum asn_err err;
791 
792 	if ((err = asn_put_header(b, ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS,
793 	    4)) != ASN_ERR_OK)
794 		return (err);
795 	if (b->asn_len < 4)
796 		return (ASN_ERR_EOBUF);
797 
798 	memcpy(b->asn_ptr, addr, 4);
799 	b->asn_ptr += 4;
800 	b->asn_len -= 4;
801 	return (ASN_ERR_OK);
802 }
803 
804 
805 /*
806  * UNSIGNED32
807  *
808  * 0x42|0x41 <len> ...
809  */
810 enum asn_err
811 asn_get_uint32_raw(struct asn_buf *b, asn_len_t len, uint32_t *vp)
812 {
813 	uint64_t v;
814 	enum asn_err err;
815 
816 	if ((err = asn_get_real_unsigned(b, len, &v)) == ASN_ERR_OK) {
817 		if (len > 5) {
818 			asn_error(b, "uint32 too long %u", len);
819 			err = ASN_ERR_BADLEN;
820 		} else if (v > UINT32_MAX) {
821 			asn_error(b, "uint32 too large %llu", v);
822 			err = ASN_ERR_RANGE;
823 		}
824 		*vp = (uint32_t)v;
825 	}
826 	return (err);
827 }
828 
829 enum asn_err
830 asn_put_uint32(struct asn_buf *b, u_char type, uint32_t val)
831 {
832 	uint64_t v = val;
833 
834 	return (asn_put_real_unsigned(b, ASN_CLASS_APPLICATION|type, v));
835 }
836 
837 /*
838  * COUNTER64
839  * 0x46 <len> ...
840  */
841 enum asn_err
842 asn_get_counter64_raw(struct asn_buf *b, asn_len_t len, uint64_t *vp)
843 {
844 	return (asn_get_real_unsigned(b, len, vp));
845 }
846 
847 enum asn_err
848 asn_put_counter64(struct asn_buf *b, uint64_t val)
849 {
850 	return (asn_put_real_unsigned(b,
851 	    ASN_CLASS_APPLICATION | ASN_APP_COUNTER64, val));
852 }
853 
854 /*
855  * TimeTicks
856  * 0x43 <len> ...
857  */
858 enum asn_err
859 asn_get_timeticks(struct asn_buf *b, uint32_t *vp)
860 {
861 	asn_len_t len;
862 	u_char type;
863 	enum asn_err err;
864 
865 	if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK)
866 		return (err);
867 	if (type != (ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS)) {
868 		asn_error(b, "bad type for timeticks %u", type);
869 		return (ASN_ERR_TAG);
870 	}
871 	return (asn_get_uint32_raw(b, len, vp));
872 }
873 
874 enum asn_err
875 asn_put_timeticks(struct asn_buf *b, uint32_t val)
876 {
877 	uint64_t v = val;
878 
879 	return (asn_put_real_unsigned(b,
880 	    ASN_CLASS_APPLICATION | ASN_APP_TIMETICKS, v));
881 }
882 
883 /*
884  * Construct a new OID by taking a range of sub ids of the original oid.
885  */
886 void
887 asn_slice_oid(struct asn_oid *dest, const struct asn_oid *src,
888     u_int from, u_int to)
889 {
890 	if (from >= to) {
891 		dest->len = 0;
892 		return;
893 	}
894 	dest->len = to - from;
895 	memcpy(dest->subs, &src->subs[from], dest->len * sizeof(dest->subs[0]));
896 }
897 
898 /*
899  * Append from to to
900  */
901 void
902 asn_append_oid(struct asn_oid *to, const struct asn_oid *from)
903 {
904 	memcpy(&to->subs[to->len], &from->subs[0],
905 	    from->len * sizeof(from->subs[0]));
906 	to->len += from->len;
907 }
908 
909 /*
910  * Skip a value
911  */
912 enum asn_err
913 asn_skip(struct asn_buf *b, asn_len_t len)
914 {
915 	if (b->asn_len < len)
916 		return (ASN_ERR_EOBUF);
917 	b->asn_cptr += len;
918 	b->asn_len -= len;
919 	return (ASN_ERR_OK);
920 }
921 
922 /*
923  * Add a padding
924  */
925 enum asn_err
926 asn_pad(struct asn_buf *b, asn_len_t len)
927 {
928 	if (b->asn_len < len)
929 		return (ASN_ERR_EOBUF);
930 	b->asn_ptr += len;
931 	b->asn_len -= len;
932 
933 	return (ASN_ERR_OK);
934 }
935 
936 /*
937  * Compare two OIDs.
938  *
939  * o1 < o2 : -1
940  * o1 > o2 : +1
941  * o1 = o2 :  0
942  */
943 int
944 asn_compare_oid(const struct asn_oid *o1, const struct asn_oid *o2)
945 {
946 	u_long i;
947 
948 	for (i = 0; i < o1->len && i < o2->len; i++) {
949 		if (o1->subs[i] < o2->subs[i])
950 			return (-1);
951 		if (o1->subs[i] > o2->subs[i])
952 			return (+1);
953 	}
954 	if (o1->len < o2->len)
955 		return (-1);
956 	if (o1->len > o2->len)
957 		return (+1);
958 	return (0);
959 }
960 
961 /*
962  * Check whether an OID is a sub-string of another OID.
963  */
964 int
965 asn_is_suboid(const struct asn_oid *o1, const struct asn_oid *o2)
966 {
967 	u_long i;
968 
969 	for (i = 0; i < o1->len; i++)
970 		if (i >= o2->len || o1->subs[i] != o2->subs[i])
971 			return (0);
972 	return (1);
973 }
974 
975 /*
976  * Put a string representation of an oid into a user buffer. This buffer
977  * is assumed to be at least ASN_OIDSTRLEN characters long.
978  *
979  * sprintf is assumed not to fail here.
980  */
981 char *
982 asn_oid2str_r(const struct asn_oid *oid, char *buf)
983 {
984 	u_int len, i;
985 	char *ptr;
986 
987 	if ((len = oid->len) > ASN_MAXOIDLEN)
988 		len = ASN_MAXOIDLEN;
989 	buf[0] = '\0';
990 	for (i = 0, ptr = buf; i < len; i++) {
991 		if (i > 0)
992 			*ptr++ = '.';
993 		ptr += sprintf(ptr, "%u", oid->subs[i]);
994 	}
995 	return (buf);
996 }
997 
998 /*
999  * Make a string from an OID in a private buffer.
1000  */
1001 char *
1002 asn_oid2str(const struct asn_oid *oid)
1003 {
1004 	static char str[ASN_OIDSTRLEN];
1005 
1006 	return (asn_oid2str_r(oid, str));
1007 }
1008 
1009 
1010 static void
1011 asn_error_func(const struct asn_buf *b, const char *err, ...)
1012 {
1013 	va_list ap;
1014 	u_long i;
1015 
1016 	fprintf(stderr, "ASN.1: ");
1017 	va_start(ap, err);
1018 	vfprintf(stderr, err, ap);
1019 	va_end(ap);
1020 
1021 	if (b != NULL) {
1022 		fprintf(stderr, " at");
1023 		for (i = 0; b->asn_len > i; i++)
1024 			fprintf(stderr, " %02x", b->asn_cptr[i]);
1025 	}
1026 	fprintf(stderr, "\n");
1027 }
1028