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