quickder.c (29918B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 Optimized ASN.1 DER decoder 7 */ 8 9 #include "secerr.h" 10 #include "secasn1.h" /* for SEC_ASN1GetSubtemplate */ 11 #include "secitem.h" 12 13 /* 14 * simple definite-length ASN.1 decoder 15 */ 16 17 static unsigned char* 18 definite_length_decoder(const unsigned char* buf, 19 const unsigned int buf_length, 20 unsigned int* out_data_length, 21 PRBool includeTag) 22 { 23 unsigned char tag; 24 unsigned int used_length = 0; 25 unsigned int data_length = 0; 26 unsigned char length_field_len = 0; 27 unsigned char byte; 28 unsigned int i; 29 30 if (used_length >= buf_length) { 31 /* Tag field was not found! */ 32 return NULL; 33 } 34 tag = buf[used_length++]; 35 36 if (tag == 0) { 37 /* End-of-contents octects should not be present in DER because 38 DER doesn't use the indefinite length form. */ 39 return NULL; 40 } 41 42 if ((tag & 0x1F) == 0x1F) { 43 /* High tag number (a tag number > 30) is not supported */ 44 return NULL; 45 } 46 47 if (used_length >= buf_length) { 48 /* Length field was not found! */ 49 return NULL; 50 } 51 byte = buf[used_length++]; 52 53 if (!(byte & 0x80)) { 54 /* Short form: The high bit is not set. */ 55 data_length = byte; /* clarity; we're returning a 32-bit int. */ 56 } else { 57 /* Long form. Extract the field length */ 58 length_field_len = byte & 0x7F; 59 if (length_field_len == 0) { 60 /* DER doesn't use the indefinite length form. */ 61 return NULL; 62 } 63 64 if (length_field_len > sizeof(data_length)) { 65 /* We don't support an extended length field longer than 66 4 bytes (2^32) */ 67 return NULL; 68 } 69 70 if (length_field_len > (buf_length - used_length)) { 71 /* Extended length field was not found */ 72 return NULL; 73 } 74 75 /* Iterate across the extended length field */ 76 for (i = 0; i < length_field_len; i++) { 77 byte = buf[used_length++]; 78 data_length = (data_length << 8) | byte; 79 80 if (i == 0) { 81 PRBool too_long = PR_FALSE; 82 if (length_field_len == 1) { 83 too_long = ((byte & 0x80) == 0); /* Short form suffices */ 84 } else { 85 too_long = (byte == 0); /* This zero byte can be omitted */ 86 } 87 if (too_long) { 88 /* The length is longer than needed. */ 89 return NULL; 90 } 91 } 92 } 93 } 94 95 if ((tag & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_NULL && data_length != 0) { 96 /* The DER encoding of NULL has no contents octets */ 97 return NULL; 98 } 99 100 if (data_length > (buf_length - used_length)) { 101 /* The decoded length exceeds the available buffer */ 102 return NULL; 103 } 104 105 if (includeTag) { 106 data_length += used_length; 107 } 108 109 *out_data_length = data_length; 110 return ((unsigned char*)buf + (includeTag ? 0 : used_length)); 111 } 112 113 static SECStatus 114 GetItem(SECItem* src, SECItem* dest, PRBool includeTag) 115 { 116 if ((!src) || (!dest) || (!src->data && src->len)) { 117 PORT_SetError(SEC_ERROR_INVALID_ARGS); 118 return SECFailure; 119 } 120 121 if (!src->len) { 122 /* reaching the end of the buffer is not an error */ 123 dest->data = NULL; 124 dest->len = 0; 125 return SECSuccess; 126 } 127 128 dest->data = definite_length_decoder(src->data, src->len, &dest->len, 129 includeTag); 130 if (dest->data == NULL) { 131 PORT_SetError(SEC_ERROR_BAD_DER); 132 return SECFailure; 133 } 134 src->len -= (int)(dest->data - src->data) + dest->len; 135 src->data = dest->data + dest->len; 136 return SECSuccess; 137 } 138 139 /* check if the actual component's type matches the type in the template */ 140 141 static SECStatus 142 MatchComponentType(const SEC_ASN1Template* templateEntry, 143 SECItem* item, PRBool* match, void* dest) 144 { 145 unsigned long kind = 0; 146 unsigned char tag = 0; 147 148 if ((!item) || (!item->data && item->len) || (!templateEntry) || (!match)) { 149 PORT_SetError(SEC_ERROR_INVALID_ARGS); 150 return SECFailure; 151 } 152 153 if (!item->len) { 154 *match = PR_FALSE; 155 return SECSuccess; 156 } 157 158 kind = templateEntry->kind; 159 tag = *(unsigned char*)item->data; 160 161 if (((kind & SEC_ASN1_INLINE) || 162 (kind & SEC_ASN1_POINTER)) && 163 (0 == (kind & SEC_ASN1_TAG_MASK))) { 164 /* These cases are special because the template's "kind" does not 165 give us the information for the ASN.1 tag of the next item. It can 166 only be figured out from the subtemplate. */ 167 if (!(kind & SEC_ASN1_OPTIONAL)) { 168 /* This is a required component. If there is a type mismatch, 169 the decoding of the subtemplate will fail, so assume this 170 is a match at the parent level and let it fail later. This 171 avoids a redundant check in matching cases */ 172 *match = PR_TRUE; 173 return SECSuccess; 174 } else { 175 /* optional component. This is the hard case. Now we need to 176 look at the subtemplate to get the expected kind */ 177 const SEC_ASN1Template* subTemplate = 178 SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE); 179 if (!subTemplate) { 180 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); 181 return SECFailure; 182 } 183 if ((subTemplate->kind & SEC_ASN1_INLINE) || 184 (subTemplate->kind & SEC_ASN1_POINTER)) { 185 /* disallow nesting SEC_ASN1_POINTER and SEC_ASN1_INLINE, 186 otherwise you may get a false positive due to the recursion 187 optimization above that always matches the type if the 188 component is required . Nesting these should never be 189 required, so that no one should miss this ability */ 190 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); 191 return SECFailure; 192 } 193 return MatchComponentType(subTemplate, item, match, 194 (void*)((char*)dest + templateEntry->offset)); 195 } 196 } 197 198 if (kind & SEC_ASN1_CHOICE) { 199 /* we need to check the component's tag against each choice's tag */ 200 /* XXX it would be nice to save the index of the choice here so that 201 DecodeChoice wouldn't have to do this again. However, due to the 202 recursivity of MatchComponentType, we don't know if we are in a 203 required or optional component, so we can't write anywhere in 204 the destination within this function */ 205 unsigned choiceIndex = 1; 206 const SEC_ASN1Template* choiceEntry; 207 while ((choiceEntry = &templateEntry[choiceIndex++]) && (choiceEntry->kind)) { 208 if ((SECSuccess == MatchComponentType(choiceEntry, item, match, 209 (void*)((char*)dest + choiceEntry->offset))) && 210 (PR_TRUE == *match)) { 211 return SECSuccess; 212 } 213 } 214 /* no match, caller must decide if this is BAD DER, or not. */ 215 *match = PR_FALSE; 216 return SECSuccess; 217 } 218 219 if (kind & SEC_ASN1_ANY) { 220 /* SEC_ASN1_ANY always matches */ 221 *match = PR_TRUE; 222 return SECSuccess; 223 } 224 225 if ((0 == ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK)) && 226 (!(kind & SEC_ASN1_EXPLICIT)) && 227 (((kind & SEC_ASN1_SAVE) || 228 (kind & SEC_ASN1_SKIP)) && 229 (!(kind & SEC_ASN1_OPTIONAL)))) { 230 /* when saving or skipping a required component, a type is not 231 required in the template. This is for legacy support of 232 SEC_ASN1_SAVE and SEC_ASN1_SKIP only. XXX I would like to 233 deprecate these usages and always require a type, as this 234 disables type checking, and effectively forbids us from 235 transparently ignoring optional components we aren't aware of */ 236 *match = PR_TRUE; 237 return SECSuccess; 238 } 239 240 /* first, do a class check */ 241 if ((tag & SEC_ASN1_CLASS_MASK) != 242 (((unsigned char)kind) & SEC_ASN1_CLASS_MASK)) { 243 /* this is only to help debugging of the decoder in case of problems */ 244 /* unsigned char tagclass = tag & SEC_ASN1_CLASS_MASK; */ 245 /* unsigned char expectedclass = (unsigned char)kind & SEC_ASN1_CLASS_MASK; */ 246 *match = PR_FALSE; 247 return SECSuccess; 248 } 249 250 /* now do a tag check */ 251 if (((unsigned char)kind & SEC_ASN1_TAGNUM_MASK) != 252 (tag & SEC_ASN1_TAGNUM_MASK)) { 253 *match = PR_FALSE; 254 return SECSuccess; 255 } 256 257 /* now, do a method check. This depends on the class */ 258 switch (tag & SEC_ASN1_CLASS_MASK) { 259 case SEC_ASN1_UNIVERSAL: 260 /* For types of the SEC_ASN1_UNIVERSAL class, we know which must be 261 primitive or constructed based on the tag */ 262 switch (tag & SEC_ASN1_TAGNUM_MASK) { 263 case SEC_ASN1_SEQUENCE: 264 case SEC_ASN1_SET: 265 case SEC_ASN1_EMBEDDED_PDV: 266 /* this component must be a constructed type */ 267 /* XXX add any new universal constructed type here */ 268 if (tag & SEC_ASN1_CONSTRUCTED) { 269 *match = PR_TRUE; 270 return SECSuccess; 271 } 272 break; 273 274 default: 275 /* this component must be a primitive type */ 276 if (!(tag & SEC_ASN1_CONSTRUCTED)) { 277 *match = PR_TRUE; 278 return SECSuccess; 279 } 280 break; 281 } 282 break; 283 284 default: 285 /* for all other classes, we check the method based on the template */ 286 if ((unsigned char)(kind & SEC_ASN1_METHOD_MASK) == 287 (tag & SEC_ASN1_METHOD_MASK)) { 288 *match = PR_TRUE; 289 return SECSuccess; 290 } 291 /* method does not match between template and component */ 292 break; 293 } 294 295 *match = PR_FALSE; 296 return SECSuccess; 297 } 298 299 #ifdef DEBUG 300 301 static SECStatus 302 CheckSequenceTemplate(const SEC_ASN1Template* sequenceTemplate) 303 { 304 SECStatus rv = SECSuccess; 305 const SEC_ASN1Template* sequenceEntry = NULL; 306 unsigned long seqIndex = 0; 307 unsigned long lastEntryIndex = 0; 308 unsigned long ambiguityIndex = 0; 309 PRBool foundAmbiguity = PR_FALSE; 310 311 do { 312 sequenceEntry = &sequenceTemplate[seqIndex++]; 313 if (sequenceEntry->kind) { 314 /* ensure that we don't have an optional component of SEC_ASN1_ANY 315 in the middle of the sequence, since we could not handle it */ 316 /* XXX this function needs to dig into the subtemplates to find 317 the next tag */ 318 if ((PR_FALSE == foundAmbiguity) && 319 (sequenceEntry->kind & SEC_ASN1_OPTIONAL) && 320 (sequenceEntry->kind & SEC_ASN1_ANY)) { 321 foundAmbiguity = PR_TRUE; 322 ambiguityIndex = seqIndex - 1; 323 } 324 } 325 } while (sequenceEntry->kind); 326 327 lastEntryIndex = seqIndex - 2; 328 329 if (PR_FALSE != foundAmbiguity) { 330 if (ambiguityIndex < lastEntryIndex) { 331 /* ambiguity can only be tolerated on the last entry */ 332 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); 333 rv = SECFailure; 334 } 335 } 336 337 /* XXX also enforce ASN.1 requirement that tags be 338 distinct for consecutive optional components */ 339 340 return rv; 341 } 342 343 #endif 344 345 static SECStatus DecodeItem(void* dest, 346 const SEC_ASN1Template* templateEntry, 347 SECItem* src, PLArenaPool* arena, PRBool checkTag); 348 349 static SECStatus 350 DecodeSequence(void* dest, 351 const SEC_ASN1Template* templateEntry, 352 SECItem* src, PLArenaPool* arena) 353 { 354 SECStatus rv = SECSuccess; 355 SECItem source; 356 SECItem sequence; 357 const SEC_ASN1Template* sequenceTemplate = &(templateEntry[1]); 358 const SEC_ASN1Template* sequenceEntry = NULL; 359 unsigned long seqindex = 0; 360 361 #ifdef DEBUG 362 /* for a sequence, we need to validate the template. */ 363 rv = CheckSequenceTemplate(sequenceTemplate); 364 #endif 365 366 source = *src; 367 368 /* get the sequence */ 369 if (SECSuccess == rv) { 370 rv = GetItem(&source, &sequence, PR_FALSE); 371 } 372 373 /* process it */ 374 if (SECSuccess == rv) 375 do { 376 sequenceEntry = &sequenceTemplate[seqindex++]; 377 if ((sequenceEntry && sequenceEntry->kind) && 378 (sequenceEntry->kind != SEC_ASN1_SKIP_REST)) { 379 rv = DecodeItem(dest, sequenceEntry, &sequence, arena, PR_TRUE); 380 } 381 } while ((SECSuccess == rv) && 382 (sequenceEntry->kind && 383 sequenceEntry->kind != SEC_ASN1_SKIP_REST)); 384 /* we should have consumed all the bytes in the sequence by now 385 unless the caller doesn't care about the rest of the sequence */ 386 if (SECSuccess == rv && sequence.len && 387 sequenceEntry && sequenceEntry->kind != SEC_ASN1_SKIP_REST) { 388 /* it isn't 100% clear whether this is a bad DER or a bad template. 389 The problem is that logically, they don't match - there is extra 390 data in the DER that the template doesn't know about */ 391 PORT_SetError(SEC_ERROR_BAD_DER); 392 rv = SECFailure; 393 } 394 395 return rv; 396 } 397 398 static SECStatus 399 DecodeInline(void* dest, 400 const SEC_ASN1Template* templateEntry, 401 SECItem* src, PLArenaPool* arena, PRBool checkTag) 402 { 403 const SEC_ASN1Template* inlineTemplate = 404 SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE); 405 return DecodeItem((void*)((char*)dest + templateEntry->offset), 406 inlineTemplate, src, arena, checkTag); 407 } 408 409 static SECStatus 410 DecodePointer(void* dest, 411 const SEC_ASN1Template* templateEntry, 412 SECItem* src, PLArenaPool* arena, PRBool checkTag) 413 { 414 const SEC_ASN1Template* ptrTemplate = 415 SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE); 416 if (!ptrTemplate) { 417 PORT_SetError(SEC_ERROR_INVALID_ARGS); 418 return SECFailure; 419 } 420 void* subdata = PORT_ArenaZAlloc(arena, ptrTemplate->size); 421 *(void**)((char*)dest + templateEntry->offset) = subdata; 422 if (subdata) { 423 return DecodeItem(subdata, ptrTemplate, src, arena, checkTag); 424 } else { 425 PORT_SetError(SEC_ERROR_NO_MEMORY); 426 return SECFailure; 427 } 428 } 429 430 static SECStatus 431 DecodeImplicit(void* dest, 432 const SEC_ASN1Template* templateEntry, 433 SECItem* src, PLArenaPool* arena) 434 { 435 if (templateEntry->kind & SEC_ASN1_POINTER) { 436 return DecodePointer((void*)((char*)dest), 437 templateEntry, src, arena, PR_FALSE); 438 } else { 439 return DecodeInline((void*)((char*)dest), 440 templateEntry, src, arena, PR_FALSE); 441 } 442 } 443 444 static SECStatus 445 DecodeChoice(void* dest, 446 const SEC_ASN1Template* templateEntry, 447 SECItem* src, PLArenaPool* arena) 448 { 449 SECStatus rv = SECSuccess; 450 SECItem choice; 451 const SEC_ASN1Template* choiceTemplate = &(templateEntry[1]); 452 const SEC_ASN1Template* choiceEntry = NULL; 453 unsigned long choiceindex = 0; 454 455 /* XXX for a choice component, we should validate the template to make 456 sure the tags are distinct, in debug builds. This hasn't been 457 implemented yet */ 458 /* rv = CheckChoiceTemplate(sequenceTemplate); */ 459 460 /* process it */ 461 do { 462 choice = *src; 463 choiceEntry = &choiceTemplate[choiceindex++]; 464 if (choiceEntry->kind) { 465 rv = DecodeItem(dest, choiceEntry, &choice, arena, PR_TRUE); 466 } 467 } while ((SECFailure == rv) && (choiceEntry->kind)); 468 469 if (SECFailure == rv) { 470 /* the component didn't match any of the choices */ 471 PORT_SetError(SEC_ERROR_BAD_DER); 472 } else { 473 /* set the type in the union here */ 474 int* which = (int*)((char*)dest + templateEntry->offset); 475 *which = (int)choiceEntry->size; 476 } 477 478 /* we should have consumed all the bytes by now */ 479 /* fail if we have not */ 480 if (SECSuccess == rv && choice.len) { 481 /* there is extra data that isn't listed in the template */ 482 PORT_SetError(SEC_ERROR_BAD_DER); 483 rv = SECFailure; 484 } 485 return rv; 486 } 487 488 static SECStatus 489 DecodeGroup(void* dest, 490 const SEC_ASN1Template* templateEntry, 491 SECItem* src, PLArenaPool* arena) 492 { 493 SECStatus rv = SECSuccess; 494 SECItem source; 495 SECItem group; 496 PRUint32 totalEntries = 0; 497 PRUint32 entryIndex = 0; 498 void** entries = NULL; 499 500 const SEC_ASN1Template* subTemplate = 501 SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE); 502 503 source = *src; 504 505 /* get the group */ 506 if (SECSuccess == rv) { 507 rv = GetItem(&source, &group, PR_FALSE); 508 } 509 510 /* XXX we should check the subtemplate in debug builds */ 511 if (SECSuccess == rv) { 512 /* first, count the number of entries. Benchmarking showed that this 513 counting pass is more efficient than trying to allocate entries as 514 we read the DER, even if allocating many entries at a time 515 */ 516 SECItem counter = group; 517 do { 518 SECItem anitem; 519 rv = GetItem(&counter, &anitem, PR_TRUE); 520 if (SECSuccess == rv && (anitem.len)) { 521 totalEntries++; 522 } 523 } while ((SECSuccess == rv) && (counter.len)); 524 525 if (SECSuccess == rv) { 526 /* allocate room for pointer array and entries */ 527 /* we want to allocate the array even if there is 0 entry */ 528 entries = (void**)PORT_ArenaZAlloc(arena, sizeof(void*) * (totalEntries + 1) + /* the extra one is for NULL termination */ 529 subTemplate->size * totalEntries); 530 531 if (entries) { 532 entries[totalEntries] = NULL; /* terminate the array */ 533 } else { 534 PORT_SetError(SEC_ERROR_NO_MEMORY); 535 rv = SECFailure; 536 } 537 if (SECSuccess == rv) { 538 void* entriesData = (unsigned char*)entries + (unsigned long)(sizeof(void*) * (totalEntries + 1)); 539 /* and fix the pointers in the array */ 540 PRUint32 entriesIndex = 0; 541 for (entriesIndex = 0; entriesIndex < totalEntries; entriesIndex++) { 542 entries[entriesIndex] = 543 (char*)entriesData + (subTemplate->size * entriesIndex); 544 } 545 } 546 } 547 } 548 549 if (SECSuccess == rv && totalEntries) 550 do { 551 if (!(entryIndex < totalEntries)) { 552 rv = SECFailure; 553 break; 554 } 555 rv = DecodeItem(entries[entryIndex++], subTemplate, &group, arena, PR_TRUE); 556 } while ((SECSuccess == rv) && (group.len)); 557 /* we should be at the end of the set by now */ 558 /* save the entries where requested */ 559 memcpy(((char*)dest + templateEntry->offset), &entries, sizeof(void**)); 560 561 return rv; 562 } 563 564 static SECStatus 565 DecodeExplicit(void* dest, 566 const SEC_ASN1Template* templateEntry, 567 SECItem* src, PLArenaPool* arena) 568 { 569 SECStatus rv = SECSuccess; 570 SECItem subItem; 571 SECItem constructed = *src; 572 573 rv = GetItem(&constructed, &subItem, PR_FALSE); 574 575 if (SECSuccess == rv) { 576 if (templateEntry->kind & SEC_ASN1_POINTER) { 577 rv = DecodePointer(dest, templateEntry, &subItem, arena, PR_TRUE); 578 } else { 579 rv = DecodeInline(dest, templateEntry, &subItem, arena, PR_TRUE); 580 } 581 } 582 583 return rv; 584 } 585 586 /* new decoder implementation. This is a recursive function */ 587 588 static SECStatus 589 DecodeItem(void* dest, 590 const SEC_ASN1Template* templateEntry, 591 SECItem* src, PLArenaPool* arena, PRBool checkTag) 592 { 593 SECStatus rv = SECSuccess; 594 SECItem temp; 595 SECItem mark = { siBuffer, NULL, 0 }; 596 PRBool pop = PR_FALSE; 597 PRBool decode = PR_TRUE; 598 PRBool save = PR_FALSE; 599 unsigned long kind; 600 PRBool match = PR_TRUE; 601 602 PR_ASSERT(src && dest && templateEntry && arena); 603 #if 0 604 if (!src || !dest || !templateEntry || !arena) 605 { 606 PORT_SetError(SEC_ERROR_INVALID_ARGS); 607 rv = SECFailure; 608 } 609 #endif 610 611 if (SECSuccess == rv) { 612 /* do the template validation */ 613 kind = templateEntry->kind; 614 if (!kind) { 615 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); 616 rv = SECFailure; 617 } 618 } 619 620 if (SECSuccess == rv) { 621 #ifdef DEBUG 622 if (kind & SEC_ASN1_DEBUG_BREAK) { 623 /* when debugging the decoder or a template that fails to 624 decode, put SEC_ASN1_DEBUG in the component that gives you 625 trouble. The decoder will then get to this block and assert. 626 If you want to debug the rest of the code, you can set a 627 breakpoint and set dontassert to PR_TRUE, which will let 628 you skip over the assert and continue the debugging session 629 past it. */ 630 PRBool dontassert = PR_FALSE; 631 PR_ASSERT(dontassert); /* set bkpoint here & set dontassert*/ 632 } 633 #endif 634 635 if ((kind & SEC_ASN1_SKIP) || 636 (kind & SEC_ASN1_SAVE)) { 637 /* if skipping or saving this component, don't decode it */ 638 decode = PR_FALSE; 639 } 640 641 if (kind & (SEC_ASN1_SAVE | SEC_ASN1_OPTIONAL)) { 642 /* if saving this component, or if it is optional, we may not want to 643 move past it, so save the position in case we have to rewind */ 644 mark = *src; 645 if (kind & SEC_ASN1_SAVE) { 646 save = PR_TRUE; 647 if (0 == (kind & SEC_ASN1_SKIP)) { 648 /* we will for sure have to rewind when saving this 649 component and not skipping it. This is true for all 650 legacy uses of SEC_ASN1_SAVE where the following entry 651 in the template would causes the same component to be 652 processed again */ 653 pop = PR_TRUE; 654 } 655 } 656 } 657 658 rv = GetItem(src, &temp, PR_TRUE); 659 } 660 661 if (SECSuccess == rv) { 662 /* now check if the component matches what we expect in the template */ 663 664 if (PR_TRUE == checkTag) 665 666 { 667 rv = MatchComponentType(templateEntry, &temp, &match, dest); 668 } 669 670 if ((SECSuccess == rv) && (PR_TRUE != match)) { 671 if (kind & SEC_ASN1_OPTIONAL) { 672 673 /* the optional component is missing. This is not fatal. */ 674 /* Rewind, don't decode, and don't save */ 675 pop = PR_TRUE; 676 decode = PR_FALSE; 677 save = PR_FALSE; 678 } else { 679 /* a required component is missing. abort */ 680 PORT_SetError(SEC_ERROR_BAD_DER); 681 rv = SECFailure; 682 } 683 } 684 } 685 686 if ((SECSuccess == rv) && (PR_TRUE == decode)) { 687 /* the order of processing here is is the tricky part */ 688 /* we start with our special cases */ 689 /* first, check the component class */ 690 if (kind & SEC_ASN1_INLINE) { 691 /* decode inline template */ 692 rv = DecodeInline(dest, templateEntry, &temp, arena, PR_TRUE); 693 } 694 695 else if (kind & SEC_ASN1_EXPLICIT) { 696 rv = DecodeExplicit(dest, templateEntry, &temp, arena); 697 } else if ((SEC_ASN1_UNIVERSAL != (kind & SEC_ASN1_CLASS_MASK)) && 698 699 (!(kind & SEC_ASN1_EXPLICIT))) { 700 701 /* decode implicitly tagged components */ 702 rv = DecodeImplicit(dest, templateEntry, &temp, arena); 703 } else if (kind & SEC_ASN1_POINTER) { 704 rv = DecodePointer(dest, templateEntry, &temp, arena, PR_TRUE); 705 } else if (kind & SEC_ASN1_CHOICE) { 706 rv = DecodeChoice(dest, templateEntry, &temp, arena); 707 } else if (kind & SEC_ASN1_ANY) { 708 /* catch-all ANY type, don't decode */ 709 save = PR_TRUE; 710 if (kind & SEC_ASN1_INNER) { 711 /* skip the tag and length */ 712 SECItem newtemp = temp; 713 rv = GetItem(&newtemp, &temp, PR_FALSE); 714 } 715 } else if (kind & SEC_ASN1_GROUP) { 716 if ((SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) || 717 (SEC_ASN1_SET == (kind & SEC_ASN1_TAGNUM_MASK))) { 718 rv = DecodeGroup(dest, templateEntry, &temp, arena); 719 } else { 720 /* a group can only be a SET OF or SEQUENCE OF */ 721 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); 722 rv = SECFailure; 723 } 724 } else if (SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) { 725 /* plain SEQUENCE */ 726 rv = DecodeSequence(dest, templateEntry, &temp, arena); 727 } else { 728 /* handle all other types as "save" */ 729 /* we should only get here for primitive universal types */ 730 SECItem newtemp = temp; 731 rv = GetItem(&newtemp, &temp, PR_FALSE); 732 save = PR_TRUE; 733 if ((SECSuccess == rv) && 734 SEC_ASN1_UNIVERSAL == (kind & SEC_ASN1_CLASS_MASK)) { 735 unsigned long tagnum = kind & SEC_ASN1_TAGNUM_MASK; 736 if (temp.len == 0 && (tagnum == SEC_ASN1_BOOLEAN || 737 tagnum == SEC_ASN1_INTEGER || 738 tagnum == SEC_ASN1_BIT_STRING || 739 tagnum == SEC_ASN1_OBJECT_ID || 740 tagnum == SEC_ASN1_ENUMERATED || 741 tagnum == SEC_ASN1_UTC_TIME || 742 tagnum == SEC_ASN1_GENERALIZED_TIME)) { 743 /* these types MUST have at least one content octet */ 744 PORT_SetError(SEC_ERROR_BAD_DER); 745 rv = SECFailure; 746 } else 747 switch (tagnum) { 748 /* special cases of primitive types */ 749 case SEC_ASN1_INTEGER: { 750 SECItem* destItem = (SECItem*)((char*)dest + 751 templateEntry->offset); 752 if (destItem && (siUnsignedInteger == destItem->type)) { 753 /* A leading 0 is only allowed when a value 754 * would otherwise be interpreted as negative. */ 755 if (temp.len > 1 && temp.data[0] == 0) { 756 temp.data++; 757 temp.len--; 758 if (!(temp.data[0] & 0x80)) { 759 PORT_SetError(SEC_ERROR_BAD_DER); 760 rv = SECFailure; 761 } 762 } 763 } 764 break; 765 } 766 767 case SEC_ASN1_BIT_STRING: { 768 /* Can't be 8 or more spare bits, or any spare bits 769 * if there are no octets. */ 770 if (temp.data[0] >= 8 || (temp.data[0] > 0 && temp.len == 1)) { 771 PORT_SetError(SEC_ERROR_BAD_DER); 772 rv = SECFailure; 773 break; 774 } 775 /* change the length in the SECItem to be the number 776 of bits */ 777 temp.len = (temp.len - 1) * 8 - (temp.data[0] & 0x7); 778 temp.data++; 779 break; 780 } 781 782 default: { 783 break; 784 } 785 } 786 } 787 } 788 } 789 790 if ((SECSuccess == rv) && (PR_TRUE == save)) { 791 SECItem* destItem = (SECItem*)((char*)dest + templateEntry->offset); 792 if (destItem) { 793 /* we leave the type alone in the destination SECItem. 794 If part of the destination was allocated by the decoder, in 795 cases of POINTER, SET OF and SEQUENCE OF, then type is set to 796 siBuffer due to the use of PORT_ArenaZAlloc*/ 797 destItem->data = temp.len ? temp.data : NULL; 798 destItem->len = temp.len; 799 } else { 800 PORT_SetError(SEC_ERROR_INVALID_ARGS); 801 rv = SECFailure; 802 } 803 } 804 805 if (PR_TRUE == pop) { 806 /* we don't want to move ahead, so restore the position */ 807 *src = mark; 808 } 809 return rv; 810 } 811 812 /* the function below is the public one */ 813 814 SECStatus 815 SEC_QuickDERDecodeItem(PLArenaPool* arena, void* dest, 816 const SEC_ASN1Template* templateEntry, 817 const SECItem* src) 818 { 819 SECStatus rv = SECSuccess; 820 SECItem newsrc; 821 822 if (!arena || !templateEntry || !src) { 823 PORT_SetError(SEC_ERROR_INVALID_ARGS); 824 rv = SECFailure; 825 } 826 827 if (SECSuccess == rv) { 828 newsrc = *src; 829 rv = DecodeItem(dest, templateEntry, &newsrc, arena, PR_TRUE); 830 if (SECSuccess == rv && newsrc.len) { 831 rv = SECFailure; 832 PORT_SetError(SEC_ERROR_EXTRA_INPUT); 833 } 834 } 835 836 return rv; 837 }