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}
|