1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/krb5/asn.1/asn1_encode.c */ 3 /* 4 * Copyright 1994, 2008 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include "asn1_encode.h" 28 29 struct asn1buf_st { 30 uint8_t *ptr; /* Position, moving backwards; may be NULL */ 31 size_t count; /* Count of bytes written so far */ 32 }; 33 34 /**** Functions for encoding primitive types ****/ 35 36 /* Insert one byte into buf going backwards. */ 37 static inline void 38 insert_byte(asn1buf *buf, uint8_t o) 39 { 40 if (buf->ptr != NULL) { 41 buf->ptr--; 42 *buf->ptr = o; 43 } 44 buf->count++; 45 } 46 47 /* Insert a block of bytes into buf going backwards (but without reversing 48 * bytes). */ 49 static inline void 50 insert_bytes(asn1buf *buf, const void *bytes, size_t len) 51 { 52 if (buf->ptr != NULL) { 53 memcpy(buf->ptr - len, bytes, len); 54 buf->ptr -= len; 55 } 56 buf->count += len; 57 } 58 59 void 60 k5_asn1_encode_bool(asn1buf *buf, intmax_t val) 61 { 62 insert_byte(buf, val ? 0xFF : 0x00); 63 } 64 65 void 66 k5_asn1_encode_int(asn1buf *buf, intmax_t val) 67 { 68 long valcopy; 69 int digit; 70 71 valcopy = val; 72 do { 73 digit = valcopy & 0xFF; 74 insert_byte(buf, digit); 75 valcopy = valcopy >> 8; 76 } while (valcopy != 0 && valcopy != ~0); 77 78 /* Make sure the high bit is of the proper signed-ness. */ 79 if (val > 0 && (digit & 0x80) == 0x80) 80 insert_byte(buf, 0); 81 else if (val < 0 && (digit & 0x80) != 0x80) 82 insert_byte(buf, 0xFF); 83 } 84 85 void 86 k5_asn1_encode_uint(asn1buf *buf, uintmax_t val) 87 { 88 uintmax_t valcopy; 89 int digit; 90 91 valcopy = val; 92 do { 93 digit = valcopy & 0xFF; 94 insert_byte(buf, digit); 95 valcopy = valcopy >> 8; 96 } while (valcopy != 0); 97 98 /* Make sure the high bit is of the proper signed-ness. */ 99 if (digit & 0x80) 100 insert_byte(buf, 0); 101 } 102 103 krb5_error_code 104 k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val, size_t len) 105 { 106 if (len > 0 && val == NULL) 107 return ASN1_MISSING_FIELD; 108 insert_bytes(buf, *val, len); 109 return 0; 110 } 111 112 krb5_error_code 113 k5_asn1_encode_generaltime(asn1buf *buf, time_t val) 114 { 115 struct tm *gtime, gtimebuf; 116 char s[16], *sp; 117 time_t gmt_time = val; 118 int len; 119 120 /* 121 * Time encoding: YYYYMMDDhhmmssZ 122 */ 123 if (gmt_time == 0) { 124 sp = "19700101000000Z"; 125 } else { 126 /* 127 * Sanity check this just to be paranoid, as gmtime can return NULL, 128 * and some bogus implementations might overrun on the sprintf. 129 */ 130 #ifdef HAVE_GMTIME_R 131 #ifdef GMTIME_R_RETURNS_INT 132 if (gmtime_r(&gmt_time, >imebuf) != 0) 133 return ASN1_BAD_GMTIME; 134 #else 135 if (gmtime_r(&gmt_time, >imebuf) == NULL) 136 return ASN1_BAD_GMTIME; 137 #endif 138 #else /* HAVE_GMTIME_R */ 139 gtime = gmtime(&gmt_time); 140 if (gtime == NULL) 141 return ASN1_BAD_GMTIME; 142 memcpy(>imebuf, gtime, sizeof(gtimebuf)); 143 #endif /* HAVE_GMTIME_R */ 144 gtime = >imebuf; 145 146 if (gtime->tm_year > 8099 || gtime->tm_mon > 11 || 147 gtime->tm_mday > 31 || gtime->tm_hour > 23 || 148 gtime->tm_min > 59 || gtime->tm_sec > 59) 149 return ASN1_BAD_GMTIME; 150 len = snprintf(s, sizeof(s), "%04d%02d%02d%02d%02d%02dZ", 151 1900 + gtime->tm_year, gtime->tm_mon + 1, 152 gtime->tm_mday, gtime->tm_hour, 153 gtime->tm_min, gtime->tm_sec); 154 if (SNPRINTF_OVERFLOW(len, sizeof(s))) 155 /* Shouldn't be possible given above tests. */ 156 return ASN1_BAD_GMTIME; 157 sp = s; 158 } 159 160 insert_bytes(buf, sp, 15); 161 return 0; 162 } 163 164 krb5_error_code 165 k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val, size_t len) 166 { 167 insert_bytes(buf, *val, len); 168 insert_byte(buf, 0); 169 return 0; 170 } 171 172 /**** Functions for decoding primitive types ****/ 173 174 krb5_error_code 175 k5_asn1_decode_bool(const uint8_t *asn1, size_t len, intmax_t *val) 176 { 177 if (len != 1) 178 return ASN1_BAD_LENGTH; 179 *val = (*asn1 != 0); 180 return 0; 181 } 182 183 /* Decode asn1/len as the contents of a DER integer, placing the signed result 184 * in val. */ 185 krb5_error_code 186 k5_asn1_decode_int(const uint8_t *asn1, size_t len, intmax_t *val) 187 { 188 intmax_t n; 189 size_t i; 190 191 if (len == 0) 192 return ASN1_BAD_LENGTH; 193 n = (asn1[0] & 0x80) ? -1 : 0; 194 /* Check length. */ 195 if (len > sizeof(intmax_t)) 196 return ASN1_OVERFLOW; 197 for (i = 0; i < len; i++) 198 n = n * 256 + asn1[i]; 199 *val = n; 200 return 0; 201 } 202 203 /* Decode asn1/len as the contents of a DER integer, placing the unsigned 204 * result in val. */ 205 krb5_error_code 206 k5_asn1_decode_uint(const uint8_t *asn1, size_t len, uintmax_t *val) 207 { 208 uintmax_t n; 209 size_t i; 210 211 if (len == 0) 212 return ASN1_BAD_LENGTH; 213 /* Check for negative values and check length. */ 214 if ((asn1[0] & 0x80) || len > sizeof(uintmax_t) + (asn1[0] == 0)) 215 return ASN1_OVERFLOW; 216 for (i = 0, n = 0; i < len; i++) 217 n = (n << 8) | asn1[i]; 218 *val = n; 219 return 0; 220 } 221 222 krb5_error_code 223 k5_asn1_decode_bytestring(const uint8_t *asn1, size_t len, 224 uint8_t **str_out, size_t *len_out) 225 { 226 uint8_t *str; 227 228 *str_out = NULL; 229 *len_out = 0; 230 if (len == 0) 231 return 0; 232 str = malloc(len); 233 if (str == NULL) 234 return ENOMEM; 235 memcpy(str, asn1, len); 236 *str_out = str; 237 *len_out = len; 238 return 0; 239 } 240 241 krb5_error_code 242 k5_asn1_decode_generaltime(const uint8_t *asn1, size_t len, time_t *time_out) 243 { 244 const char *s = (char *)asn1; 245 struct tm ts; 246 time_t t; 247 size_t i; 248 249 *time_out = 0; 250 if (len != 15) 251 return ASN1_BAD_LENGTH; 252 /* Time encoding: YYYYMMDDhhmmssZ */ 253 if (s[14] != 'Z') 254 return ASN1_BAD_FORMAT; 255 if (memcmp(s, "19700101000000Z", 15) == 0) { 256 *time_out = 0; 257 return 0; 258 } 259 #define c2i(c) ((c) - '0') 260 for (i = 0; i < 14; ++i) { 261 if ((uint8_t)c2i(s[i]) > 9) 262 return ASN1_BAD_TIMEFORMAT; 263 } 264 ts.tm_year = 1000 * c2i(s[0]) + 100 * c2i(s[1]) + 10 * c2i(s[2]) + 265 c2i(s[3]) - 1900; 266 ts.tm_mon = 10 * c2i(s[4]) + c2i(s[5]) - 1; 267 ts.tm_mday = 10 * c2i(s[6]) + c2i(s[7]); 268 ts.tm_hour = 10 * c2i(s[8]) + c2i(s[9]); 269 ts.tm_min = 10 * c2i(s[10]) + c2i(s[11]); 270 ts.tm_sec = 10 * c2i(s[12]) + c2i(s[13]); 271 ts.tm_isdst = -1; 272 t = krb5int_gmt_mktime(&ts); 273 if (t == -1) 274 return ASN1_BAD_TIMEFORMAT; 275 *time_out = t; 276 return 0; 277 } 278 279 /* 280 * Note: we return the number of bytes, not bits, in the bit string. If the 281 * number of bits is not a multiple of 8 we effectively round up to the next 282 * multiple of 8. 283 */ 284 krb5_error_code 285 k5_asn1_decode_bitstring(const uint8_t *asn1, size_t len, 286 uint8_t **bits_out, size_t *len_out) 287 { 288 uint8_t unused, *bits; 289 290 *bits_out = NULL; 291 *len_out = 0; 292 if (len == 0) 293 return ASN1_BAD_LENGTH; 294 unused = *asn1++; 295 len--; 296 if (unused > 7) 297 return ASN1_BAD_FORMAT; 298 299 bits = malloc(len); 300 if (bits == NULL) 301 return ENOMEM; 302 memcpy(bits, asn1, len); 303 if (len > 1) 304 bits[len - 1] &= (0xff << unused); 305 306 *bits_out = bits; 307 *len_out = len; 308 return 0; 309 } 310 311 /**** Functions for encoding and decoding tags ****/ 312 313 /* Encode a DER tag into buf with the tag parameters in t and the content 314 * length len. Place the length of the encoded tag in *retlen. */ 315 static krb5_error_code 316 make_tag(asn1buf *buf, const taginfo *t, size_t len) 317 { 318 asn1_tagnum tag_copy; 319 size_t len_copy, oldcount; 320 321 if (t->tagnum > ASN1_TAGNUM_MAX) 322 return ASN1_OVERFLOW; 323 324 /* Encode the length of the content within the tag. */ 325 if (len < 128) { 326 insert_byte(buf, len & 0x7F); 327 } else { 328 oldcount = buf->count; 329 for (len_copy = len; len_copy != 0; len_copy >>= 8) 330 insert_byte(buf, len_copy & 0xFF); 331 insert_byte(buf, 0x80 | ((buf->count - oldcount) & 0x7F)); 332 } 333 334 /* Encode the tag and construction bit. */ 335 if (t->tagnum < 31) { 336 insert_byte(buf, t->asn1class | t->construction | t->tagnum); 337 } else { 338 tag_copy = t->tagnum; 339 insert_byte(buf, tag_copy & 0x7F); 340 tag_copy >>= 7; 341 342 for (; tag_copy != 0; tag_copy >>= 7) 343 insert_byte(buf, 0x80 | (tag_copy & 0x7F)); 344 345 insert_byte(buf, t->asn1class | t->construction | 0x1F); 346 } 347 348 return 0; 349 } 350 351 /* 352 * Read a DER tag and length from asn1/len. Place the tag parameters in 353 * tag_out. Set contents_out/clen_out to the octet range of the tag's 354 * contents, and remainder_out/rlen_out to the octet range after the end of the 355 * DER encoding. 356 */ 357 static krb5_error_code 358 get_tag(const uint8_t *asn1, size_t len, taginfo *tag_out, 359 const uint8_t **contents_out, size_t *clen_out, 360 const uint8_t **remainder_out, size_t *rlen_out) 361 { 362 uint8_t o; 363 const uint8_t *tag_start = asn1; 364 size_t clen, llen, i; 365 366 *contents_out = *remainder_out = NULL; 367 *clen_out = *rlen_out = 0; 368 if (len == 0) 369 return ASN1_OVERRUN; 370 o = *asn1++; 371 len--; 372 tag_out->asn1class = o & 0xC0; 373 tag_out->construction = o & 0x20; 374 if ((o & 0x1F) != 0x1F) { 375 tag_out->tagnum = o & 0x1F; 376 } else { 377 tag_out->tagnum = 0; 378 do { 379 if (len == 0) 380 return ASN1_OVERRUN; 381 if (tag_out->tagnum > (ASN1_TAGNUM_MAX >> 7)) 382 return ASN1_OVERFLOW; 383 o = *asn1++; 384 len--; 385 tag_out->tagnum = (tag_out->tagnum << 7) | (o & 0x7F); 386 } while (o & 0x80); 387 /* Check for overly large tag values */ 388 if (tag_out->tagnum > ASN1_TAGNUM_MAX) 389 return ASN1_OVERFLOW; 390 } 391 392 if (len == 0) 393 return ASN1_OVERRUN; 394 o = *asn1++; 395 len--; 396 397 if ((o & 0x80) == 0) { 398 /* Short form (first octet gives content length). */ 399 if (o > len) 400 return ASN1_OVERRUN; 401 *contents_out = asn1; 402 *clen_out = o; 403 *remainder_out = asn1 + *clen_out; 404 *rlen_out = len - (*remainder_out - asn1); 405 } else { 406 /* Long form (first octet gives number of base-256 length octets). */ 407 llen = o & 0x7F; 408 if (llen > len) 409 return ASN1_OVERRUN; 410 if (llen > sizeof(*clen_out)) 411 return ASN1_OVERFLOW; 412 if (llen == 0) 413 return ASN1_INDEF; 414 for (i = 0, clen = 0; i < llen; i++) 415 clen = (clen << 8) | asn1[i]; 416 if (clen > len - llen) 417 return ASN1_OVERRUN; 418 *contents_out = asn1 + llen; 419 *clen_out = clen; 420 *remainder_out = *contents_out + clen; 421 *rlen_out = len - (*remainder_out - asn1); 422 } 423 tag_out->tag_len = *contents_out - tag_start; 424 return 0; 425 } 426 427 #ifdef POINTERS_ARE_ALL_THE_SAME 428 #define LOADPTR(PTR, TYPE) (*(const void *const *)(PTR)) 429 #define STOREPTR(PTR, TYPE, VAL) (*(void **)(VAL) = (PTR)) 430 #else 431 #define LOADPTR(PTR, PTRINFO) \ 432 (assert((PTRINFO)->loadptr != NULL), (PTRINFO)->loadptr(PTR)) 433 #define STOREPTR(PTR, PTRINFO, VAL) \ 434 (assert((PTRINFO)->storeptr != NULL), (PTRINFO)->storeptr(PTR, VAL)) 435 #endif 436 437 static size_t 438 get_nullterm_sequence_len(const void *valp, const struct atype_info *seq) 439 { 440 size_t i; 441 const struct atype_info *a; 442 const struct ptr_info *ptr; 443 const void *elt, *eltptr; 444 445 a = seq; 446 i = 0; 447 assert(a->type == atype_ptr); 448 assert(seq->size != 0); 449 ptr = a->tinfo; 450 451 while (1) { 452 eltptr = (const char *)valp + i * seq->size; 453 elt = LOADPTR(eltptr, ptr); 454 if (elt == NULL) 455 break; 456 i++; 457 } 458 return i; 459 } 460 static krb5_error_code 461 encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val, 462 const struct atype_info *eltinfo); 463 464 static krb5_error_code 465 encode_nullterm_sequence_of(asn1buf *buf, const void *val, 466 const struct atype_info *type, int can_be_empty) 467 { 468 size_t len = get_nullterm_sequence_len(val, type); 469 470 if (!can_be_empty && len == 0) 471 return ASN1_MISSING_FIELD; 472 return encode_sequence_of(buf, len, val, type); 473 } 474 475 static intmax_t 476 load_int(const void *val, size_t size) 477 { 478 switch (size) { 479 case 1: return *(int8_t *)val; 480 case 2: return *(int16_t *)val; 481 case 4: return *(int32_t *)val; 482 case 8: return *(int64_t *)val; 483 default: abort(); 484 } 485 } 486 487 static uintmax_t 488 load_uint(const void *val, size_t size) 489 { 490 switch (size) { 491 case 1: return *(uint8_t *)val; 492 case 2: return *(uint16_t *)val; 493 case 4: return *(uint32_t *)val; 494 case 8: return *(uint64_t *)val; 495 default: abort(); 496 } 497 } 498 499 static krb5_error_code 500 load_count(const void *val, const struct counted_info *counted, 501 size_t *count_out) 502 { 503 const void *countptr = (const char *)val + counted->lenoff; 504 505 assert(sizeof(size_t) <= sizeof(uintmax_t)); 506 if (counted->lensigned) { 507 intmax_t xlen = load_int(countptr, counted->lensize); 508 if (xlen < 0 || (uintmax_t)xlen > SIZE_MAX) 509 return EINVAL; 510 *count_out = xlen; 511 } else { 512 uintmax_t xlen = load_uint(countptr, counted->lensize); 513 if ((size_t)xlen != xlen || xlen > SIZE_MAX) 514 return EINVAL; 515 *count_out = xlen; 516 } 517 return 0; 518 } 519 520 static krb5_error_code 521 store_int(intmax_t intval, size_t size, void *val) 522 { 523 switch (size) { 524 case 1: 525 if ((int8_t)intval != intval) 526 return ASN1_OVERFLOW; 527 *(int8_t *)val = intval; 528 return 0; 529 case 2: 530 if ((int16_t)intval != intval) 531 return ASN1_OVERFLOW; 532 *(int16_t *)val = intval; 533 return 0; 534 case 4: 535 if ((int32_t)intval != intval) 536 return ASN1_OVERFLOW; 537 *(int32_t *)val = intval; 538 return 0; 539 case 8: 540 if ((int64_t)intval != intval) 541 return ASN1_OVERFLOW; 542 *(int64_t *)val = intval; 543 return 0; 544 default: 545 abort(); 546 } 547 } 548 549 static krb5_error_code 550 store_uint(uintmax_t intval, size_t size, void *val) 551 { 552 switch (size) { 553 case 1: 554 if ((uint8_t)intval != intval) 555 return ASN1_OVERFLOW; 556 *(uint8_t *)val = intval; 557 return 0; 558 case 2: 559 if ((uint16_t)intval != intval) 560 return ASN1_OVERFLOW; 561 *(uint16_t *)val = intval; 562 return 0; 563 case 4: 564 if ((uint32_t)intval != intval) 565 return ASN1_OVERFLOW; 566 *(uint32_t *)val = intval; 567 return 0; 568 case 8: 569 if ((uint64_t)intval != intval) 570 return ASN1_OVERFLOW; 571 *(uint64_t *)val = intval; 572 return 0; 573 default: 574 abort(); 575 } 576 } 577 578 /* Store a count value in an integer field of a structure. If count is 579 * SIZE_MAX and the target is a signed field, store -1. */ 580 static krb5_error_code 581 store_count(size_t count, const struct counted_info *counted, void *val) 582 { 583 void *countptr = (char *)val + counted->lenoff; 584 585 if (counted->lensigned) { 586 if (count == SIZE_MAX) 587 return store_int(-1, counted->lensize, countptr); 588 else if ((intmax_t)count < 0) 589 return ASN1_OVERFLOW; 590 else 591 return store_int(count, counted->lensize, countptr); 592 } else 593 return store_uint(count, counted->lensize, countptr); 594 } 595 596 /* Split a DER encoding into tag and contents. Insert the contents into buf, 597 * then return the length of the contents and the tag. */ 598 static krb5_error_code 599 split_der(asn1buf *buf, uint8_t *const *der, size_t len, taginfo *tag_out) 600 { 601 krb5_error_code ret; 602 const uint8_t *contents, *remainder; 603 size_t clen, rlen; 604 605 ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen); 606 if (ret) 607 return ret; 608 if (rlen != 0) 609 return ASN1_BAD_LENGTH; 610 insert_bytes(buf, contents, clen); 611 return 0; 612 } 613 614 /* 615 * Store the DER encoding given by t and asn1/len into the char * or 616 * uint8_t * pointed to by val. Set *count_out to the length of the 617 * DER encoding. 618 */ 619 static krb5_error_code 620 store_der(const taginfo *t, const uint8_t *asn1, size_t len, void *val, 621 size_t *count_out) 622 { 623 uint8_t *der; 624 size_t der_len; 625 626 *count_out = 0; 627 der_len = t->tag_len + len; 628 der = malloc(der_len); 629 if (der == NULL) 630 return ENOMEM; 631 memcpy(der, asn1 - t->tag_len, der_len); 632 *(uint8_t **)val = der; 633 *count_out = der_len; 634 return 0; 635 } 636 637 static krb5_error_code 638 encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq); 639 static krb5_error_code 640 encode_cntype(asn1buf *buf, const void *val, size_t len, 641 const struct cntype_info *c, taginfo *tag_out); 642 643 /* Encode a value (contents only, no outer tag) according to a type, and return 644 * its encoded tag information. */ 645 static krb5_error_code 646 encode_atype(asn1buf *buf, const void *val, const struct atype_info *a, 647 taginfo *tag_out) 648 { 649 krb5_error_code ret; 650 651 if (val == NULL) 652 return ASN1_MISSING_FIELD; 653 654 switch (a->type) { 655 case atype_fn: { 656 const struct fn_info *fn = a->tinfo; 657 assert(fn->enc != NULL); 658 return fn->enc(buf, val, tag_out); 659 } 660 case atype_sequence: 661 assert(a->tinfo != NULL); 662 ret = encode_sequence(buf, val, a->tinfo); 663 if (ret) 664 return ret; 665 tag_out->asn1class = UNIVERSAL; 666 tag_out->construction = CONSTRUCTED; 667 tag_out->tagnum = ASN1_SEQUENCE; 668 break; 669 case atype_ptr: { 670 const struct ptr_info *ptr = a->tinfo; 671 assert(ptr->basetype != NULL); 672 return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out); 673 } 674 case atype_offset: { 675 const struct offset_info *off = a->tinfo; 676 assert(off->basetype != NULL); 677 return encode_atype(buf, (const char *)val + off->dataoff, 678 off->basetype, tag_out); 679 } 680 case atype_optional: { 681 const struct optional_info *opt = a->tinfo; 682 assert(opt->is_present != NULL); 683 if (opt->is_present(val)) 684 return encode_atype(buf, val, opt->basetype, tag_out); 685 else 686 return ASN1_OMITTED; 687 } 688 case atype_counted: { 689 const struct counted_info *counted = a->tinfo; 690 const void *dataptr = (const char *)val + counted->dataoff; 691 size_t count; 692 assert(counted->basetype != NULL); 693 ret = load_count(val, counted, &count); 694 if (ret) 695 return ret; 696 return encode_cntype(buf, dataptr, count, counted->basetype, tag_out); 697 } 698 case atype_nullterm_sequence_of: 699 case atype_nonempty_nullterm_sequence_of: 700 assert(a->tinfo != NULL); 701 ret = encode_nullterm_sequence_of(buf, val, a->tinfo, 702 a->type == 703 atype_nullterm_sequence_of); 704 if (ret) 705 return ret; 706 tag_out->asn1class = UNIVERSAL; 707 tag_out->construction = CONSTRUCTED; 708 tag_out->tagnum = ASN1_SEQUENCE; 709 break; 710 case atype_tagged_thing: { 711 const struct tagged_info *tag = a->tinfo; 712 size_t oldcount = buf->count; 713 ret = encode_atype(buf, val, tag->basetype, tag_out); 714 if (ret) 715 return ret; 716 if (!tag->implicit) { 717 ret = make_tag(buf, tag_out, buf->count - oldcount); 718 if (ret) 719 return ret; 720 tag_out->construction = tag->construction; 721 } 722 tag_out->asn1class = tag->tagtype; 723 tag_out->tagnum = tag->tagval; 724 break; 725 } 726 case atype_bool: 727 k5_asn1_encode_bool(buf, load_int(val, a->size)); 728 tag_out->asn1class = UNIVERSAL; 729 tag_out->construction = PRIMITIVE; 730 tag_out->tagnum = ASN1_BOOLEAN; 731 break; 732 case atype_int: 733 k5_asn1_encode_int(buf, load_int(val, a->size)); 734 tag_out->asn1class = UNIVERSAL; 735 tag_out->construction = PRIMITIVE; 736 tag_out->tagnum = ASN1_INTEGER; 737 break; 738 case atype_uint: 739 k5_asn1_encode_uint(buf, load_uint(val, a->size)); 740 tag_out->asn1class = UNIVERSAL; 741 tag_out->construction = PRIMITIVE; 742 tag_out->tagnum = ASN1_INTEGER; 743 break; 744 case atype_int_immediate: { 745 const struct immediate_info *imm = a->tinfo; 746 k5_asn1_encode_int(buf, imm->val); 747 tag_out->asn1class = UNIVERSAL; 748 tag_out->construction = PRIMITIVE; 749 tag_out->tagnum = ASN1_INTEGER; 750 break; 751 } 752 default: 753 assert(a->type > atype_min); 754 assert(a->type < atype_max); 755 abort(); 756 } 757 758 return 0; 759 } 760 761 static krb5_error_code 762 encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a) 763 { 764 taginfo t; 765 krb5_error_code ret; 766 size_t oldcount = buf->count; 767 768 ret = encode_atype(buf, val, a, &t); 769 if (ret) 770 return ret; 771 ret = make_tag(buf, &t, buf->count - oldcount); 772 if (ret) 773 return ret; 774 return 0; 775 } 776 777 /* 778 * Encode an object and count according to a cntype_info structure. val is a 779 * pointer to the object being encoded, which in most cases is itself a 780 * pointer (but is a union in the cntype_choice case). 781 */ 782 static krb5_error_code 783 encode_cntype(asn1buf *buf, const void *val, size_t count, 784 const struct cntype_info *c, taginfo *tag_out) 785 { 786 krb5_error_code ret; 787 788 switch (c->type) { 789 case cntype_string: { 790 const struct string_info *string = c->tinfo; 791 assert(string->enc != NULL); 792 ret = string->enc(buf, val, count); 793 if (ret) 794 return ret; 795 tag_out->asn1class = UNIVERSAL; 796 tag_out->construction = PRIMITIVE; 797 tag_out->tagnum = string->tagval; 798 break; 799 } 800 case cntype_der: 801 return split_der(buf, val, count, tag_out); 802 case cntype_seqof: { 803 const struct atype_info *a = c->tinfo; 804 const struct ptr_info *ptr = a->tinfo; 805 assert(a->type == atype_ptr); 806 val = LOADPTR(val, ptr); 807 ret = encode_sequence_of(buf, count, val, ptr->basetype); 808 if (ret) 809 return ret; 810 tag_out->asn1class = UNIVERSAL; 811 tag_out->construction = CONSTRUCTED; 812 tag_out->tagnum = ASN1_SEQUENCE; 813 break; 814 } 815 case cntype_choice: { 816 const struct choice_info *choice = c->tinfo; 817 if (count >= choice->n_options) 818 return ASN1_MISSING_FIELD; 819 return encode_atype(buf, val, choice->options[count], tag_out); 820 } 821 822 default: 823 assert(c->type > cntype_min); 824 assert(c->type < cntype_max); 825 abort(); 826 } 827 828 return 0; 829 } 830 831 static krb5_error_code 832 encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq) 833 { 834 krb5_error_code ret; 835 size_t i; 836 837 for (i = seq->n_fields; i > 0; i--) { 838 ret = encode_atype_and_tag(buf, val, seq->fields[i - 1]); 839 if (ret == ASN1_OMITTED) 840 continue; 841 else if (ret != 0) 842 return ret; 843 } 844 return 0; 845 } 846 847 static krb5_error_code 848 encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val, 849 const struct atype_info *eltinfo) 850 { 851 krb5_error_code ret; 852 size_t i; 853 const void *eltptr; 854 855 assert(eltinfo->size != 0); 856 for (i = seqlen; i > 0; i--) { 857 eltptr = (const char *)val + (i - 1) * eltinfo->size; 858 ret = encode_atype_and_tag(buf, eltptr, eltinfo); 859 if (ret) 860 return ret; 861 } 862 return 0; 863 } 864 865 /**** Functions for freeing C objects based on type info ****/ 866 867 static void free_atype_ptr(const struct atype_info *a, void *val); 868 static void free_sequence(const struct seq_info *seq, void *val); 869 static void free_sequence_of(const struct atype_info *eltinfo, void *val, 870 size_t count); 871 static void free_cntype(const struct cntype_info *a, void *val, size_t count); 872 873 /* 874 * Free a C object according to a type description. Do not free pointers at 875 * the first level; they may be referenced by other fields of a sequence, and 876 * will be freed by free_atype_ptr in a second pass. 877 */ 878 static void 879 free_atype(const struct atype_info *a, void *val) 880 { 881 switch (a->type) { 882 case atype_fn: { 883 const struct fn_info *fn = a->tinfo; 884 if (fn->free_func != NULL) 885 fn->free_func(val); 886 break; 887 } 888 case atype_sequence: 889 free_sequence(a->tinfo, val); 890 break; 891 case atype_ptr: { 892 const struct ptr_info *ptrinfo = a->tinfo; 893 void *ptr = LOADPTR(val, ptrinfo); 894 if (ptr != NULL) { 895 free_atype(ptrinfo->basetype, ptr); 896 free_atype_ptr(ptrinfo->basetype, ptr); 897 } 898 break; 899 } 900 case atype_offset: { 901 const struct offset_info *off = a->tinfo; 902 assert(off->basetype != NULL); 903 free_atype(off->basetype, (char *)val + off->dataoff); 904 break; 905 } 906 case atype_optional: { 907 const struct optional_info *opt = a->tinfo; 908 free_atype(opt->basetype, val); 909 break; 910 } 911 case atype_counted: { 912 const struct counted_info *counted = a->tinfo; 913 void *dataptr = (char *)val + counted->dataoff; 914 size_t count; 915 if (load_count(val, counted, &count) == 0) 916 free_cntype(counted->basetype, dataptr, count); 917 break; 918 } 919 case atype_nullterm_sequence_of: 920 case atype_nonempty_nullterm_sequence_of: { 921 size_t count = get_nullterm_sequence_len(val, a->tinfo); 922 free_sequence_of(a->tinfo, val, count); 923 break; 924 } 925 case atype_tagged_thing: { 926 const struct tagged_info *tag = a->tinfo; 927 free_atype(tag->basetype, val); 928 break; 929 } 930 case atype_bool: 931 case atype_int: 932 case atype_uint: 933 case atype_int_immediate: 934 break; 935 default: 936 abort(); 937 } 938 } 939 940 static void 941 free_atype_ptr(const struct atype_info *a, void *val) 942 { 943 switch (a->type) { 944 case atype_fn: 945 case atype_sequence: 946 case atype_counted: 947 case atype_nullterm_sequence_of: 948 case atype_nonempty_nullterm_sequence_of: 949 case atype_bool: 950 case atype_int: 951 case atype_uint: 952 case atype_int_immediate: 953 break; 954 case atype_ptr: { 955 const struct ptr_info *ptrinfo = a->tinfo; 956 void *ptr = LOADPTR(val, ptrinfo); 957 free(ptr); 958 STOREPTR(NULL, ptrinfo, val); 959 break; 960 } 961 case atype_offset: { 962 const struct offset_info *off = a->tinfo; 963 assert(off->basetype != NULL); 964 free_atype_ptr(off->basetype, (char *)val + off->dataoff); 965 break; 966 } 967 case atype_optional: { 968 const struct optional_info *opt = a->tinfo; 969 free_atype_ptr(opt->basetype, val); 970 break; 971 } 972 case atype_tagged_thing: { 973 const struct tagged_info *tag = a->tinfo; 974 free_atype_ptr(tag->basetype, val); 975 break; 976 } 977 default: 978 abort(); 979 } 980 } 981 982 static void 983 free_cntype(const struct cntype_info *c, void *val, size_t count) 984 { 985 switch (c->type) { 986 case cntype_string: 987 case cntype_der: 988 free(*(char **)val); 989 *(char **)val = NULL; 990 break; 991 case cntype_seqof: { 992 const struct atype_info *a = c->tinfo; 993 const struct ptr_info *ptrinfo = a->tinfo; 994 void *seqptr = LOADPTR(val, ptrinfo); 995 free_sequence_of(ptrinfo->basetype, seqptr, count); 996 free(seqptr); 997 STOREPTR(NULL, ptrinfo, val); 998 break; 999 } 1000 case cntype_choice: { 1001 const struct choice_info *choice = c->tinfo; 1002 if (count < choice->n_options) { 1003 free_atype(choice->options[count], val); 1004 free_atype_ptr(choice->options[count], val); 1005 } 1006 break; 1007 } 1008 default: 1009 abort(); 1010 } 1011 } 1012 1013 static void 1014 free_sequence(const struct seq_info *seq, void *val) 1015 { 1016 size_t i; 1017 1018 for (i = 0; i < seq->n_fields; i++) 1019 free_atype(seq->fields[i], val); 1020 for (i = 0; i < seq->n_fields; i++) 1021 free_atype_ptr(seq->fields[i], val); 1022 } 1023 1024 static void 1025 free_sequence_of(const struct atype_info *eltinfo, void *val, size_t count) 1026 { 1027 void *eltptr; 1028 1029 assert(eltinfo->size != 0); 1030 while (count-- > 0) { 1031 eltptr = (char *)val + count * eltinfo->size; 1032 free_atype(eltinfo, eltptr); 1033 free_atype_ptr(eltinfo, eltptr); 1034 } 1035 } 1036 1037 /**** Functions for decoding objects based on type info ****/ 1038 1039 /* Return nonzero if t is an expected tag for an ASN.1 object of type a. */ 1040 static int 1041 check_atype_tag(const struct atype_info *a, const taginfo *t) 1042 { 1043 switch (a->type) { 1044 case atype_fn: { 1045 const struct fn_info *fn = a->tinfo; 1046 assert(fn->check_tag != NULL); 1047 return fn->check_tag(t); 1048 } 1049 case atype_sequence: 1050 case atype_nullterm_sequence_of: 1051 case atype_nonempty_nullterm_sequence_of: 1052 return (t->asn1class == UNIVERSAL && t->construction == CONSTRUCTED && 1053 t->tagnum == ASN1_SEQUENCE); 1054 case atype_ptr: { 1055 const struct ptr_info *ptrinfo = a->tinfo; 1056 return check_atype_tag(ptrinfo->basetype, t); 1057 } 1058 case atype_offset: { 1059 const struct offset_info *off = a->tinfo; 1060 return check_atype_tag(off->basetype, t); 1061 } 1062 case atype_optional: { 1063 const struct optional_info *opt = a->tinfo; 1064 return check_atype_tag(opt->basetype, t); 1065 } 1066 case atype_counted: { 1067 const struct counted_info *counted = a->tinfo; 1068 switch (counted->basetype->type) { 1069 case cntype_string: { 1070 const struct string_info *string = counted->basetype->tinfo; 1071 return (t->asn1class == UNIVERSAL && 1072 t->construction == PRIMITIVE && 1073 t->tagnum == string->tagval); 1074 } 1075 case cntype_seqof: 1076 return (t->asn1class == UNIVERSAL && 1077 t->construction == CONSTRUCTED && 1078 t->tagnum == ASN1_SEQUENCE); 1079 case cntype_der: 1080 /* 1081 * We treat any tag as matching a stored DER encoding. In some 1082 * cases we know what the tag should be; in others, we truly want 1083 * to accept any tag. If it ever becomes an issue, we could add 1084 * optional tag info to the type and check it here. 1085 */ 1086 return 1; 1087 case cntype_choice: 1088 /* 1089 * ASN.1 choices may or may not be extensible. For now, we treat 1090 * all choices as extensible and match any tag. We should consider 1091 * modeling whether choices are extensible before making the 1092 * encoder visible to plugins. 1093 */ 1094 return 1; 1095 default: 1096 abort(); 1097 } 1098 } 1099 case atype_tagged_thing: { 1100 const struct tagged_info *tag = a->tinfo; 1101 /* NOTE: Doesn't check construction bit for implicit tags. */ 1102 if (!tag->implicit && t->construction != tag->construction) 1103 return 0; 1104 return (t->asn1class == tag->tagtype && t->tagnum == tag->tagval); 1105 } 1106 case atype_bool: 1107 return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && 1108 t->tagnum == ASN1_BOOLEAN); 1109 case atype_int: 1110 case atype_uint: 1111 case atype_int_immediate: 1112 return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && 1113 t->tagnum == ASN1_INTEGER); 1114 default: 1115 abort(); 1116 } 1117 } 1118 1119 static krb5_error_code 1120 decode_cntype(const taginfo *t, const uint8_t *asn1, size_t len, 1121 const struct cntype_info *c, void *val, size_t *count_out); 1122 static krb5_error_code 1123 decode_atype_to_ptr(const taginfo *t, const uint8_t *asn1, size_t len, 1124 const struct atype_info *basetype, void **ptr_out); 1125 static krb5_error_code 1126 decode_sequence(const uint8_t *asn1, size_t len, const struct seq_info *seq, 1127 void *val); 1128 static krb5_error_code 1129 decode_sequence_of(const uint8_t *asn1, size_t len, 1130 const struct atype_info *elemtype, void **seq_out, 1131 size_t *count_out); 1132 1133 /* Given the enclosing tag t, decode from asn1/len the contents of the ASN.1 1134 * type specified by a, placing the result into val (caller-allocated). */ 1135 static krb5_error_code 1136 decode_atype(const taginfo *t, const uint8_t *asn1, size_t len, 1137 const struct atype_info *a, void *val) 1138 { 1139 krb5_error_code ret; 1140 1141 switch (a->type) { 1142 case atype_fn: { 1143 const struct fn_info *fn = a->tinfo; 1144 assert(fn->dec != NULL); 1145 return fn->dec(t, asn1, len, val); 1146 } 1147 case atype_sequence: 1148 return decode_sequence(asn1, len, a->tinfo, val); 1149 case atype_ptr: { 1150 const struct ptr_info *ptrinfo = a->tinfo; 1151 void *ptr = LOADPTR(val, ptrinfo); 1152 assert(ptrinfo->basetype != NULL); 1153 if (ptr != NULL) { 1154 /* Container was already allocated by a previous sequence field. */ 1155 return decode_atype(t, asn1, len, ptrinfo->basetype, ptr); 1156 } else { 1157 ret = decode_atype_to_ptr(t, asn1, len, ptrinfo->basetype, &ptr); 1158 if (ret) 1159 return ret; 1160 STOREPTR(ptr, ptrinfo, val); 1161 break; 1162 } 1163 } 1164 case atype_offset: { 1165 const struct offset_info *off = a->tinfo; 1166 assert(off->basetype != NULL); 1167 return decode_atype(t, asn1, len, off->basetype, 1168 (char *)val + off->dataoff); 1169 } 1170 case atype_optional: { 1171 const struct optional_info *opt = a->tinfo; 1172 return decode_atype(t, asn1, len, opt->basetype, val); 1173 } 1174 case atype_counted: { 1175 const struct counted_info *counted = a->tinfo; 1176 void *dataptr = (char *)val + counted->dataoff; 1177 size_t count; 1178 assert(counted->basetype != NULL); 1179 ret = decode_cntype(t, asn1, len, counted->basetype, dataptr, &count); 1180 if (ret) 1181 return ret; 1182 return store_count(count, counted, val); 1183 } 1184 case atype_tagged_thing: { 1185 const struct tagged_info *tag = a->tinfo; 1186 taginfo inner_tag; 1187 const taginfo *tp = t; 1188 const uint8_t *rem; 1189 size_t rlen; 1190 if (!tag->implicit) { 1191 ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen); 1192 if (ret) 1193 return ret; 1194 if (rlen) 1195 return ASN1_BAD_LENGTH; 1196 tp = &inner_tag; 1197 if (!check_atype_tag(tag->basetype, tp)) 1198 return ASN1_BAD_ID; 1199 } 1200 return decode_atype(tp, asn1, len, tag->basetype, val); 1201 } 1202 case atype_bool: { 1203 intmax_t intval; 1204 ret = k5_asn1_decode_bool(asn1, len, &intval); 1205 if (ret) 1206 return ret; 1207 return store_int(intval, a->size, val); 1208 } 1209 case atype_int: { 1210 intmax_t intval; 1211 ret = k5_asn1_decode_int(asn1, len, &intval); 1212 if (ret) 1213 return ret; 1214 return store_int(intval, a->size, val); 1215 } 1216 case atype_uint: { 1217 uintmax_t intval; 1218 ret = k5_asn1_decode_uint(asn1, len, &intval); 1219 if (ret) 1220 return ret; 1221 return store_uint(intval, a->size, val); 1222 } 1223 case atype_int_immediate: { 1224 const struct immediate_info *imm = a->tinfo; 1225 intmax_t intval; 1226 ret = k5_asn1_decode_int(asn1, len, &intval); 1227 if (ret) 1228 return ret; 1229 if (intval != imm->val && imm->err != 0) 1230 return imm->err; 1231 break; 1232 } 1233 default: 1234 /* Null-terminated sequence types are handled in decode_atype_to_ptr, 1235 * since they create variable-sized objects. */ 1236 assert(a->type != atype_nullterm_sequence_of); 1237 assert(a->type != atype_nonempty_nullterm_sequence_of); 1238 assert(a->type > atype_min); 1239 assert(a->type < atype_max); 1240 abort(); 1241 } 1242 return 0; 1243 } 1244 1245 /* 1246 * Given the enclosing tag t, decode from asn1/len the contents of the 1247 * ASN.1 type described by c, placing the counted result into val/count_out. 1248 * If the resulting count should be -1 (for an unknown union distinguisher), 1249 * set *count_out to SIZE_MAX. 1250 */ 1251 static krb5_error_code 1252 decode_cntype(const taginfo *t, const uint8_t *asn1, size_t len, 1253 const struct cntype_info *c, void *val, size_t *count_out) 1254 { 1255 krb5_error_code ret; 1256 1257 switch (c->type) { 1258 case cntype_string: { 1259 const struct string_info *string = c->tinfo; 1260 assert(string->dec != NULL); 1261 return string->dec(asn1, len, val, count_out); 1262 } 1263 case cntype_der: 1264 return store_der(t, asn1, len, val, count_out); 1265 case cntype_seqof: { 1266 const struct atype_info *a = c->tinfo; 1267 const struct ptr_info *ptrinfo = a->tinfo; 1268 void *seq; 1269 assert(a->type == atype_ptr); 1270 ret = decode_sequence_of(asn1, len, ptrinfo->basetype, &seq, 1271 count_out); 1272 if (ret) 1273 return ret; 1274 STOREPTR(seq, ptrinfo, val); 1275 break; 1276 } 1277 case cntype_choice: { 1278 const struct choice_info *choice = c->tinfo; 1279 size_t i; 1280 for (i = 0; i < choice->n_options; i++) { 1281 if (check_atype_tag(choice->options[i], t)) { 1282 ret = decode_atype(t, asn1, len, choice->options[i], val); 1283 if (ret) 1284 return ret; 1285 *count_out = i; 1286 return 0; 1287 } 1288 } 1289 /* SIZE_MAX will be stored as -1 in the distinguisher. If we start 1290 * modeling non-extensible choices we should check that here. */ 1291 *count_out = SIZE_MAX; 1292 break; 1293 } 1294 default: 1295 assert(c->type > cntype_min); 1296 assert(c->type < cntype_max); 1297 abort(); 1298 } 1299 return 0; 1300 } 1301 1302 /* Add a null pointer to the end of a sequence. ptr is consumed on success 1303 * (to be replaced by *ptr_out), left alone on failure. */ 1304 static krb5_error_code 1305 null_terminate(const struct atype_info *eltinfo, void *ptr, size_t count, 1306 void **ptr_out) 1307 { 1308 const struct ptr_info *ptrinfo = eltinfo->tinfo; 1309 void *endptr; 1310 1311 assert(eltinfo->type == atype_ptr); 1312 ptr = realloc(ptr, (count + 1) * eltinfo->size); 1313 if (ptr == NULL) 1314 return ENOMEM; 1315 endptr = (char *)ptr + count * eltinfo->size; 1316 STOREPTR(NULL, ptrinfo, endptr); 1317 *ptr_out = ptr; 1318 return 0; 1319 } 1320 1321 static krb5_error_code 1322 decode_atype_to_ptr(const taginfo *t, const uint8_t *asn1, size_t len, 1323 const struct atype_info *a, void **ptr_out) 1324 { 1325 krb5_error_code ret; 1326 void *ptr; 1327 size_t count; 1328 1329 *ptr_out = NULL; 1330 switch (a->type) { 1331 case atype_nullterm_sequence_of: 1332 case atype_nonempty_nullterm_sequence_of: 1333 ret = decode_sequence_of(asn1, len, a->tinfo, &ptr, &count); 1334 if (ret) 1335 return ret; 1336 ret = null_terminate(a->tinfo, ptr, count, &ptr); 1337 if (ret) { 1338 free_sequence_of(a->tinfo, ptr, count); 1339 return ret; 1340 } 1341 /* Historically we do not enforce non-emptiness of sequences when 1342 * decoding, even when it is required by the ASN.1 type. */ 1343 break; 1344 default: 1345 ptr = calloc(a->size, 1); 1346 if (ptr == NULL) 1347 return ENOMEM; 1348 ret = decode_atype(t, asn1, len, a, ptr); 1349 if (ret) { 1350 free(ptr); 1351 return ret; 1352 } 1353 break; 1354 } 1355 *ptr_out = ptr; 1356 return 0; 1357 } 1358 1359 /* Initialize a C object when the corresponding ASN.1 type was omitted within a 1360 * sequence. If the ASN.1 type is not optional, return ASN1_MISSING_FIELD. */ 1361 static krb5_error_code 1362 omit_atype(const struct atype_info *a, void *val) 1363 { 1364 switch (a->type) 1365 { 1366 case atype_fn: 1367 case atype_sequence: 1368 case atype_nullterm_sequence_of: 1369 case atype_nonempty_nullterm_sequence_of: 1370 case atype_counted: 1371 case atype_bool: 1372 case atype_int: 1373 case atype_uint: 1374 case atype_int_immediate: 1375 return ASN1_MISSING_FIELD; 1376 case atype_ptr: { 1377 const struct ptr_info *ptrinfo = a->tinfo; 1378 return omit_atype(ptrinfo->basetype, val); 1379 } 1380 case atype_offset: { 1381 const struct offset_info *off = a->tinfo; 1382 return omit_atype(off->basetype, (char *)val + off->dataoff); 1383 } 1384 case atype_tagged_thing: { 1385 const struct tagged_info *tag = a->tinfo; 1386 return omit_atype(tag->basetype, val); 1387 } 1388 case atype_optional: { 1389 const struct optional_info *opt = a->tinfo; 1390 if (opt->init != NULL) 1391 opt->init(val); 1392 return 0; 1393 } 1394 default: 1395 abort(); 1396 } 1397 } 1398 1399 /* Decode an ASN.1 sequence into a C object. */ 1400 static krb5_error_code 1401 decode_sequence(const uint8_t *asn1, size_t len, const struct seq_info *seq, 1402 void *val) 1403 { 1404 krb5_error_code ret; 1405 const uint8_t *contents; 1406 size_t i, j, clen; 1407 taginfo t; 1408 1409 assert(seq->n_fields > 0); 1410 for (i = 0; i < seq->n_fields; i++) { 1411 if (len == 0) 1412 break; 1413 ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len); 1414 if (ret) 1415 goto error; 1416 /* 1417 * Find the applicable sequence field. This logic is a little 1418 * oversimplified; we could match an element to an optional extensible 1419 * choice or optional stored-DER type when we ought to match a 1420 * subsequent non-optional field. But it's unwise and (hopefully) very 1421 * rare for ASN.1 modules to require such precision. 1422 */ 1423 for (; i < seq->n_fields; i++) { 1424 if (check_atype_tag(seq->fields[i], &t)) 1425 break; 1426 ret = omit_atype(seq->fields[i], val); 1427 if (ret) 1428 goto error; 1429 } 1430 /* We currently model all sequences as extensible. We should consider 1431 * changing this before making the encoder visible to plugins. */ 1432 if (i == seq->n_fields) 1433 break; 1434 ret = decode_atype(&t, contents, clen, seq->fields[i], val); 1435 if (ret) 1436 goto error; 1437 } 1438 /* Initialize any fields in the C object which were not accounted for in 1439 * the sequence. Error out if any of them aren't optional. */ 1440 for (; i < seq->n_fields; i++) { 1441 ret = omit_atype(seq->fields[i], val); 1442 if (ret) 1443 goto error; 1444 } 1445 return 0; 1446 1447 error: 1448 /* Free what we've decoded so far. Free pointers in a second pass in 1449 * case multiple fields refer to the same pointer. */ 1450 for (j = 0; j < i; j++) 1451 free_atype(seq->fields[j], val); 1452 for (j = 0; j < i; j++) 1453 free_atype_ptr(seq->fields[j], val); 1454 return ret; 1455 } 1456 1457 static krb5_error_code 1458 decode_sequence_of(const uint8_t *asn1, size_t len, 1459 const struct atype_info *elemtype, void **seq_out, 1460 size_t *count_out) 1461 { 1462 krb5_error_code ret; 1463 void *seq = NULL, *elem, *newseq; 1464 const uint8_t *contents; 1465 size_t clen, count = 0; 1466 taginfo t; 1467 1468 *seq_out = NULL; 1469 *count_out = 0; 1470 while (len > 0) { 1471 ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len); 1472 if (ret) 1473 goto error; 1474 if (!check_atype_tag(elemtype, &t)) { 1475 ret = ASN1_BAD_ID; 1476 goto error; 1477 } 1478 newseq = realloc(seq, (count + 1) * elemtype->size); 1479 if (newseq == NULL) { 1480 ret = ENOMEM; 1481 goto error; 1482 } 1483 seq = newseq; 1484 elem = (char *)seq + count * elemtype->size; 1485 memset(elem, 0, elemtype->size); 1486 ret = decode_atype(&t, contents, clen, elemtype, elem); 1487 if (ret) 1488 goto error; 1489 count++; 1490 } 1491 *seq_out = seq; 1492 *count_out = count; 1493 return 0; 1494 1495 error: 1496 free_sequence_of(elemtype, seq, count); 1497 free(seq); 1498 return ret; 1499 } 1500 1501 /* These three entry points are only needed for the kdc_req_body hack and may 1502 * go away at some point. Define them here so we can use short names above. */ 1503 1504 krb5_error_code 1505 k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a, 1506 taginfo *tag_out) 1507 { 1508 return encode_atype(buf, val, a, tag_out); 1509 } 1510 1511 krb5_error_code 1512 k5_asn1_decode_atype(const taginfo *t, const uint8_t *asn1, size_t len, 1513 const struct atype_info *a, void *val) 1514 { 1515 return decode_atype(t, asn1, len, a, val); 1516 } 1517 1518 krb5_error_code 1519 k5_asn1_full_encode(const void *rep, const struct atype_info *a, 1520 krb5_data **code_out) 1521 { 1522 krb5_error_code ret; 1523 asn1buf buf; 1524 krb5_data *d; 1525 uint8_t *bytes; 1526 1527 *code_out = NULL; 1528 1529 if (rep == NULL) 1530 return ASN1_MISSING_FIELD; 1531 1532 /* Make a first pass over rep to count the encoding size. */ 1533 buf.ptr = NULL; 1534 buf.count = 0; 1535 ret = encode_atype_and_tag(&buf, rep, a); 1536 if (ret) 1537 return ret; 1538 1539 /* Allocate space for the encoding. */ 1540 bytes = malloc(buf.count + 1); 1541 if (bytes == NULL) 1542 return ENOMEM; 1543 bytes[buf.count] = 0; 1544 1545 /* Make a second pass over rep to encode it. buf.ptr moves backwards as we 1546 * encode, and will always exactly return to the base. */ 1547 buf.ptr = bytes + buf.count; 1548 buf.count = 0; 1549 ret = encode_atype_and_tag(&buf, rep, a); 1550 if (ret) { 1551 free(bytes); 1552 return ret; 1553 } 1554 assert(buf.ptr == bytes); 1555 1556 /* Create the output data object. */ 1557 *code_out = malloc(sizeof(*d)); 1558 if (*code_out == NULL) { 1559 free(bytes); 1560 return ENOMEM; 1561 } 1562 **code_out = make_data(bytes, buf.count); 1563 return 0; 1564 } 1565 1566 krb5_error_code 1567 k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a, 1568 void **retrep) 1569 { 1570 krb5_error_code ret; 1571 const uint8_t *contents, *remainder; 1572 size_t clen, rlen; 1573 taginfo t; 1574 1575 *retrep = NULL; 1576 ret = get_tag((uint8_t *)code->data, code->length, &t, &contents, 1577 &clen, &remainder, &rlen); 1578 if (ret) 1579 return ret; 1580 /* rlen should be 0, but we don't check it (and due to padding in 1581 * non-length-preserving enctypes, it will sometimes be nonzero). */ 1582 if (!check_atype_tag(a, &t)) 1583 return ASN1_BAD_ID; 1584 return decode_atype_to_ptr(&t, contents, clen, a, retrep); 1585 } 1586