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