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