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