1 /* wintrust asn functions 2 * 3 * Copyright 2007 Juan Lang 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 * 19 */ 20 21 #include "wintrust_priv.h" 22 23 #include <assert.h> 24 #include <snmp.h> 25 #include <wine/exception.h> 26 27 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn); 28 29 #ifdef WORDS_BIGENDIAN 30 31 #define hton16(x) (x) 32 #define n16toh(x) (x) 33 34 #else 35 36 #define hton16(x) RtlUshortByteSwap(x) 37 #define n16toh(x) RtlUshortByteSwap(x) 38 39 #endif 40 41 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01) 42 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03) 43 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e) 44 45 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded) 46 { 47 DWORD bytesNeeded, significantBytes = 0; 48 49 if (len <= 0x7f) 50 bytesNeeded = 1; 51 else 52 { 53 DWORD temp; 54 55 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000); 56 temp <<= 8, significantBytes--) 57 ; 58 bytesNeeded = significantBytes + 1; 59 } 60 if (!pbEncoded) 61 { 62 *pcbEncoded = bytesNeeded; 63 return TRUE; 64 } 65 if (*pcbEncoded < bytesNeeded) 66 { 67 SetLastError(ERROR_MORE_DATA); 68 return FALSE; 69 } 70 if (len <= 0x7f) 71 *pbEncoded = (BYTE)len; 72 else 73 { 74 DWORD i; 75 76 *pbEncoded++ = significantBytes | 0x80; 77 for (i = 0; i < significantBytes; i++) 78 { 79 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff); 80 len >>= 8; 81 } 82 } 83 *pcbEncoded = bytesNeeded; 84 return TRUE; 85 } 86 87 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, 88 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 89 DWORD *pcbEncoded) 90 { 91 BOOL ret = TRUE; 92 const CRYPT_DATA_BLOB *blob = pvStructInfo; 93 DWORD bytesNeeded, lenBytes; 94 95 TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded, 96 *pcbEncoded); 97 98 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes); 99 bytesNeeded = 1 + lenBytes + blob->cbData; 100 if (!pbEncoded) 101 *pcbEncoded = bytesNeeded; 102 else if (*pcbEncoded < bytesNeeded) 103 { 104 *pcbEncoded = bytesNeeded; 105 SetLastError(ERROR_MORE_DATA); 106 ret = FALSE; 107 } 108 else 109 { 110 *pbEncoded++ = ASN_OCTETSTRING; 111 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes); 112 pbEncoded += lenBytes; 113 if (blob->cbData) 114 memcpy(pbEncoded, blob->pbData, blob->cbData); 115 } 116 TRACE("returning %d\n", ret); 117 return ret; 118 } 119 120 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType, 121 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 122 DWORD *pcbEncoded) 123 { 124 BOOL ret = FALSE; 125 126 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 127 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, 128 pcbEncoded); 129 130 __TRY 131 { 132 const SPC_LINK *link = pvStructInfo; 133 DWORD bytesNeeded, lenBytes; 134 135 switch (link->dwLinkChoice) 136 { 137 case SPC_FILE_LINK_CHOICE: 138 { 139 DWORD fileNameLen, fileNameLenBytes; 140 LPWSTR ptr; 141 142 fileNameLen = link->u.pwszFile ? 143 lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0; 144 CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes); 145 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL, 146 &lenBytes); 147 bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen; 148 if (!pbEncoded) 149 { 150 *pcbEncoded = bytesNeeded; 151 ret = TRUE; 152 } 153 else if (*pcbEncoded < bytesNeeded) 154 { 155 SetLastError(ERROR_MORE_DATA); 156 *pcbEncoded = bytesNeeded; 157 } 158 else 159 { 160 *pcbEncoded = bytesNeeded; 161 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2; 162 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded, 163 &lenBytes); 164 pbEncoded += lenBytes; 165 *pbEncoded++ = ASN_CONTEXT; 166 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes); 167 pbEncoded += fileNameLenBytes; 168 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++) 169 { 170 *(WCHAR *)pbEncoded = hton16(*ptr); 171 pbEncoded += sizeof(WCHAR); 172 } 173 ret = TRUE; 174 } 175 break; 176 } 177 case SPC_MONIKER_LINK_CHOICE: 178 { 179 DWORD classIdLenBytes, dataLenBytes, dataLen; 180 CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId), 181 (BYTE *)link->u.Moniker.ClassId }; 182 183 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes); 184 CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL, 185 &dataLenBytes); 186 dataLen = 2 + classIdLenBytes + classId.cbData + 187 dataLenBytes + link->u.Moniker.SerializedData.cbData; 188 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 189 bytesNeeded = 1 + dataLen + lenBytes; 190 if (!pbEncoded) 191 { 192 *pcbEncoded = bytesNeeded; 193 ret = TRUE; 194 } 195 else if (*pcbEncoded < bytesNeeded) 196 { 197 SetLastError(ERROR_MORE_DATA); 198 *pcbEncoded = bytesNeeded; 199 } 200 else 201 { 202 DWORD size; 203 204 *pcbEncoded = bytesNeeded; 205 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1; 206 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 207 pbEncoded += lenBytes; 208 size = 1 + classIdLenBytes + classId.cbData; 209 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId, 210 pbEncoded, &size); 211 pbEncoded += size; 212 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData; 213 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, 214 &link->u.Moniker.SerializedData, pbEncoded, &size); 215 pbEncoded += size; 216 ret = TRUE; 217 } 218 break; 219 } 220 case SPC_URL_LINK_CHOICE: 221 { 222 LPWSTR ptr; 223 DWORD urlLen; 224 225 /* Check for invalid characters in URL */ 226 ret = TRUE; 227 urlLen = 0; 228 for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++) 229 if (*ptr > 0x7f) 230 { 231 *pcbEncoded = 0; 232 SetLastError(CRYPT_E_INVALID_IA5_STRING); 233 ret = FALSE; 234 } 235 else 236 urlLen++; 237 if (ret) 238 { 239 CRYPT_EncodeLen(urlLen, NULL, &lenBytes); 240 bytesNeeded = 1 + lenBytes + urlLen; 241 if (!pbEncoded) 242 *pcbEncoded = bytesNeeded; 243 else if (*pcbEncoded < bytesNeeded) 244 { 245 SetLastError(ERROR_MORE_DATA); 246 *pcbEncoded = bytesNeeded; 247 ret = FALSE; 248 } 249 else 250 { 251 *pcbEncoded = bytesNeeded; 252 *pbEncoded++ = ASN_CONTEXT; 253 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes); 254 pbEncoded += lenBytes; 255 for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++) 256 *pbEncoded++ = (BYTE)*ptr; 257 } 258 } 259 break; 260 } 261 default: 262 SetLastError(E_INVALIDARG); 263 } 264 } 265 __EXCEPT_PAGE_FAULT 266 { 267 SetLastError(STATUS_ACCESS_VIOLATION); 268 } 269 __ENDTRY 270 TRACE("returning %d\n", ret); 271 return ret; 272 } 273 274 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *, 275 BYTE *, DWORD *); 276 277 struct AsnEncodeSequenceItem 278 { 279 const void *pvStructInfo; 280 CryptEncodeObjectFunc encodeFunc; 281 DWORD size; /* used during encoding, not for your use */ 282 }; 283 284 static BOOL CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType, 285 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded, 286 DWORD *pcbEncoded) 287 { 288 BOOL ret; 289 DWORD i, dataLen = 0; 290 291 TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded); 292 for (i = 0, ret = TRUE; ret && i < cItem; i++) 293 { 294 ret = items[i].encodeFunc(dwCertEncodingType, NULL, 295 items[i].pvStructInfo, NULL, &items[i].size); 296 /* Some functions propagate their errors through the size */ 297 if (!ret) 298 *pcbEncoded = items[i].size; 299 dataLen += items[i].size; 300 } 301 if (ret) 302 { 303 DWORD lenBytes, bytesNeeded; 304 305 CRYPT_EncodeLen(dataLen, NULL, &lenBytes); 306 bytesNeeded = 1 + lenBytes + dataLen; 307 if (!pbEncoded) 308 *pcbEncoded = bytesNeeded; 309 else if (*pcbEncoded < bytesNeeded) 310 { 311 *pcbEncoded = bytesNeeded; 312 SetLastError(ERROR_MORE_DATA); 313 ret = FALSE; 314 } 315 else 316 { 317 *pcbEncoded = bytesNeeded; 318 *pbEncoded++ = ASN_SEQUENCE; 319 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); 320 pbEncoded += lenBytes; 321 for (i = 0; ret && i < cItem; i++) 322 { 323 ret = items[i].encodeFunc(dwCertEncodingType, NULL, 324 items[i].pvStructInfo, pbEncoded, &items[i].size); 325 /* Some functions propagate their errors through the size */ 326 if (!ret) 327 *pcbEncoded = items[i].size; 328 pbEncoded += items[i].size; 329 } 330 } 331 } 332 TRACE("returning %d\n", ret); 333 return ret; 334 } 335 336 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, 337 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 338 DWORD *pcbEncoded) 339 { 340 BOOL ret = FALSE; 341 342 __TRY 343 { 344 const CRYPT_BIT_BLOB *blob = pvStructInfo; 345 DWORD bytesNeeded, lenBytes, dataBytes; 346 BYTE unusedBits; 347 348 /* yep, MS allows cUnusedBits to be >= 8 */ 349 if (!blob->cUnusedBits) 350 { 351 dataBytes = blob->cbData; 352 unusedBits = 0; 353 } 354 else if (blob->cbData * 8 > blob->cUnusedBits) 355 { 356 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1; 357 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 : 358 blob->cUnusedBits; 359 } 360 else 361 { 362 dataBytes = 0; 363 unusedBits = 0; 364 } 365 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes); 366 bytesNeeded = 1 + lenBytes + dataBytes + 1; 367 if (!pbEncoded) 368 { 369 *pcbEncoded = bytesNeeded; 370 ret = TRUE; 371 } 372 else if (*pcbEncoded < bytesNeeded) 373 { 374 *pcbEncoded = bytesNeeded; 375 SetLastError(ERROR_MORE_DATA); 376 } 377 else 378 { 379 ret = TRUE; 380 *pcbEncoded = bytesNeeded; 381 *pbEncoded++ = ASN_BITSTRING; 382 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes); 383 pbEncoded += lenBytes; 384 *pbEncoded++ = unusedBits; 385 if (dataBytes) 386 { 387 BYTE mask = 0xff << unusedBits; 388 389 if (dataBytes > 1) 390 { 391 memcpy(pbEncoded, blob->pbData, dataBytes - 1); 392 pbEncoded += dataBytes - 1; 393 } 394 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask; 395 } 396 } 397 } 398 __EXCEPT_PAGE_FAULT 399 { 400 SetLastError(STATUS_ACCESS_VIOLATION); 401 } 402 __ENDTRY 403 return ret; 404 } 405 406 struct AsnConstructedItem 407 { 408 BYTE tag; 409 const void *pvStructInfo; 410 CryptEncodeObjectFunc encodeFunc; 411 }; 412 413 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType, 414 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 415 DWORD *pcbEncoded) 416 { 417 BOOL ret; 418 const struct AsnConstructedItem *item = pvStructInfo; 419 DWORD len; 420 421 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 422 item->pvStructInfo, NULL, &len))) 423 { 424 DWORD dataLen, bytesNeeded; 425 426 CRYPT_EncodeLen(len, NULL, &dataLen); 427 bytesNeeded = 1 + dataLen + len; 428 if (!pbEncoded) 429 *pcbEncoded = bytesNeeded; 430 else if (*pcbEncoded < bytesNeeded) 431 { 432 *pcbEncoded = bytesNeeded; 433 SetLastError(ERROR_MORE_DATA); 434 ret = FALSE; 435 } 436 else 437 { 438 *pcbEncoded = bytesNeeded; 439 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag; 440 CRYPT_EncodeLen(len, pbEncoded, &dataLen); 441 pbEncoded += dataLen; 442 ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 443 item->pvStructInfo, pbEncoded, &len); 444 if (!ret) 445 { 446 /* Some functions propagate their errors through the size */ 447 *pcbEncoded = len; 448 } 449 } 450 } 451 else 452 { 453 /* Some functions propagate their errors through the size */ 454 *pcbEncoded = len; 455 } 456 return ret; 457 } 458 459 460 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType, 461 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 462 DWORD *pcbEncoded) 463 { 464 const SPC_PE_IMAGE_DATA *imageData = pvStructInfo; 465 BOOL ret = FALSE; 466 467 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 468 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, 469 pcbEncoded); 470 471 __TRY 472 { 473 struct AsnEncodeSequenceItem items[2] = { 474 { 0 } 475 }; 476 struct AsnConstructedItem constructed = { 0, imageData->pFile, 477 WVTAsn1SpcLinkEncode }; 478 DWORD cItem = 0; 479 480 if (imageData->Flags.cbData) 481 { 482 items[cItem].pvStructInfo = &imageData->Flags; 483 items[cItem].encodeFunc = CRYPT_AsnEncodeBits; 484 cItem++; 485 } 486 if (imageData->pFile) 487 { 488 items[cItem].pvStructInfo = &constructed; 489 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 490 cItem++; 491 } 492 493 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, 494 pbEncoded, pcbEncoded); 495 } 496 __EXCEPT_PAGE_FAULT 497 { 498 SetLastError(STATUS_ACCESS_VIOLATION); 499 } 500 __ENDTRY 501 TRACE("returning %d\n", ret); 502 return ret; 503 } 504 505 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, 506 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 507 DWORD *pcbEncoded) 508 { 509 LPCSTR pszObjId = pvStructInfo; 510 DWORD bytesNeeded = 0, lenBytes; 511 BOOL ret = TRUE; 512 int firstPos = 0; 513 BYTE firstByte = 0; 514 515 TRACE("%s\n", debugstr_a(pszObjId)); 516 517 if (pszObjId) 518 { 519 const char *ptr; 520 int val1, val2; 521 522 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2) 523 { 524 SetLastError(CRYPT_E_ASN1_ERROR); 525 return FALSE; 526 } 527 bytesNeeded++; 528 firstByte = val1 * 40 + val2; 529 ptr = pszObjId + firstPos; 530 if (*ptr == '.') 531 { 532 ptr++; 533 firstPos++; 534 } 535 while (ret && *ptr) 536 { 537 int pos; 538 539 /* note I assume each component is at most 32-bits long in base 2 */ 540 if (sscanf(ptr, "%d%n", &val1, &pos) == 1) 541 { 542 if (val1 >= 0x10000000) 543 bytesNeeded += 5; 544 else if (val1 >= 0x200000) 545 bytesNeeded += 4; 546 else if (val1 >= 0x4000) 547 bytesNeeded += 3; 548 else if (val1 >= 0x80) 549 bytesNeeded += 2; 550 else 551 bytesNeeded += 1; 552 ptr += pos; 553 if (*ptr == '.') 554 ptr++; 555 } 556 else 557 { 558 SetLastError(CRYPT_E_ASN1_ERROR); 559 return FALSE; 560 } 561 } 562 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); 563 } 564 else 565 lenBytes = 1; 566 bytesNeeded += 1 + lenBytes; 567 if (pbEncoded) 568 { 569 if (*pcbEncoded < bytesNeeded) 570 { 571 SetLastError(ERROR_MORE_DATA); 572 ret = FALSE; 573 } 574 else 575 { 576 *pbEncoded++ = ASN_OBJECTIDENTIFIER; 577 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes); 578 pbEncoded += lenBytes; 579 if (pszObjId) 580 { 581 const char *ptr; 582 int val, pos; 583 584 *pbEncoded++ = firstByte; 585 ptr = pszObjId + firstPos; 586 while (ret && *ptr) 587 { 588 sscanf(ptr, "%d%n", &val, &pos); 589 { 590 unsigned char outBytes[5]; 591 int numBytes, i; 592 593 if (val >= 0x10000000) 594 numBytes = 5; 595 else if (val >= 0x200000) 596 numBytes = 4; 597 else if (val >= 0x4000) 598 numBytes = 3; 599 else if (val >= 0x80) 600 numBytes = 2; 601 else 602 numBytes = 1; 603 for (i = numBytes; i > 0; i--) 604 { 605 outBytes[i - 1] = val & 0x7f; 606 val >>= 7; 607 } 608 for (i = 0; i < numBytes - 1; i++) 609 *pbEncoded++ = outBytes[i] | 0x80; 610 *pbEncoded++ = outBytes[i]; 611 ptr += pos; 612 if (*ptr == '.') 613 ptr++; 614 } 615 } 616 } 617 } 618 } 619 *pcbEncoded = bytesNeeded; 620 return ret; 621 } 622 623 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType, 624 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 625 DWORD *pcbEncoded) 626 { 627 const CRYPT_DER_BLOB *blob = pvStructInfo; 628 BOOL ret = TRUE; 629 630 if (!pbEncoded) 631 *pcbEncoded = blob->cbData; 632 else if (*pcbEncoded < blob->cbData) 633 { 634 *pcbEncoded = blob->cbData; 635 SetLastError(ERROR_MORE_DATA); 636 ret = FALSE; 637 } 638 else 639 { 640 if (blob->cbData) 641 memcpy(pbEncoded, blob->pbData, blob->cbData); 642 *pcbEncoded = blob->cbData; 643 } 644 return ret; 645 } 646 647 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams( 648 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, 649 BYTE *pbEncoded, DWORD *pcbEncoded) 650 { 651 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 652 static const BYTE asn1Null[] = { ASN_NULL, 0 }; 653 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null), 654 (LPBYTE)asn1Null }; 655 BOOL ret; 656 struct AsnEncodeSequenceItem items[2] = { 657 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, 658 { NULL, CRYPT_CopyEncodedBlob, 0 }, 659 }; 660 661 if (algo->Parameters.cbData) 662 items[1].pvStructInfo = &algo->Parameters; 663 else 664 items[1].pvStructInfo = &nullBlob; 665 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 666 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 667 return ret; 668 } 669 670 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType, 671 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 672 DWORD *pcbEncoded) 673 { 674 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo; 675 struct AsnEncodeSequenceItem items[] = { 676 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 }, 677 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 }, 678 }; 679 680 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 681 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 682 } 683 684 struct SPCDigest 685 { 686 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm; 687 CRYPT_HASH_BLOB Digest; 688 }; 689 690 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType, 691 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 692 DWORD *pcbEncoded) 693 { 694 const struct SPCDigest *digest = pvStructInfo; 695 struct AsnEncodeSequenceItem items[] = { 696 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, 697 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 }, 698 }; 699 700 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 701 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 702 } 703 704 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType, 705 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 706 DWORD *pcbEncoded) 707 { 708 BOOL ret = FALSE; 709 710 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 711 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded); 712 713 __TRY 714 { 715 const SPC_INDIRECT_DATA_CONTENT *data = pvStructInfo; 716 struct AsnEncodeSequenceItem items[] = { 717 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 }, 718 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 }, 719 }; 720 721 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 722 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 723 } 724 __EXCEPT_PAGE_FAULT 725 { 726 SetLastError(STATUS_ACCESS_VIOLATION); 727 } 728 __ENDTRY 729 return ret; 730 } 731 732 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType, 733 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 734 DWORD *pcbEncoded) 735 { 736 BOOL ret = TRUE; 737 LPCWSTR str = pvStructInfo; 738 DWORD bytesNeeded, lenBytes, strLen; 739 740 if (str) 741 strLen = lstrlenW(str); 742 else 743 strLen = 0; 744 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes); 745 bytesNeeded = 1 + lenBytes + strLen * 2; 746 if (!pbEncoded) 747 *pcbEncoded = bytesNeeded; 748 else if (*pcbEncoded < bytesNeeded) 749 { 750 *pcbEncoded = bytesNeeded; 751 SetLastError(ERROR_MORE_DATA); 752 ret = FALSE; 753 } 754 else 755 { 756 DWORD i; 757 758 *pcbEncoded = bytesNeeded; 759 *pbEncoded++ = ASN_BMPSTRING; 760 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes); 761 pbEncoded += lenBytes; 762 for (i = 0; i < strLen; i++) 763 { 764 *pbEncoded++ = (str[i] & 0xff00) >> 8; 765 *pbEncoded++ = str[i] & 0x00ff; 766 } 767 } 768 return ret; 769 } 770 771 struct AsnEncodeTagSwappedItem 772 { 773 BYTE tag; 774 const void *pvStructInfo; 775 CryptEncodeObjectFunc encodeFunc; 776 }; 777 778 /* Sort of a wacky hack, it encodes something using the struct 779 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag 780 * given in the struct AsnEncodeTagSwappedItem. 781 */ 782 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType, 783 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 784 DWORD *pcbEncoded) 785 { 786 BOOL ret; 787 const struct AsnEncodeTagSwappedItem *item = pvStructInfo; 788 789 ret = item->encodeFunc(dwCertEncodingType, lpszStructType, 790 item->pvStructInfo, pbEncoded, pcbEncoded); 791 if (ret && pbEncoded) 792 *pbEncoded = item->tag; 793 return ret; 794 } 795 796 BOOL WINAPI WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType, 797 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 798 DWORD *pcbEncoded) 799 { 800 BOOL ret = FALSE; 801 802 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 803 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded); 804 805 __TRY 806 { 807 const SPC_SP_OPUS_INFO *info = pvStructInfo; 808 809 if (info->pMoreInfo && 810 info->pMoreInfo->dwLinkChoice != SPC_URL_LINK_CHOICE && 811 info->pMoreInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE && 812 info->pMoreInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE) 813 SetLastError(E_INVALIDARG); 814 else if (info->pPublisherInfo && 815 info->pPublisherInfo->dwLinkChoice != SPC_URL_LINK_CHOICE && 816 info->pPublisherInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE && 817 info->pPublisherInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE) 818 SetLastError(E_INVALIDARG); 819 else 820 { 821 struct AsnEncodeSequenceItem items[3] = { { 0 } }; 822 struct AsnConstructedItem constructed[3] = { { 0 } }; 823 struct AsnEncodeTagSwappedItem swapped; 824 DWORD cItem = 0, cConstructed = 0; 825 826 if (info->pwszProgramName) 827 { 828 swapped.tag = ASN_CONTEXT; 829 swapped.pvStructInfo = info->pwszProgramName; 830 swapped.encodeFunc = CRYPT_AsnEncodeBMPString; 831 constructed[cConstructed].tag = 0; 832 constructed[cConstructed].pvStructInfo = &swapped; 833 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeSwapTag; 834 items[cItem].pvStructInfo = &constructed[cConstructed]; 835 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 836 cConstructed++; 837 cItem++; 838 } 839 if (info->pMoreInfo) 840 { 841 constructed[cConstructed].tag = 1; 842 constructed[cConstructed].pvStructInfo = info->pMoreInfo; 843 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode; 844 items[cItem].pvStructInfo = &constructed[cConstructed]; 845 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 846 cConstructed++; 847 cItem++; 848 } 849 if (info->pPublisherInfo) 850 { 851 constructed[cConstructed].tag = 2; 852 constructed[cConstructed].pvStructInfo = info->pPublisherInfo; 853 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode; 854 items[cItem].pvStructInfo = &constructed[cConstructed]; 855 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; 856 cConstructed++; 857 cItem++; 858 } 859 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 860 items, cItem, pbEncoded, pcbEncoded); 861 } 862 } 863 __EXCEPT_PAGE_FAULT 864 { 865 SetLastError(STATUS_ACCESS_VIOLATION); 866 } 867 __ENDTRY 868 return ret; 869 } 870 871 static BOOL CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, 872 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 873 DWORD *pcbEncoded) 874 { 875 BOOL ret; 876 877 __TRY 878 { 879 DWORD significantBytes, lenBytes, bytesNeeded; 880 BYTE padByte = 0; 881 BOOL pad = FALSE; 882 const CRYPT_INTEGER_BLOB *blob = pvStructInfo; 883 884 significantBytes = blob->cbData; 885 if (significantBytes) 886 { 887 if (blob->pbData[significantBytes - 1] & 0x80) 888 { 889 /* negative, lop off leading (little-endian) 0xffs */ 890 for (; significantBytes > 0 && 891 blob->pbData[significantBytes - 1] == 0xff; significantBytes--) 892 ; 893 if (blob->pbData[significantBytes - 1] < 0x80) 894 { 895 padByte = 0xff; 896 pad = TRUE; 897 } 898 } 899 else 900 { 901 /* positive, lop off leading (little-endian) zeroes */ 902 for (; significantBytes > 0 && 903 !blob->pbData[significantBytes - 1]; significantBytes--) 904 ; 905 if (significantBytes == 0) 906 significantBytes = 1; 907 if (blob->pbData[significantBytes - 1] > 0x7f) 908 { 909 padByte = 0; 910 pad = TRUE; 911 } 912 } 913 } 914 if (pad) 915 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); 916 else 917 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); 918 bytesNeeded = 1 + lenBytes + significantBytes; 919 if (pad) 920 bytesNeeded++; 921 if (!pbEncoded) 922 { 923 *pcbEncoded = bytesNeeded; 924 ret = TRUE; 925 } 926 else if (*pcbEncoded < bytesNeeded) 927 { 928 *pcbEncoded = bytesNeeded; 929 SetLastError(ERROR_MORE_DATA); 930 ret = FALSE; 931 } 932 else 933 { 934 *pcbEncoded = bytesNeeded; 935 *pbEncoded++ = ASN_INTEGER; 936 if (pad) 937 { 938 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); 939 pbEncoded += lenBytes; 940 *pbEncoded++ = padByte; 941 } 942 else 943 { 944 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); 945 pbEncoded += lenBytes; 946 } 947 for (; significantBytes > 0; significantBytes--) 948 *(pbEncoded++) = blob->pbData[significantBytes - 1]; 949 ret = TRUE; 950 } 951 } 952 __EXCEPT_PAGE_FAULT 953 { 954 SetLastError(STATUS_ACCESS_VIOLATION); 955 ret = FALSE; 956 } 957 __ENDTRY 958 return ret; 959 } 960 961 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, 962 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 963 DWORD *pcbEncoded) 964 { 965 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo }; 966 967 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER, 968 &blob, pbEncoded, pcbEncoded); 969 } 970 971 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType, 972 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 973 DWORD *pcbEncoded) 974 { 975 BOOL ret = FALSE; 976 977 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 978 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded); 979 980 __TRY 981 { 982 const CAT_MEMBERINFO *info = pvStructInfo; 983 struct AsnEncodeSequenceItem items[] = { 984 { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 }, 985 { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 }, 986 }; 987 988 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 989 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 990 } 991 __EXCEPT_PAGE_FAULT 992 { 993 SetLastError(STATUS_ACCESS_VIOLATION); 994 } 995 __ENDTRY 996 return ret; 997 } 998 999 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType, 1000 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 1001 DWORD *pcbEncoded) 1002 { 1003 BOOL ret = FALSE; 1004 1005 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 1006 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded); 1007 1008 __TRY 1009 { 1010 const CAT_NAMEVALUE *value = pvStructInfo; 1011 struct AsnEncodeSequenceItem items[] = { 1012 { value->pwszTag, CRYPT_AsnEncodeBMPString, 0 }, 1013 { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 }, 1014 { &value->Value, CRYPT_AsnEncodeOctets, 0 }, 1015 }; 1016 1017 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 1018 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 1019 } 1020 __EXCEPT_PAGE_FAULT 1021 { 1022 SetLastError(STATUS_ACCESS_VIOLATION); 1023 } 1024 __ENDTRY 1025 return ret; 1026 } 1027 1028 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, 1029 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 1030 DWORD *pcbEncoded) 1031 { 1032 BOOL val = *(const BOOL *)pvStructInfo, ret; 1033 1034 TRACE("%d\n", val); 1035 1036 if (!pbEncoded) 1037 { 1038 *pcbEncoded = 3; 1039 ret = TRUE; 1040 } 1041 else if (*pcbEncoded < 3) 1042 { 1043 *pcbEncoded = 3; 1044 SetLastError(ERROR_MORE_DATA); 1045 ret = FALSE; 1046 } 1047 else 1048 { 1049 *pcbEncoded = 3; 1050 *pbEncoded++ = ASN_BOOL; 1051 *pbEncoded++ = 1; 1052 *pbEncoded++ = val ? 0xff : 0; 1053 ret = TRUE; 1054 } 1055 TRACE("returning %d (%08x)\n", ret, GetLastError()); 1056 return ret; 1057 } 1058 1059 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType, 1060 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded, 1061 DWORD *pcbEncoded) 1062 { 1063 BOOL ret = FALSE; 1064 1065 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType, 1066 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded); 1067 1068 __TRY 1069 { 1070 const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo; 1071 struct AsnEncodeSequenceItem items[] = { 1072 { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 }, 1073 { &criteria->fMeetsCriteria, CRYPT_AsnEncodeBool, 0 }, 1074 }; 1075 1076 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, 1077 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded); 1078 } 1079 __EXCEPT_PAGE_FAULT 1080 { 1081 SetLastError(STATUS_ACCESS_VIOLATION); 1082 } 1083 __ENDTRY 1084 return ret; 1085 } 1086 1087 /* Gets the number of length bytes from the given (leading) length byte */ 1088 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f)) 1089 1090 /* Helper function to get the encoded length of the data starting at pbEncoded, 1091 * where pbEncoded[0] is the tag. If the data are too short to contain a 1092 * length or if the length is too large for cbEncoded, sets an appropriate 1093 * error code and returns FALSE. 1094 */ 1095 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len) 1096 { 1097 BOOL ret; 1098 1099 if (cbEncoded <= 1) 1100 { 1101 SetLastError(CRYPT_E_ASN1_CORRUPT); 1102 ret = FALSE; 1103 } 1104 else if (pbEncoded[1] <= 0x7f) 1105 { 1106 if (pbEncoded[1] + 1 > cbEncoded) 1107 { 1108 SetLastError(CRYPT_E_ASN1_EOD); 1109 ret = FALSE; 1110 } 1111 else 1112 { 1113 *len = pbEncoded[1]; 1114 ret = TRUE; 1115 } 1116 } 1117 else if (pbEncoded[1] == 0x80) 1118 { 1119 FIXME("unimplemented for indefinite-length encoding\n"); 1120 SetLastError(CRYPT_E_ASN1_CORRUPT); 1121 ret = FALSE; 1122 } 1123 else 1124 { 1125 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]); 1126 1127 if (lenLen > sizeof(DWORD) + 1) 1128 { 1129 SetLastError(CRYPT_E_ASN1_LARGE); 1130 ret = FALSE; 1131 } 1132 else if (lenLen + 2 > cbEncoded) 1133 { 1134 SetLastError(CRYPT_E_ASN1_CORRUPT); 1135 ret = FALSE; 1136 } 1137 else 1138 { 1139 DWORD out = 0; 1140 1141 pbEncoded += 2; 1142 while (--lenLen) 1143 { 1144 out <<= 8; 1145 out |= *pbEncoded++; 1146 } 1147 if (out + lenLen + 1 > cbEncoded) 1148 { 1149 SetLastError(CRYPT_E_ASN1_EOD); 1150 ret = FALSE; 1151 } 1152 else 1153 { 1154 *len = out; 1155 ret = TRUE; 1156 } 1157 } 1158 } 1159 return ret; 1160 } 1161 1162 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType, 1163 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1164 void *pvStructInfo, DWORD *pcbStructInfo) 1165 { 1166 BOOL ret; 1167 DWORD bytesNeeded, dataLen; 1168 1169 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1170 pvStructInfo, *pcbStructInfo); 1171 1172 if (!cbEncoded) 1173 { 1174 SetLastError(CRYPT_E_ASN1_CORRUPT); 1175 ret = FALSE; 1176 } 1177 else if (pbEncoded[0] != ASN_OCTETSTRING) 1178 { 1179 SetLastError(CRYPT_E_ASN1_BADTAG); 1180 ret = FALSE; 1181 } 1182 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 1183 { 1184 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) 1185 bytesNeeded = sizeof(CRYPT_DATA_BLOB); 1186 else 1187 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB); 1188 if (!pvStructInfo) 1189 *pcbStructInfo = bytesNeeded; 1190 else if (*pcbStructInfo < bytesNeeded) 1191 { 1192 SetLastError(ERROR_MORE_DATA); 1193 *pcbStructInfo = bytesNeeded; 1194 ret = FALSE; 1195 } 1196 else 1197 { 1198 CRYPT_DATA_BLOB *blob; 1199 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 1200 1201 blob = pvStructInfo; 1202 blob->cbData = dataLen; 1203 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) 1204 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes; 1205 else 1206 { 1207 assert(blob->pbData); 1208 if (blob->cbData) 1209 memcpy(blob->pbData, pbEncoded + 1 + lenBytes, 1210 blob->cbData); 1211 } 1212 } 1213 } 1214 return ret; 1215 } 1216 1217 static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType, 1218 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1219 void *pvStructInfo, DWORD *pcbStructInfo) 1220 { 1221 BOOL ret = FALSE; 1222 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen; 1223 1224 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1225 pvStructInfo, *pcbStructInfo); 1226 1227 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 1228 { 1229 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 1230 DWORD realDataLen; 1231 1232 switch (pbEncoded[0]) 1233 { 1234 case ASN_CONTEXT: 1235 bytesNeeded += (dataLen + 1) * sizeof(WCHAR); 1236 if (!pvStructInfo) 1237 *pcbStructInfo = bytesNeeded; 1238 else if (*pcbStructInfo < bytesNeeded) 1239 { 1240 *pcbStructInfo = bytesNeeded; 1241 SetLastError(ERROR_MORE_DATA); 1242 ret = FALSE; 1243 } 1244 else 1245 { 1246 PSPC_LINK link = pvStructInfo; 1247 DWORD i; 1248 1249 link->dwLinkChoice = SPC_URL_LINK_CHOICE; 1250 for (i = 0; i < dataLen; i++) 1251 link->u.pwszUrl[i] = 1252 *(pbEncoded + 1 + lenBytes + i); 1253 link->u.pwszUrl[i] = '\0'; 1254 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl)); 1255 } 1256 break; 1257 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1: 1258 { 1259 CRYPT_DATA_BLOB classId; 1260 DWORD size = sizeof(classId); 1261 1262 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL, 1263 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, 1264 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size))) 1265 { 1266 if (classId.cbData != sizeof(SPC_UUID)) 1267 { 1268 SetLastError(CRYPT_E_BAD_ENCODE); 1269 ret = FALSE; 1270 } 1271 else 1272 { 1273 CRYPT_DATA_BLOB data; 1274 1275 /* The tag length for the classId must be 1 since the 1276 * length is correct. 1277 */ 1278 size = sizeof(data); 1279 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL, 1280 pbEncoded + 3 + lenBytes + classId.cbData, 1281 cbEncoded - 3 - lenBytes - classId.cbData, 1282 CRYPT_DECODE_NOCOPY_FLAG, &data, &size))) 1283 { 1284 bytesNeeded += data.cbData; 1285 if (!pvStructInfo) 1286 *pcbStructInfo = bytesNeeded; 1287 else if (*pcbStructInfo < bytesNeeded) 1288 { 1289 *pcbStructInfo = bytesNeeded; 1290 SetLastError(ERROR_MORE_DATA); 1291 ret = FALSE; 1292 } 1293 else 1294 { 1295 PSPC_LINK link = pvStructInfo; 1296 1297 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE; 1298 /* pwszFile pointer was set by caller, copy it 1299 * before overwriting it 1300 */ 1301 link->u.Moniker.SerializedData.pbData = 1302 (BYTE *)link->u.pwszFile; 1303 memcpy(link->u.Moniker.ClassId, classId.pbData, 1304 classId.cbData); 1305 memcpy(link->u.Moniker.SerializedData.pbData, 1306 data.pbData, data.cbData); 1307 link->u.Moniker.SerializedData.cbData = data.cbData; 1308 } 1309 } 1310 } 1311 } 1312 break; 1313 } 1314 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2: 1315 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT) 1316 SetLastError(CRYPT_E_ASN1_BADTAG); 1317 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen, 1318 &realDataLen))) 1319 { 1320 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]); 1321 1322 bytesNeeded += realDataLen + sizeof(WCHAR); 1323 if (!pvStructInfo) 1324 *pcbStructInfo = bytesNeeded; 1325 else if (*pcbStructInfo < bytesNeeded) 1326 { 1327 *pcbStructInfo = bytesNeeded; 1328 SetLastError(ERROR_MORE_DATA); 1329 ret = FALSE; 1330 } 1331 else 1332 { 1333 PSPC_LINK link = pvStructInfo; 1334 DWORD i; 1335 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes; 1336 1337 link->dwLinkChoice = SPC_FILE_LINK_CHOICE; 1338 for (i = 0; i < dataLen / sizeof(WCHAR); i++) 1339 link->u.pwszFile[i] = 1340 hton16(*(const WORD *)(ptr + i * sizeof(WCHAR))); 1341 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0'; 1342 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile)); 1343 } 1344 } 1345 else 1346 { 1347 bytesNeeded += sizeof(WCHAR); 1348 if (!pvStructInfo) 1349 *pcbStructInfo = bytesNeeded; 1350 else if (*pcbStructInfo < bytesNeeded) 1351 { 1352 *pcbStructInfo = bytesNeeded; 1353 SetLastError(ERROR_MORE_DATA); 1354 ret = FALSE; 1355 } 1356 else 1357 { 1358 PSPC_LINK link = pvStructInfo; 1359 1360 link->dwLinkChoice = SPC_FILE_LINK_CHOICE; 1361 link->u.pwszFile[0] = '\0'; 1362 ret = TRUE; 1363 } 1364 } 1365 break; 1366 default: 1367 SetLastError(CRYPT_E_ASN1_BADTAG); 1368 } 1369 } 1370 TRACE("returning %d\n", ret); 1371 return ret; 1372 } 1373 1374 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType, 1375 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1376 void *pvStructInfo, DWORD *pcbStructInfo) 1377 { 1378 BOOL ret = FALSE; 1379 1380 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1381 pvStructInfo, *pcbStructInfo); 1382 1383 __TRY 1384 { 1385 DWORD bytesNeeded; 1386 1387 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, 1388 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded); 1389 if (ret) 1390 { 1391 if (!pvStructInfo) 1392 *pcbStructInfo = bytesNeeded; 1393 else if (*pcbStructInfo < bytesNeeded) 1394 { 1395 *pcbStructInfo = bytesNeeded; 1396 SetLastError(ERROR_MORE_DATA); 1397 ret = FALSE; 1398 } 1399 else 1400 { 1401 SPC_LINK *link = pvStructInfo; 1402 1403 link->u.pwszFile = 1404 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK)); 1405 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, 1406 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo, 1407 pcbStructInfo); 1408 } 1409 } 1410 } 1411 __EXCEPT_PAGE_FAULT 1412 { 1413 SetLastError(STATUS_ACCESS_VIOLATION); 1414 } 1415 __ENDTRY 1416 TRACE("returning %d\n", ret); 1417 return ret; 1418 } 1419 1420 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *, 1421 DWORD, DWORD, void *, DWORD *); 1422 1423 /* tag: 1424 * The expected tag of the item. If tag is 0, decodeFunc is called 1425 * regardless of the tag value seen. 1426 * offset: 1427 * A sequence is decoded into a struct. The offset member is the 1428 * offset of this item within that struct. 1429 * decodeFunc: 1430 * The decoder function to use. If this is NULL, then the member isn't 1431 * decoded, but minSize space is reserved for it. 1432 * minSize: 1433 * The minimum amount of space occupied after decoding. You must set this. 1434 * optional: 1435 * If true, and the tag doesn't match the expected tag for this item, 1436 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is 1437 * filled with 0 for this member. 1438 * hasPointer, pointerOffset: 1439 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to 1440 * the offset within the struct of the data pointer (or to the 1441 * first data pointer, if more than one exist). 1442 * size: 1443 * Used by CRYPT_AsnDecodeSequence, not for your use. 1444 */ 1445 struct AsnDecodeSequenceItem 1446 { 1447 BYTE tag; 1448 DWORD offset; 1449 CryptDecodeObjectFunc decodeFunc; 1450 DWORD minSize; 1451 BOOL optional; 1452 BOOL hasPointer; 1453 DWORD pointerOffset; 1454 DWORD size; 1455 }; 1456 1457 /* Align up to a DWORD_PTR boundary 1458 */ 1459 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1)) 1460 1461 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member)) 1462 #define MEMBERSIZE(s, member, nextmember) \ 1463 (offsetof(s, nextmember) - offsetof(s, member)) 1464 1465 1466 /* Decodes the items in a sequence, where the items are described in items, 1467 * the encoded data are in pbEncoded with length cbEncoded. Decodes into 1468 * pvStructInfo. nextData is a pointer to the memory location at which the 1469 * first decoded item with a dynamic pointer should point. 1470 * Upon decoding, *cbDecoded is the total number of bytes decoded. 1471 */ 1472 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType, 1473 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded, 1474 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData, 1475 DWORD *cbDecoded) 1476 { 1477 BOOL ret; 1478 DWORD i, decoded = 0; 1479 const BYTE *ptr = pbEncoded; 1480 1481 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded, 1482 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded); 1483 1484 for (i = 0, ret = TRUE; ret && i < cItem; i++) 1485 { 1486 if (cbEncoded - (ptr - pbEncoded) != 0) 1487 { 1488 DWORD nextItemLen; 1489 1490 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded), 1491 &nextItemLen))) 1492 { 1493 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]); 1494 1495 if (ptr[0] == items[i].tag || !items[i].tag) 1496 { 1497 if (nextData && pvStructInfo && items[i].hasPointer) 1498 { 1499 TRACE("Setting next pointer to %p\n", 1500 nextData); 1501 *(BYTE **)((BYTE *)pvStructInfo + 1502 items[i].pointerOffset) = nextData; 1503 } 1504 if (items[i].decodeFunc) 1505 { 1506 if (pvStructInfo) 1507 TRACE("decoding item %d\n", i); 1508 else 1509 TRACE("sizing item %d\n", i); 1510 ret = items[i].decodeFunc(dwCertEncodingType, 1511 NULL, ptr, 1 + nextItemLenBytes + nextItemLen, 1512 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, 1513 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset 1514 : NULL, &items[i].size); 1515 if (ret) 1516 { 1517 if (items[i].size < items[i].minSize) 1518 items[i].size = items[i].minSize; 1519 else if (items[i].size > items[i].minSize) 1520 { 1521 /* Account for alignment padding */ 1522 items[i].size = ALIGN_DWORD_PTR(items[i].size); 1523 } 1524 TRACE("item %d size: %d\n", i, items[i].size); 1525 if (nextData && items[i].hasPointer && 1526 items[i].size > items[i].minSize) 1527 nextData += items[i].size - items[i].minSize; 1528 ptr += 1 + nextItemLenBytes + nextItemLen; 1529 decoded += 1 + nextItemLenBytes + nextItemLen; 1530 TRACE("item %d: decoded %d bytes\n", i, 1531 1 + nextItemLenBytes + nextItemLen); 1532 } 1533 else if (items[i].optional && 1534 GetLastError() == CRYPT_E_ASN1_BADTAG) 1535 { 1536 TRACE("skipping optional item %d\n", i); 1537 items[i].size = items[i].minSize; 1538 SetLastError(NOERROR); 1539 ret = TRUE; 1540 } 1541 else 1542 TRACE("item %d failed: %08x\n", i, 1543 GetLastError()); 1544 } 1545 else 1546 { 1547 TRACE("item %d: decoded %d bytes\n", i, 1548 1 + nextItemLenBytes + nextItemLen); 1549 ptr += 1 + nextItemLenBytes + nextItemLen; 1550 decoded += 1 + nextItemLenBytes + nextItemLen; 1551 items[i].size = items[i].minSize; 1552 } 1553 } 1554 else if (items[i].optional) 1555 { 1556 TRACE("skipping optional item %d\n", i); 1557 items[i].size = items[i].minSize; 1558 } 1559 else 1560 { 1561 TRACE("item %d: tag %02x doesn't match expected %02x\n", 1562 i, ptr[0], items[i].tag); 1563 SetLastError(CRYPT_E_ASN1_BADTAG); 1564 ret = FALSE; 1565 } 1566 } 1567 } 1568 else if (items[i].optional) 1569 { 1570 TRACE("missing optional item %d, skipping\n", i); 1571 items[i].size = items[i].minSize; 1572 } 1573 else 1574 { 1575 TRACE("not enough bytes for item %d, failing\n", i); 1576 SetLastError(CRYPT_E_ASN1_CORRUPT); 1577 ret = FALSE; 1578 } 1579 } 1580 if (ret) 1581 *cbDecoded = decoded; 1582 TRACE("returning %d\n", ret); 1583 return ret; 1584 } 1585 1586 /* This decodes an arbitrary sequence into a contiguous block of memory 1587 * (basically, a struct.) Each element being decoded is described by a struct 1588 * AsnDecodeSequenceItem, see above. 1589 * startingPointer is an optional pointer to the first place where dynamic 1590 * data will be stored. If you know the starting offset, you may pass it 1591 * here. Otherwise, pass NULL, and one will be inferred from the items. 1592 */ 1593 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType, 1594 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded, 1595 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, 1596 void *startingPointer) 1597 { 1598 BOOL ret; 1599 1600 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded, 1601 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer); 1602 1603 if (pbEncoded[0] == ASN_SEQUENCE) 1604 { 1605 DWORD dataLen; 1606 1607 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 1608 { 1609 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded; 1610 const BYTE *ptr = pbEncoded + 1 + lenBytes; 1611 1612 cbEncoded -= 1 + lenBytes; 1613 if (cbEncoded < dataLen) 1614 { 1615 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen, 1616 cbEncoded); 1617 SetLastError(CRYPT_E_ASN1_CORRUPT); 1618 ret = FALSE; 1619 } 1620 else 1621 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr, 1622 cbEncoded, dwFlags, NULL, NULL, &cbDecoded); 1623 if (ret && cbDecoded != dataLen) 1624 { 1625 TRACE("expected %d decoded, got %d, failing\n", dataLen, 1626 cbDecoded); 1627 SetLastError(CRYPT_E_ASN1_CORRUPT); 1628 ret = FALSE; 1629 } 1630 if (ret) 1631 { 1632 DWORD i, bytesNeeded = 0, structSize = 0; 1633 1634 for (i = 0; i < cItem; i++) 1635 { 1636 bytesNeeded += items[i].size; 1637 structSize += items[i].minSize; 1638 } 1639 if (!pvStructInfo) 1640 *pcbStructInfo = bytesNeeded; 1641 else if (*pcbStructInfo < bytesNeeded) 1642 { 1643 SetLastError(ERROR_MORE_DATA); 1644 *pcbStructInfo = bytesNeeded; 1645 ret = FALSE; 1646 } 1647 else 1648 { 1649 BYTE *nextData; 1650 1651 *pcbStructInfo = bytesNeeded; 1652 if (startingPointer) 1653 nextData = startingPointer; 1654 else 1655 nextData = (BYTE *)pvStructInfo + structSize; 1656 memset(pvStructInfo, 0, structSize); 1657 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, 1658 ptr, cbEncoded, dwFlags, pvStructInfo, nextData, 1659 &cbDecoded); 1660 } 1661 } 1662 } 1663 } 1664 else 1665 { 1666 SetLastError(CRYPT_E_ASN1_BADTAG); 1667 ret = FALSE; 1668 } 1669 TRACE("returning %d (%08x)\n", ret, GetLastError()); 1670 return ret; 1671 } 1672 1673 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType, 1674 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1675 void *pvStructInfo, DWORD *pcbStructInfo) 1676 { 1677 BOOL ret; 1678 1679 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags, 1680 pvStructInfo, *pcbStructInfo); 1681 1682 if (pbEncoded[0] == ASN_BITSTRING) 1683 { 1684 DWORD bytesNeeded, dataLen; 1685 1686 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 1687 { 1688 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) 1689 bytesNeeded = sizeof(CRYPT_BIT_BLOB); 1690 else 1691 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB); 1692 if (!pvStructInfo) 1693 *pcbStructInfo = bytesNeeded; 1694 else if (*pcbStructInfo < bytesNeeded) 1695 { 1696 *pcbStructInfo = bytesNeeded; 1697 SetLastError(ERROR_MORE_DATA); 1698 ret = FALSE; 1699 } 1700 else 1701 { 1702 CRYPT_BIT_BLOB *blob; 1703 1704 blob = pvStructInfo; 1705 blob->cbData = dataLen - 1; 1706 blob->cUnusedBits = *(pbEncoded + 1 + 1707 GET_LEN_BYTES(pbEncoded[1])); 1708 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) 1709 { 1710 blob->pbData = (BYTE *)pbEncoded + 2 + 1711 GET_LEN_BYTES(pbEncoded[1]); 1712 } 1713 else 1714 { 1715 assert(blob->pbData); 1716 if (blob->cbData) 1717 { 1718 BYTE mask = 0xff << blob->cUnusedBits; 1719 1720 memcpy(blob->pbData, pbEncoded + 2 + 1721 GET_LEN_BYTES(pbEncoded[1]), blob->cbData); 1722 blob->pbData[blob->cbData - 1] &= mask; 1723 } 1724 } 1725 } 1726 } 1727 } 1728 else 1729 { 1730 SetLastError(CRYPT_E_ASN1_BADTAG); 1731 ret = FALSE; 1732 } 1733 TRACE("returning %d (%08x)\n", ret, GetLastError()); 1734 return ret; 1735 } 1736 1737 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType, 1738 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1739 void *pvStructInfo, DWORD *pcbStructInfo) 1740 { 1741 BOOL ret = FALSE; 1742 DWORD dataLen; 1743 1744 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 1745 { 1746 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 1747 DWORD size; 1748 SPC_LINK **pLink = pvStructInfo; 1749 1750 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType, 1751 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size); 1752 if (ret) 1753 { 1754 if (!pvStructInfo) 1755 *pcbStructInfo = size + sizeof(PSPC_LINK); 1756 else if (*pcbStructInfo < size + sizeof(PSPC_LINK)) 1757 { 1758 *pcbStructInfo = size + sizeof(PSPC_LINK); 1759 SetLastError(ERROR_MORE_DATA); 1760 ret = FALSE; 1761 } 1762 else 1763 { 1764 *pcbStructInfo = size + sizeof(PSPC_LINK); 1765 /* Set imageData's pointer if necessary */ 1766 if (size > sizeof(SPC_LINK)) 1767 { 1768 (*pLink)->u.pwszUrl = 1769 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK)); 1770 } 1771 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, 1772 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags, 1773 *pLink, pcbStructInfo); 1774 } 1775 } 1776 } 1777 return ret; 1778 } 1779 1780 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType, 1781 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1782 void *pvStructInfo, DWORD *pcbStructInfo) 1783 { 1784 BOOL ret = FALSE; 1785 1786 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1787 pvStructInfo, *pcbStructInfo); 1788 1789 __TRY 1790 { 1791 struct AsnDecodeSequenceItem items[] = { 1792 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags), 1793 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, 1794 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 }, 1795 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile), 1796 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE, 1797 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 }, 1798 }; 1799 1800 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 1801 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 1802 pvStructInfo, pcbStructInfo, NULL); 1803 } 1804 __EXCEPT_PAGE_FAULT 1805 { 1806 SetLastError(STATUS_ACCESS_VIOLATION); 1807 } 1808 __ENDTRY 1809 TRACE("returning %d\n", ret); 1810 return ret; 1811 } 1812 1813 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType, 1814 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1815 void *pvStructInfo, DWORD *pcbStructInfo) 1816 { 1817 BOOL ret = TRUE; 1818 DWORD dataLen; 1819 1820 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1821 pvStructInfo, *pcbStructInfo); 1822 1823 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 1824 { 1825 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 1826 DWORD bytesNeeded = sizeof(LPSTR); 1827 1828 if (dataLen) 1829 { 1830 /* The largest possible string for the first two components 1831 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough. 1832 */ 1833 char firstTwo[8]; 1834 const BYTE *ptr; 1835 1836 sprintf(firstTwo, "%d.%d", 1837 pbEncoded[1 + lenBytes] / 40, 1838 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40) 1839 * 40); 1840 bytesNeeded += strlen(firstTwo) + 1; 1841 for (ptr = pbEncoded + 2 + lenBytes; ret && 1842 ptr - pbEncoded - 1 - lenBytes < dataLen; ) 1843 { 1844 /* large enough for ".4000000" */ 1845 char str[9]; 1846 int val = 0; 1847 1848 while (ptr - pbEncoded - 1 - lenBytes < dataLen && 1849 (*ptr & 0x80)) 1850 { 1851 val <<= 7; 1852 val |= *ptr & 0x7f; 1853 ptr++; 1854 } 1855 if (ptr - pbEncoded - 1 - lenBytes >= dataLen || 1856 (*ptr & 0x80)) 1857 { 1858 SetLastError(CRYPT_E_ASN1_CORRUPT); 1859 ret = FALSE; 1860 } 1861 else 1862 { 1863 val <<= 7; 1864 val |= *ptr++; 1865 snprintf(str, sizeof(str), ".%d", val); 1866 bytesNeeded += strlen(str); 1867 } 1868 } 1869 } 1870 if (!pvStructInfo) 1871 *pcbStructInfo = bytesNeeded; 1872 else if (*pcbStructInfo < bytesNeeded) 1873 { 1874 *pcbStructInfo = bytesNeeded; 1875 SetLastError(ERROR_MORE_DATA); 1876 ret = FALSE; 1877 } 1878 else 1879 { 1880 if (dataLen) 1881 { 1882 const BYTE *ptr; 1883 LPSTR pszObjId = *(LPSTR *)pvStructInfo; 1884 1885 *pszObjId = 0; 1886 pszObjId += sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40, 1887 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 1888 40) * 40); 1889 for (ptr = pbEncoded + 2 + lenBytes; ret && 1890 ptr - pbEncoded - 1 - lenBytes < dataLen; ) 1891 { 1892 int val = 0; 1893 1894 while (ptr - pbEncoded - 1 - lenBytes < dataLen && 1895 (*ptr & 0x80)) 1896 { 1897 val <<= 7; 1898 val |= *ptr & 0x7f; 1899 ptr++; 1900 } 1901 val <<= 7; 1902 val |= *ptr++; 1903 pszObjId += sprintf(pszObjId, ".%d", val); 1904 } 1905 } 1906 else 1907 *(LPSTR *)pvStructInfo = NULL; 1908 *pcbStructInfo = bytesNeeded; 1909 } 1910 } 1911 return ret; 1912 } 1913 1914 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType, 1915 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1916 void *pvStructInfo, DWORD *pcbStructInfo) 1917 { 1918 BOOL ret = FALSE; 1919 1920 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1921 pvStructInfo, *pcbStructInfo); 1922 1923 if (!cbEncoded) 1924 SetLastError(CRYPT_E_ASN1_CORRUPT); 1925 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER) 1926 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType, 1927 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo); 1928 else 1929 SetLastError(CRYPT_E_ASN1_BADTAG); 1930 return ret; 1931 } 1932 1933 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType, 1934 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1935 void *pvStructInfo, DWORD *pcbStructInfo) 1936 { 1937 BOOL ret = TRUE; 1938 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB); 1939 1940 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1941 pvStructInfo, *pcbStructInfo); 1942 1943 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) 1944 bytesNeeded += cbEncoded; 1945 if (!pvStructInfo) 1946 *pcbStructInfo = bytesNeeded; 1947 else if (*pcbStructInfo < bytesNeeded) 1948 { 1949 SetLastError(ERROR_MORE_DATA); 1950 *pcbStructInfo = bytesNeeded; 1951 ret = FALSE; 1952 } 1953 else 1954 { 1955 PCRYPT_OBJID_BLOB blob = pvStructInfo; 1956 1957 *pcbStructInfo = bytesNeeded; 1958 blob->cbData = cbEncoded; 1959 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) 1960 blob->pbData = (LPBYTE)pbEncoded; 1961 else 1962 { 1963 assert(blob->pbData); 1964 memcpy(blob->pbData, pbEncoded, blob->cbData); 1965 } 1966 } 1967 return ret; 1968 } 1969 1970 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType, 1971 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1972 void *pvStructInfo, DWORD *pcbStructInfo) 1973 { 1974 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo; 1975 struct AsnDecodeSequenceItem items[] = { 1976 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 1977 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE, 1978 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 }, 1979 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value), 1980 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE, 1981 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 }, 1982 }; 1983 1984 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 1985 pvStructInfo, *pcbStructInfo); 1986 1987 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 1988 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 1989 pvStructInfo, pcbStructInfo, 1990 typeValue ? typeValue->pszObjId : NULL); 1991 } 1992 1993 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType, 1994 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 1995 void *pvStructInfo, DWORD *pcbStructInfo) 1996 { 1997 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo; 1998 BOOL ret = TRUE; 1999 struct AsnDecodeSequenceItem items[] = { 2000 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 2001 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, 2002 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 }, 2003 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters), 2004 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 2005 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 }, 2006 }; 2007 2008 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 2009 pvStructInfo, *pcbStructInfo); 2010 2011 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2012 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2013 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL); 2014 if (ret && pvStructInfo) 2015 { 2016 TRACE("pszObjId is %p (%s)\n", algo->pszObjId, 2017 debugstr_a(algo->pszObjId)); 2018 } 2019 return ret; 2020 } 2021 2022 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType, 2023 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2024 void *pvStructInfo, DWORD *pcbStructInfo) 2025 { 2026 struct SPCDigest *digest = pvStructInfo; 2027 struct AsnDecodeSequenceItem items[] = { 2028 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm), 2029 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), 2030 FALSE, TRUE, 2031 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 }, 2032 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest), 2033 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), 2034 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 }, 2035 }; 2036 2037 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 2038 pvStructInfo, *pcbStructInfo); 2039 2040 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2041 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2042 pvStructInfo, pcbStructInfo, 2043 digest ? digest->DigestAlgorithm.pszObjId : NULL); 2044 } 2045 2046 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType, 2047 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2048 void *pvStructInfo, DWORD *pcbStructInfo) 2049 { 2050 BOOL ret = FALSE; 2051 2052 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 2053 pvStructInfo, *pcbStructInfo); 2054 2055 __TRY 2056 { 2057 struct AsnDecodeSequenceItem items[] = { 2058 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data), 2059 CRYPT_AsnDecodeAttributeTypeValue, 2060 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE, 2061 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 }, 2062 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm), 2063 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest), 2064 FALSE, TRUE, 2065 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 }, 2066 }; 2067 2068 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2069 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2070 pvStructInfo, pcbStructInfo, NULL); 2071 } 2072 __EXCEPT_PAGE_FAULT 2073 { 2074 SetLastError(STATUS_ACCESS_VIOLATION); 2075 } 2076 __ENDTRY 2077 TRACE("returning %d\n", ret); 2078 return ret; 2079 } 2080 2081 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType, 2082 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2083 void *pvStructInfo, DWORD *pcbStructInfo) 2084 { 2085 BOOL ret; 2086 DWORD bytesNeeded, dataLen; 2087 2088 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 2089 { 2090 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 2091 2092 bytesNeeded = dataLen + 2 + sizeof(LPWSTR); 2093 if (!pvStructInfo) 2094 *pcbStructInfo = bytesNeeded; 2095 else if (*pcbStructInfo < bytesNeeded) 2096 { 2097 *pcbStructInfo = bytesNeeded; 2098 SetLastError(ERROR_MORE_DATA); 2099 ret = FALSE; 2100 } 2101 else 2102 { 2103 LPWSTR str; 2104 DWORD i; 2105 2106 *pcbStructInfo = bytesNeeded; 2107 assert(pvStructInfo); 2108 str = *(LPWSTR *)pvStructInfo; 2109 for (i = 0; i < dataLen / 2; i++) 2110 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) | 2111 pbEncoded[1 + lenBytes + 2 * i + 1]; 2112 /* Decoded string is always NULL-terminated */ 2113 str[i] = '\0'; 2114 } 2115 } 2116 return ret; 2117 } 2118 2119 static BOOL WINAPI CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType, 2120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2121 void *pvStructInfo, DWORD *pcbStructInfo) 2122 { 2123 BOOL ret = FALSE; 2124 DWORD dataLen; 2125 2126 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags, 2127 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0); 2128 2129 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 2130 { 2131 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 2132 2133 ret = CRYPT_AsnDecodeBMPString(dwCertEncodingType, lpszStructType, 2134 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo, 2135 pcbStructInfo); 2136 } 2137 return ret; 2138 } 2139 2140 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType, 2141 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2142 void *pvStructInfo, DWORD *pcbStructInfo) 2143 { 2144 BOOL ret = FALSE; 2145 2146 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 2147 pvStructInfo, *pcbStructInfo); 2148 2149 __TRY 2150 { 2151 struct AsnDecodeSequenceItem items[] = { 2152 { ASN_CONSTRUCTOR | ASN_CONTEXT, 2153 offsetof(SPC_SP_OPUS_INFO, pwszProgramName), 2154 CRYPT_AsnDecodeProgramName, sizeof(LPCWSTR), TRUE, TRUE, 2155 offsetof(SPC_SP_OPUS_INFO, pwszProgramName), 0 }, 2156 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, 2157 offsetof(SPC_SP_OPUS_INFO, pMoreInfo), 2158 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE, 2159 offsetof(SPC_SP_OPUS_INFO, pMoreInfo), 0 }, 2160 { ASN_CONSTRUCTOR | ASN_CONTEXT | 2, 2161 offsetof(SPC_SP_OPUS_INFO, pPublisherInfo), 2162 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE, 2163 offsetof(SPC_SP_OPUS_INFO, pPublisherInfo), 0 }, 2164 }; 2165 2166 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2167 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2168 pvStructInfo, pcbStructInfo, NULL); 2169 } 2170 __EXCEPT_PAGE_FAULT 2171 { 2172 SetLastError(STATUS_ACCESS_VIOLATION); 2173 } 2174 __ENDTRY 2175 TRACE("returning %d\n", ret); 2176 return ret; 2177 } 2178 2179 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */ 2180 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, 2181 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2182 void *pvStructInfo, DWORD *pcbStructInfo) 2183 { 2184 BOOL ret; 2185 DWORD dataLen; 2186 2187 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) 2188 { 2189 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); 2190 2191 if (dataLen > sizeof(int)) 2192 { 2193 SetLastError(CRYPT_E_ASN1_LARGE); 2194 ret = FALSE; 2195 } 2196 else if (!pvStructInfo) 2197 *pcbStructInfo = sizeof(int); 2198 else if (*pcbStructInfo < sizeof(int)) 2199 { 2200 *pcbStructInfo = sizeof(int); 2201 SetLastError(ERROR_MORE_DATA); 2202 ret = FALSE; 2203 } 2204 else 2205 { 2206 int val; 2207 DWORD i; 2208 2209 *pcbStructInfo = sizeof(int); 2210 if (dataLen && pbEncoded[1 + lenBytes] & 0x80) 2211 { 2212 /* initialize to a negative value to sign-extend */ 2213 val = -1; 2214 } 2215 else 2216 val = 0; 2217 for (i = 0; i < dataLen; i++) 2218 { 2219 val <<= 8; 2220 val |= pbEncoded[1 + lenBytes + i]; 2221 } 2222 memcpy(pvStructInfo, &val, sizeof(int)); 2223 } 2224 } 2225 return ret; 2226 } 2227 2228 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType, 2229 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2230 void *pvStructInfo, DWORD *pcbStructInfo) 2231 { 2232 BOOL ret = FALSE; 2233 2234 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 2235 pvStructInfo, *pcbStructInfo); 2236 2237 __TRY 2238 { 2239 struct AsnDecodeSequenceItem items[] = { 2240 { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid), 2241 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE, 2242 offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 }, 2243 { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion), 2244 CRYPT_AsnDecodeInt, FINALMEMBERSIZE(CAT_MEMBERINFO, dwCertVersion), 2245 FALSE, FALSE, 0, 0 }, 2246 }; 2247 2248 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2249 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2250 pvStructInfo, pcbStructInfo, NULL); 2251 } 2252 __EXCEPT_PAGE_FAULT 2253 { 2254 SetLastError(STATUS_ACCESS_VIOLATION); 2255 } 2256 __ENDTRY 2257 TRACE("returning %d\n", ret); 2258 return ret; 2259 } 2260 2261 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType, 2262 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2263 void *pvStructInfo, DWORD *pcbStructInfo) 2264 { 2265 BOOL ret = FALSE; 2266 2267 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, 2268 pvStructInfo, *pcbStructInfo); 2269 2270 __TRY 2271 { 2272 struct AsnDecodeSequenceItem items[] = { 2273 { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag), 2274 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE, 2275 offsetof(CAT_NAMEVALUE, pwszTag), 0 }, 2276 { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags), 2277 CRYPT_AsnDecodeInt, MEMBERSIZE(CAT_NAMEVALUE, fdwFlags, Value), 2278 FALSE, FALSE, 0, 0 }, 2279 { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value), 2280 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, 2281 offsetof(CAT_NAMEVALUE, Value.pbData), 0 }, 2282 }; 2283 2284 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2285 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2286 pvStructInfo, pcbStructInfo, NULL); 2287 } 2288 __EXCEPT_PAGE_FAULT 2289 { 2290 SetLastError(STATUS_ACCESS_VIOLATION); 2291 } 2292 __ENDTRY 2293 TRACE("returning %d\n", ret); 2294 return ret; 2295 } 2296 2297 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType, 2298 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2299 void *pvStructInfo, DWORD *pcbStructInfo) 2300 { 2301 BOOL ret; 2302 2303 if (cbEncoded < 3) 2304 { 2305 SetLastError(CRYPT_E_ASN1_CORRUPT); 2306 return FALSE; 2307 } 2308 if (GET_LEN_BYTES(pbEncoded[1]) > 1) 2309 { 2310 SetLastError(CRYPT_E_ASN1_CORRUPT); 2311 return FALSE; 2312 } 2313 if (pbEncoded[1] > 1) 2314 { 2315 SetLastError(CRYPT_E_ASN1_CORRUPT); 2316 return FALSE; 2317 } 2318 if (!pvStructInfo) 2319 { 2320 *pcbStructInfo = sizeof(BOOL); 2321 ret = TRUE; 2322 } 2323 else if (*pcbStructInfo < sizeof(BOOL)) 2324 { 2325 *pcbStructInfo = sizeof(BOOL); 2326 SetLastError(ERROR_MORE_DATA); 2327 ret = FALSE; 2328 } 2329 else 2330 { 2331 *pcbStructInfo = sizeof(BOOL); 2332 *(BOOL *)pvStructInfo = pbEncoded[2] != 0; 2333 ret = TRUE; 2334 } 2335 TRACE("returning %d (%08x)\n", ret, GetLastError()); 2336 return ret; 2337 } 2338 2339 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType, 2340 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, 2341 void *pvStructInfo, DWORD *pcbStructInfo) 2342 { 2343 BOOL ret = FALSE; 2344 2345 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags, 2346 pvStructInfo, *pcbStructInfo); 2347 2348 __TRY 2349 { 2350 struct AsnDecodeSequenceItem items[] = { 2351 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable), 2352 CRYPT_AsnDecodeBool, MEMBERSIZE(SPC_FINANCIAL_CRITERIA, 2353 fFinancialInfoAvailable, fMeetsCriteria), FALSE, FALSE, 0, 0 }, 2354 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria), 2355 CRYPT_AsnDecodeBool, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA, 2356 fMeetsCriteria), FALSE, FALSE, 0, 0 }, 2357 }; 2358 2359 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, 2360 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, 2361 pvStructInfo, pcbStructInfo, NULL); 2362 } 2363 __EXCEPT_PAGE_FAULT 2364 { 2365 SetLastError(STATUS_ACCESS_VIOLATION); 2366 } 2367 __ENDTRY 2368 TRACE("returning %d\n", ret); 2369 return ret; 2370 } 2371