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