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 of this software and documentation and use in source and 9 * binary forms, with or without modification, are permitted provided that 10 * the following conditions are met: 11 * 12 * 1. Redistributions of source code or documentation must retain the above 13 * copyright notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 22 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $Begemot: bsnmp/lib/asn1.c,v 1.27 2003/12/08 17:11:58 hbb Exp $ 34 * 35 * ASN.1 for SNMP. 36 */ 37 #include <sys/types.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <stdarg.h> 41 #include <string.h> 42 #include <inttypes.h> 43 #include <assert.h> 44 #include "asn1.h" 45 46 static void asn_error_func(const struct asn_buf *, const char *, ...); 47 48 void (*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 */ 56 enum asn_err 57 asn_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 */ 109 static u_int 110 asn_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 */ 146 enum asn_err 147 asn_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) 184 enum asn_err 185 asn_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 } 196 enum asn_err 197 asn_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 */ 228 static enum asn_err 229 asn_get_real_integer(struct asn_buf *b, asn_len_t len, int64_t *vp) 230 { 231 u_int64_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 */ 274 static enum asn_err 275 asn_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 u_int64_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 = (u_int64_t)-(ival + 1); 287 neg = 1; 288 } else 289 val = (u_int64_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 */ 322 static enum asn_err 323 asn_get_real_unsigned(struct asn_buf *b, asn_len_t len, u_int64_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 */ 359 static int 360 asn_put_real_unsigned(struct asn_buf *b, u_char type, u_int64_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 */ 392 enum asn_err 393 asn_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 409 enum asn_err 410 asn_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 426 enum asn_err 427 asn_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 */ 441 enum asn_err 442 asn_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 465 enum asn_err 466 asn_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 481 enum asn_err 482 asn_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 */ 502 enum asn_err 503 asn_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 518 enum asn_err 519 asn_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 534 enum asn_err 535 asn_put_null(struct asn_buf *b) 536 { 537 return (asn_put_header(b, ASN_TYPE_NULL, 0)); 538 } 539 540 enum asn_err 541 asn_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 */ 551 enum asn_err 552 asn_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 606 enum asn_err 607 asn_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 622 enum asn_err 623 asn_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 */ 713 enum asn_err 714 asn_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 */ 737 enum asn_err 738 asn_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 762 enum asn_err 763 asn_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 778 enum asn_err 779 asn_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 */ 801 enum asn_err 802 asn_get_uint32_raw(struct asn_buf *b, asn_len_t len, u_int32_t *vp) 803 { 804 u_int64_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 = (u_int32_t)v; 816 } 817 return (err); 818 } 819 820 enum asn_err 821 asn_put_uint32(struct asn_buf *b, u_char type, u_int32_t val) 822 { 823 u_int64_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 */ 832 enum asn_err 833 asn_get_counter64_raw(struct asn_buf *b, asn_len_t len, u_int64_t *vp) 834 { 835 return (asn_get_real_unsigned(b, len, vp)); 836 } 837 838 enum asn_err 839 asn_put_counter64(struct asn_buf *b, u_int64_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 */ 849 enum asn_err 850 asn_get_timeticks(struct asn_buf *b, u_int32_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 865 enum asn_err 866 asn_put_timeticks(struct asn_buf *b, u_int32_t val) 867 { 868 u_int64_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 */ 877 void 878 asn_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 */ 892 void 893 asn_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 */ 903 enum asn_err 904 asn_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 */ 920 int 921 asn_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 */ 941 int 942 asn_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 */ 958 char * 959 asn_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 */ 978 char * 979 asn_oid2str(const struct asn_oid *oid) 980 { 981 static char str[ASN_OIDSTRLEN]; 982 983 return (asn_oid2str_r(oid, str)); 984 } 985 986 987 static void 988 asn_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 } 1005