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