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