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