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