[WINTRUST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / wintrust / asn.c
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 }