crypt32: Simplify CRYPT_AsnDecodeDistPointName.
[wine] / dlls / crypt32 / decode.c
1 /*
2  * Copyright 2005-2008 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * This file implements ASN.1 DER decoding of a limited set of types.
19  * It isn't a full ASN.1 implementation.  Microsoft implements BER
20  * encoding of many of the basic types in msasn1.dll, but that interface isn't
21  * implemented, so I implement them here.
22  *
23  * References:
24  * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25  * (available online, look for a PDF copy as the HTML versions tend to have
26  * translation errors.)
27  *
28  * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
29  *
30  * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
31  */
32
33 #include "config.h"
34 #include "wine/port.h"
35
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #define NONAMELESSUNION
42
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
51
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
54
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK  0x1f
57
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
60
61 struct GenericArray
62 {
63     DWORD cItems;
64     BYTE *rgItems;
65 };
66
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68  DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70  DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
71
72 /* Internal decoders don't do memory allocation or exception handling, and
73  * they report how many bytes they decoded.
74  */
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
77
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80  DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83  DWORD *pcbDecoded);
84 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
85  */
86 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
87  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
88 /* Assumes algo->Parameters.pbData is set ahead of time. */
89 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
90  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
91 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
92  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
94 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
95  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
96  DWORD *pcbDecoded);
97 /* Doesn't check the tag, assumes the caller does so */
98 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
99  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
100 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
101  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
102 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
103  * member has been initialized, doesn't do exception handling, and doesn't do
104  * memory allocation.  Also doesn't check tag, assumes the caller has checked
105  * it.
106  */
107 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
108  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
109  DWORD *pcbDecoded);
110 /* Like CRYPT_AsnDecodeInteger, but unsigned.  */
111 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
112  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
113  DWORD *pcbDecoded);
114 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
115  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
116  DWORD *pcbDecoded);
117
118 /* Gets the number of length bytes from the given (leading) length byte */
119 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
120
121 /* Helper function to get the encoded length of the data starting at pbEncoded,
122  * where pbEncoded[0] is the tag.  If the data are too short to contain a
123  * length or if the length is too large for cbEncoded, sets an appropriate
124  * error code and returns FALSE.  If the encoded length is unknown due to
125  * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
126  */
127 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
128  DWORD *len)
129 {
130     BOOL ret;
131
132     if (cbEncoded <= 1)
133     {
134         SetLastError(CRYPT_E_ASN1_CORRUPT);
135         ret = FALSE;
136     }
137     else if (pbEncoded[1] <= 0x7f)
138     {
139         if (pbEncoded[1] + 1 > cbEncoded)
140         {
141             SetLastError(CRYPT_E_ASN1_EOD);
142             ret = FALSE;
143         }
144         else
145         {
146             *len = pbEncoded[1];
147             ret = TRUE;
148         }
149     }
150     else if (pbEncoded[1] == 0x80)
151     {
152         *len = CMSG_INDEFINITE_LENGTH;
153         ret = TRUE;
154     }
155     else
156     {
157         BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
158
159         if (lenLen > sizeof(DWORD) + 1)
160         {
161             SetLastError(CRYPT_E_ASN1_LARGE);
162             ret = FALSE;
163         }
164         else if (lenLen + 2 > cbEncoded)
165         {
166             SetLastError(CRYPT_E_ASN1_CORRUPT);
167             ret = FALSE;
168         }
169         else
170         {
171             DWORD out = 0;
172
173             pbEncoded += 2;
174             while (--lenLen)
175             {
176                 out <<= 8;
177                 out |= *pbEncoded++;
178             }
179             if (out + lenLen + 1 > cbEncoded)
180             {
181                 SetLastError(CRYPT_E_ASN1_EOD);
182                 ret = FALSE;
183             }
184             else
185             {
186                 *len = out;
187                 ret = TRUE;
188             }
189         }
190     }
191     return ret;
192 }
193
194 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
195 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
196 {
197     BOOL ret;
198
199     if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
200      *len == CMSG_INDEFINITE_LENGTH)
201     {
202         SetLastError(CRYPT_E_ASN1_CORRUPT);
203         ret = FALSE;
204     }
205     return ret;
206 }
207
208 /* Helper function to check *pcbStructInfo, set it to the required size, and
209  * optionally to allocate memory.  Assumes pvStructInfo is not NULL.
210  * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
211  * pointer to the newly allocated memory.
212  */
213 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
214  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
215  DWORD bytesNeeded)
216 {
217     BOOL ret = TRUE;
218
219     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
220     {
221         if (pDecodePara && pDecodePara->pfnAlloc)
222             *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
223         else
224             *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
225         if (!*(BYTE **)pvStructInfo)
226             ret = FALSE;
227         else
228             *pcbStructInfo = bytesNeeded;
229     }
230     else if (*pcbStructInfo < bytesNeeded)
231     {
232         *pcbStructInfo = bytesNeeded;
233         SetLastError(ERROR_MORE_DATA);
234         ret = FALSE;
235     }
236     else
237         *pcbStructInfo = bytesNeeded;
238     return ret;
239 }
240
241 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
242 {
243     if (pDecodePara && pDecodePara->pfnFree)
244         pDecodePara->pfnFree(pv);
245     else
246         LocalFree(pv);
247 }
248
249 /* Helper function to check *pcbStructInfo and set it to the required size.
250  * Assumes pvStructInfo is not NULL.
251  */
252 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
253 {
254     BOOL ret;
255
256     if (*pcbStructInfo < bytesNeeded)
257     {
258         *pcbStructInfo = bytesNeeded;
259         SetLastError(ERROR_MORE_DATA);
260         ret = FALSE;
261     }
262     else
263     {
264         *pcbStructInfo = bytesNeeded;
265         ret = TRUE;
266     }
267     return ret;
268 }
269
270 /* tag:
271  *     The expected tag of the item.  If tag is 0, decodeFunc is called
272  *     regardless of the tag value seen.
273  * offset:
274  *     A sequence is decoded into a struct.  The offset member is the
275  *     offset of this item within that struct.
276  * decodeFunc:
277  *     The decoder function to use.  If this is NULL, then the member isn't
278  *     decoded, but minSize space is reserved for it.
279  * minSize:
280  *     The minimum amount of space occupied after decoding.  You must set this.
281  * optional:
282  *     If true, and the tag doesn't match the expected tag for this item,
283  *     or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
284  *     filled with 0 for this member.
285  * hasPointer, pointerOffset:
286  *     If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
287  *     the offset within the struct of the data pointer (or to the
288  *     first data pointer, if more than one exist).
289  * size:
290  *     Used by CRYPT_AsnDecodeSequence, not for your use.
291  */
292 struct AsnDecodeSequenceItem
293 {
294     BYTE               tag;
295     DWORD              offset;
296     InternalDecodeFunc decodeFunc;
297     DWORD              minSize;
298     BOOL               optional;
299     BOOL               hasPointer;
300     DWORD              pointerOffset;
301     DWORD              size;
302 };
303
304 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
305 #define MEMBERSIZE(s, member, nextmember) \
306     (offsetof(s, nextmember) - offsetof(s, member))
307
308 /* Decodes the items in a sequence, where the items are described in items,
309  * the encoded data are in pbEncoded with length cbEncoded.  Decodes into
310  * pvStructInfo.  nextData is a pointer to the memory location at which the
311  * first decoded item with a dynamic pointer should point.
312  * Upon decoding, *cbDecoded is the total number of bytes decoded.
313  * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
314  */
315 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
316  DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
317  void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
318 {
319     BOOL ret;
320     DWORD i, decoded = 0;
321     const BYTE *ptr = pbEncoded;
322
323     TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
324      cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
325
326     for (i = 0, ret = TRUE; ret && i < cItem; i++)
327     {
328         if (cbEncoded - (ptr - pbEncoded) != 0)
329         {
330             DWORD itemLen;
331
332             if ((ret = CRYPT_GetLengthIndefinite(ptr,
333              cbEncoded - (ptr - pbEncoded), &itemLen)))
334             {
335                 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
336
337                 if (ptr[0] == items[i].tag || !items[i].tag)
338                 {
339                     DWORD itemEncodedLen;
340
341                     if (itemLen == CMSG_INDEFINITE_LENGTH)
342                         itemEncodedLen = cbEncoded - (ptr - pbEncoded);
343                     else
344                         itemEncodedLen = 1 + itemLenBytes + itemLen;
345                     if (nextData && pvStructInfo && items[i].hasPointer)
346                     {
347                         TRACE("Setting next pointer to %p\n",
348                          nextData);
349                         *(BYTE **)((BYTE *)pvStructInfo +
350                          items[i].pointerOffset) = nextData;
351                     }
352                     if (items[i].decodeFunc)
353                     {
354                         DWORD itemDecoded;
355
356                         if (pvStructInfo)
357                             TRACE("decoding item %d\n", i);
358                         else
359                             TRACE("sizing item %d\n", i);
360                         ret = items[i].decodeFunc(ptr, itemEncodedLen,
361                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
362                          pvStructInfo ?  (BYTE *)pvStructInfo + items[i].offset
363                          : NULL, &items[i].size, &itemDecoded);
364                         if (ret)
365                         {
366                             /* Account for alignment padding */
367                             items[i].size = ALIGN_DWORD_PTR(items[i].size);
368                             TRACE("item %d size: %d\n", i, items[i].size);
369                             if (nextData && items[i].hasPointer &&
370                              items[i].size > items[i].minSize)
371                                 nextData += items[i].size - items[i].minSize;
372                             if (itemDecoded > itemEncodedLen)
373                             {
374                                 WARN("decoded length %d exceeds encoded %d\n",
375                                  itemDecoded, itemEncodedLen);
376                                 SetLastError(CRYPT_E_ASN1_CORRUPT);
377                                 ret = FALSE;
378                             }
379                             else
380                             {
381                                 ptr += itemDecoded;
382                                 decoded += itemDecoded;
383                                 TRACE("item %d: decoded %d bytes\n", i,
384                                  itemDecoded);
385                             }
386                         }
387                         else if (items[i].optional &&
388                          GetLastError() == CRYPT_E_ASN1_BADTAG)
389                         {
390                             TRACE("skipping optional item %d\n", i);
391                             items[i].size = items[i].minSize;
392                             SetLastError(NOERROR);
393                             ret = TRUE;
394                         }
395                         else
396                             TRACE("item %d failed: %08x\n", i,
397                              GetLastError());
398                     }
399                     else if (itemLen == CMSG_INDEFINITE_LENGTH)
400                     {
401                         ERR("can't use indefinite length encoding without a decoder\n");
402                         SetLastError(CRYPT_E_ASN1_CORRUPT);
403                         ret = FALSE;
404                     }
405                     else
406                     {
407                         TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
408                         ptr += itemEncodedLen;
409                         decoded += itemEncodedLen;
410                         items[i].size = items[i].minSize;
411                     }
412                 }
413                 else if (items[i].optional)
414                 {
415                     TRACE("skipping optional item %d\n", i);
416                     items[i].size = items[i].minSize;
417                 }
418                 else
419                 {
420                     TRACE("item %d: tag %02x doesn't match expected %02x\n",
421                      i, ptr[0], items[i].tag);
422                     SetLastError(CRYPT_E_ASN1_BADTAG);
423                     ret = FALSE;
424                 }
425             }
426         }
427         else if (items[i].optional)
428         {
429             TRACE("missing optional item %d, skipping\n", i);
430             items[i].size = items[i].minSize;
431         }
432         else
433         {
434             TRACE("not enough bytes for item %d, failing\n", i);
435             SetLastError(CRYPT_E_ASN1_CORRUPT);
436             ret = FALSE;
437         }
438     }
439     if (cbDecoded)
440         *cbDecoded = decoded;
441     TRACE("returning %d\n", ret);
442     return ret;
443 }
444
445 /* This decodes an arbitrary sequence into a contiguous block of memory
446  * (basically, a struct.)  Each element being decoded is described by a struct
447  * AsnDecodeSequenceItem, see above.
448  * startingPointer is an optional pointer to the first place where dynamic
449  * data will be stored.  If you know the starting offset, you may pass it
450  * here.  Otherwise, pass NULL, and one will be inferred from the items.
451  */
452 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
453  DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
454  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
455  DWORD *pcbDecoded, void *startingPointer)
456 {
457     BOOL ret;
458
459     TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
460      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
461      startingPointer);
462
463     if (!cbEncoded)
464     {
465         SetLastError(CRYPT_E_ASN1_EOD);
466         return FALSE;
467     }
468     if (pbEncoded[0] == ASN_SEQUENCE)
469     {
470         DWORD dataLen;
471
472         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
473         {
474             DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
475             const BYTE *ptr = pbEncoded + 1 + lenBytes;
476             BOOL indefinite = FALSE;
477
478             cbEncoded -= 1 + lenBytes;
479             if (dataLen == CMSG_INDEFINITE_LENGTH)
480             {
481                 dataLen = cbEncoded;
482                 indefinite = TRUE;
483             }
484             else if (cbEncoded < dataLen)
485             {
486                 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
487                  cbEncoded);
488                 SetLastError(CRYPT_E_ASN1_CORRUPT);
489                 ret = FALSE;
490             }
491             if (ret)
492             {
493                 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
494                  ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
495                 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
496                 {
497                     if (cbDecoded > cbEncoded - 2)
498                     {
499                         /* Not enough space for 0 TLV */
500                         SetLastError(CRYPT_E_ASN1_CORRUPT);
501                         ret = FALSE;
502                     }
503                     else if (*(ptr + cbDecoded) != 0 ||
504                      *(ptr + cbDecoded + 1) != 0)
505                     {
506                         TRACE("expected 0 TLV\n");
507                         SetLastError(CRYPT_E_ASN1_CORRUPT);
508                         ret = FALSE;
509                     }
510                     else
511                         cbDecoded += 2;
512                 }
513             }
514             if (ret && !indefinite && cbDecoded != dataLen)
515             {
516                 TRACE("expected %d decoded, got %d, failing\n", dataLen,
517                  cbDecoded);
518                 SetLastError(CRYPT_E_ASN1_CORRUPT);
519                 ret = FALSE;
520             }
521             if (ret)
522             {
523                 DWORD i, bytesNeeded = 0, structSize = 0;
524
525                 for (i = 0; i < cItem; i++)
526                 {
527                     bytesNeeded += items[i].size;
528                     structSize = max( structSize, items[i].offset + items[i].minSize );
529                 }
530                 if (pcbDecoded)
531                     *pcbDecoded = 1 + lenBytes + cbDecoded;
532                 if (!pvStructInfo)
533                     *pcbStructInfo = bytesNeeded;
534                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
535                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
536                 {
537                     BYTE *nextData;
538
539                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
540                         pvStructInfo = *(BYTE **)pvStructInfo;
541                     if (startingPointer)
542                         nextData = startingPointer;
543                     else
544                         nextData = (BYTE *)pvStructInfo + structSize;
545                     memset(pvStructInfo, 0, structSize);
546                     ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
547                      ptr, dataLen, dwFlags, pvStructInfo, nextData,
548                      &cbDecoded);
549                     if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
550                         CRYPT_FreeSpace(pDecodePara, pvStructInfo);
551                 }
552             }
553         }
554     }
555     else
556     {
557         SetLastError(CRYPT_E_ASN1_BADTAG);
558         ret = FALSE;
559     }
560     TRACE("returning %d (%08x)\n", ret, GetLastError());
561     return ret;
562 }
563
564 /* tag:
565  *     The expected tag of the entire encoded array (usually a variant
566  *     of ASN_SETOF or ASN_SEQUENCEOF.)  If tag is 0, decodeFunc is called
567  *     regardless of the tag seen.
568  * decodeFunc:
569  *     used to decode each item in the array
570  * itemSize:
571  *      is the minimum size of each decoded item
572  * hasPointer:
573  *      indicates whether each item has a dynamic pointer
574  * pointerOffset:
575  *     indicates the offset within itemSize at which the pointer exists
576  */
577 struct AsnArrayDescriptor
578 {
579     BYTE               tag;
580     InternalDecodeFunc decodeFunc;
581     DWORD              itemSize;
582     BOOL               hasPointer;
583     DWORD              pointerOffset;
584 };
585
586 struct AsnArrayItemSize
587 {
588     DWORD encodedLen;
589     DWORD size;
590 };
591
592 /* Decodes an array of like types into a struct GenericArray.
593  * The layout and decoding of the array are described by a struct
594  * AsnArrayDescriptor.
595  */
596 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
597  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
598  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
599  DWORD *pcbDecoded, void *startingPointer)
600 {
601     BOOL ret = TRUE;
602
603     TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
604      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
605      startingPointer);
606
607     if (!cbEncoded)
608     {
609         SetLastError(CRYPT_E_ASN1_EOD);
610         ret = FALSE;
611     }
612     else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
613     {
614         DWORD dataLen;
615
616         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
617         {
618             DWORD bytesNeeded, cItems = 0, decoded;
619             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
620             /* There can be arbitrarily many items, but there is often only one.
621              */
622             struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
623
624             decoded = 1 + lenBytes;
625             bytesNeeded = sizeof(struct GenericArray);
626             if (dataLen)
627             {
628                 const BYTE *ptr;
629                 BOOL doneDecoding = FALSE;
630
631                 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
632                 {
633                     if (dataLen == CMSG_INDEFINITE_LENGTH)
634                     {
635                         if (ptr[0] == 0)
636                         {
637                             doneDecoding = TRUE;
638                             if (ptr[1] != 0)
639                             {
640                                 SetLastError(CRYPT_E_ASN1_CORRUPT);
641                                 ret = FALSE;
642                             }
643                             else
644                                 decoded += 2;
645                         }
646                     }
647                     else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
648                         doneDecoding = TRUE;
649                     if (!doneDecoding)
650                     {
651                         DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
652
653                         /* Each item decoded may not tolerate extraneous bytes,
654                          * so get the length of the next element if known.
655                          */
656                         if ((ret = CRYPT_GetLengthIndefinite(ptr,
657                          cbEncoded - (ptr - pbEncoded), &itemDataLen)))
658                         {
659                             if (itemDataLen == CMSG_INDEFINITE_LENGTH)
660                                 itemEncoded = cbEncoded - (ptr - pbEncoded);
661                             else
662                                 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
663                                  itemDataLen;
664                         }
665                         if (ret)
666                             ret = arrayDesc->decodeFunc(ptr, itemEncoded,
667                              dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
668                              &itemDecoded);
669                         if (ret)
670                         {
671                             cItems++;
672                             if (itemSizes != &itemSize)
673                                 itemSizes = CryptMemRealloc(itemSizes,
674                                  cItems * sizeof(struct AsnArrayItemSize));
675                             else if (cItems > 1)
676                             {
677                                 itemSizes =
678                                  CryptMemAlloc(
679                                  cItems * sizeof(struct AsnArrayItemSize));
680                                 if (itemSizes)
681                                     memcpy(itemSizes, &itemSize,
682                                      sizeof(itemSize));
683                             }
684                             if (itemSizes)
685                             {
686                                 decoded += itemDecoded;
687                                 itemSizes[cItems - 1].encodedLen = itemEncoded;
688                                 itemSizes[cItems - 1].size = size;
689                                 bytesNeeded += size;
690                                 ptr += itemEncoded;
691                             }
692                             else
693                                 ret = FALSE;
694                         }
695                     }
696                 }
697             }
698             if (ret)
699             {
700                 if (pcbDecoded)
701                     *pcbDecoded = decoded;
702                 if (!pvStructInfo)
703                     *pcbStructInfo = bytesNeeded;
704                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
705                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
706                 {
707                     DWORD i;
708                     BYTE *nextData;
709                     const BYTE *ptr;
710                     struct GenericArray *array;
711
712                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
713                         pvStructInfo = *(BYTE **)pvStructInfo;
714                     array = pvStructInfo;
715                     array->cItems = cItems;
716                     if (startingPointer)
717                         array->rgItems = startingPointer;
718                     else
719                         array->rgItems = (BYTE *)array +
720                          sizeof(struct GenericArray);
721                     nextData = array->rgItems +
722                      array->cItems * arrayDesc->itemSize;
723                     for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
724                      i < cItems && ptr - pbEncoded - 1 - lenBytes <
725                      dataLen; i++)
726                     {
727                         DWORD itemDecoded;
728
729                         if (arrayDesc->hasPointer)
730                             *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
731                              + arrayDesc->pointerOffset) = nextData;
732                         ret = arrayDesc->decodeFunc(ptr,
733                          itemSizes[i].encodedLen,
734                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
735                          array->rgItems + i * arrayDesc->itemSize,
736                          &itemSizes[i].size, &itemDecoded);
737                         if (ret)
738                         {
739                             nextData += itemSizes[i].size - arrayDesc->itemSize;
740                             ptr += itemDecoded;
741                         }
742                     }
743                     if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
744                         CRYPT_FreeSpace(pDecodePara, pvStructInfo);
745                 }
746             }
747             if (itemSizes != &itemSize)
748                 CryptMemFree(itemSizes);
749         }
750     }
751     else
752     {
753         SetLastError(CRYPT_E_ASN1_BADTAG);
754         ret = FALSE;
755     }
756     return ret;
757 }
758
759 /* Decodes an array of like types into a struct GenericArray.
760  * The layout and decoding of the array are described by a struct
761  * AsnArrayDescriptor.  Doesn't allocate memory for the decoded items,
762  * leaves that up to the caller.
763  */
764 static BOOL CRYPT_AsnDecodeArrayNoAlloc(const struct AsnArrayDescriptor *arrayDesc,
765  const BYTE *pbEncoded, DWORD cbEncoded, DWORD *pcItems, void *rgItems,
766  DWORD *pcbItems, DWORD *pcbDecoded)
767 {
768     BOOL ret = TRUE;
769
770     TRACE("%p, %p, %d, %p, %p, %d\n", arrayDesc, pbEncoded,
771      cbEncoded, pcItems, rgItems, pcItems ? *pcbItems : 0);
772
773     if (!cbEncoded)
774     {
775         SetLastError(CRYPT_E_ASN1_EOD);
776         ret = FALSE;
777     }
778     else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
779     {
780         DWORD dataLen;
781
782         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
783         {
784             DWORD bytesNeeded = 0, cItems = 0, decoded;
785             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
786             /* There can be arbitrarily many items, but there is often only one.
787              */
788             struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
789
790             decoded = 1 + lenBytes;
791             if (dataLen)
792             {
793                 const BYTE *ptr;
794                 BOOL doneDecoding = FALSE;
795
796                 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
797                 {
798                     if (dataLen == CMSG_INDEFINITE_LENGTH)
799                     {
800                         if (ptr[0] == 0)
801                         {
802                             doneDecoding = TRUE;
803                             if (ptr[1] != 0)
804                             {
805                                 SetLastError(CRYPT_E_ASN1_CORRUPT);
806                                 ret = FALSE;
807                             }
808                             else
809                                 decoded += 2;
810                         }
811                     }
812                     else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
813                         doneDecoding = TRUE;
814                     if (!doneDecoding)
815                     {
816                         DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
817
818                         /* Each item decoded may not tolerate extraneous bytes,
819                          * so get the length of the next element if known.
820                          */
821                         if ((ret = CRYPT_GetLengthIndefinite(ptr,
822                          cbEncoded - (ptr - pbEncoded), &itemDataLen)))
823                         {
824                             if (itemDataLen == CMSG_INDEFINITE_LENGTH)
825                                 itemEncoded = cbEncoded - (ptr - pbEncoded);
826                             else
827                                 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
828                                  itemDataLen;
829                         }
830                         if (ret)
831                             ret = arrayDesc->decodeFunc(ptr, itemEncoded,
832                              0, NULL, &size, &itemDecoded);
833                         if (ret)
834                         {
835                             cItems++;
836                             if (itemSizes != &itemSize)
837                                 itemSizes = CryptMemRealloc(itemSizes,
838                                  cItems * sizeof(struct AsnArrayItemSize));
839                             else if (cItems > 1)
840                             {
841                                 itemSizes =
842                                  CryptMemAlloc(
843                                  cItems * sizeof(struct AsnArrayItemSize));
844                                 if (itemSizes)
845                                     memcpy(itemSizes, &itemSize,
846                                      sizeof(itemSize));
847                             }
848                             if (itemSizes)
849                             {
850                                 decoded += itemDecoded;
851                                 itemSizes[cItems - 1].encodedLen = itemEncoded;
852                                 itemSizes[cItems - 1].size = size;
853                                 bytesNeeded += size;
854                                 ptr += itemEncoded;
855                             }
856                             else
857                                 ret = FALSE;
858                         }
859                     }
860                 }
861             }
862             if (ret)
863             {
864                 if (pcbDecoded)
865                     *pcbDecoded = decoded;
866                 if (!pcItems)
867                     *pcbItems = bytesNeeded;
868                 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, rgItems,
869                  pcbItems, bytesNeeded)))
870                 {
871                     DWORD i;
872                     BYTE *nextData;
873                     const BYTE *ptr;
874
875                     *pcItems = cItems;
876                     nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
877                     for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
878                      i < cItems && ptr - pbEncoded - 1 - lenBytes <
879                      dataLen; i++)
880                     {
881                         DWORD itemDecoded;
882
883                         if (arrayDesc->hasPointer)
884                             *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
885                              + arrayDesc->pointerOffset) = nextData;
886                         ret = arrayDesc->decodeFunc(ptr,
887                          itemSizes[i].encodedLen, 0,
888                          (BYTE *)rgItems + i * arrayDesc->itemSize,
889                          &itemSizes[i].size, &itemDecoded);
890                         if (ret)
891                         {
892                             nextData += itemSizes[i].size - arrayDesc->itemSize;
893                             ptr += itemDecoded;
894                         }
895                     }
896                 }
897             }
898             if (itemSizes != &itemSize)
899                 CryptMemFree(itemSizes);
900         }
901     }
902     else
903     {
904         SetLastError(CRYPT_E_ASN1_BADTAG);
905         ret = FALSE;
906     }
907     return ret;
908 }
909
910 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
911  * pvStructInfo.  The BLOB must be non-empty, otherwise the last error is set
912  * to CRYPT_E_ASN1_CORRUPT.
913  * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
914  * set!
915  */
916 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
917  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
918 {
919     BOOL ret;
920     DWORD dataLen;
921
922     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
923     {
924         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
925         DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
926        
927         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
928             bytesNeeded += 1 + lenBytes + dataLen;
929
930         if (pcbDecoded)
931             *pcbDecoded = 1 + lenBytes + dataLen;
932         if (!pvStructInfo)
933             *pcbStructInfo = bytesNeeded;
934         else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
935         {
936             CRYPT_DER_BLOB *blob;
937
938             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
939                 pvStructInfo = *(BYTE **)pvStructInfo;
940             blob = pvStructInfo;
941             blob->cbData = 1 + lenBytes + dataLen;
942             if (blob->cbData)
943             {
944                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
945                     blob->pbData = (BYTE *)pbEncoded;
946                 else
947                 {
948                     assert(blob->pbData);
949                     memcpy(blob->pbData, pbEncoded, blob->cbData);
950                 }
951             }
952             else
953             {
954                 SetLastError(CRYPT_E_ASN1_CORRUPT);
955                 ret = FALSE;
956             }
957         }
958     }
959     return ret;
960 }
961
962 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
963 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
964  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
965  DWORD *pcbDecoded)
966 {
967     BOOL ret;
968
969     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
970      pvStructInfo, *pcbStructInfo, pcbDecoded);
971
972     /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
973      * place.
974      */
975     ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
976      dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
977      pcbDecoded);
978     if (ret && pvStructInfo)
979     {
980         CRYPT_BIT_BLOB *blob = pvStructInfo;
981
982         if (blob->cbData)
983         {
984             DWORD i;
985             BYTE temp;
986
987             for (i = 0; i < blob->cbData / 2; i++)
988             {
989                 temp = blob->pbData[i];
990                 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
991                 blob->pbData[blob->cbData - i - 1] = temp;
992             }
993         }
994     }
995     TRACE("returning %d (%08x)\n", ret, GetLastError());
996     return ret;
997 }
998
999 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
1000  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1001  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1002 {
1003     BOOL ret = TRUE;
1004
1005     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1006      pDecodePara, pvStructInfo, *pcbStructInfo);
1007
1008     __TRY
1009     {
1010         struct AsnDecodeSequenceItem items[] = {
1011          { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
1012            CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
1013            offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
1014          { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
1015            SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
1016            sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
1017            offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
1018          { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
1019            CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1020            offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
1021         };
1022
1023         if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
1024             items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
1025         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1026          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
1027          pcbStructInfo, NULL, NULL);
1028     }
1029     __EXCEPT_PAGE_FAULT
1030     {
1031         SetLastError(STATUS_ACCESS_VIOLATION);
1032         ret = FALSE;
1033     }
1034     __ENDTRY
1035
1036     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1037     return ret;
1038 }
1039
1040 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
1041  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1042 {
1043     BOOL ret;
1044     DWORD dataLen;
1045
1046     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1047     {
1048         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1049
1050         ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
1051          dwFlags, pvStructInfo, pcbStructInfo, NULL);
1052         if (pcbDecoded)
1053             *pcbDecoded = 1 + lenBytes + dataLen;
1054     }
1055     return ret;
1056 }
1057
1058 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
1059  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1060 {
1061     BOOL ret;
1062
1063     struct AsnDecodeSequenceItem items[] = {
1064      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
1065        CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1066      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
1067        CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1068     };
1069
1070     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1071      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
1072      pcbDecoded, NULL);
1073     return ret;
1074 }
1075
1076 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
1077  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1078  DWORD *pcbDecoded)
1079 {
1080     BOOL ret = TRUE;
1081     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1082      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1083      offsetof(CERT_EXTENSION, pszObjId) };
1084     DWORD itemSize;
1085
1086     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1087      pvStructInfo, *pcbStructInfo, pcbDecoded);
1088
1089     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1090      NULL, NULL, &itemSize, pcbDecoded);
1091     if (ret)
1092     {
1093         DWORD bytesNeeded;
1094
1095         /* The size expected by the caller includes the combination of
1096          * CERT_INFO's cExtension and rgExtension, in addition to the size of
1097          * all the decoded items.  CRYPT_AsnDecodeArrayNoAlloc only returns
1098          * the size of the decoded items, so add the size of cExtension and
1099          * rgExtension.
1100          */
1101         bytesNeeded = FINALMEMBERSIZE(CERT_INFO, cExtension) + itemSize;
1102         if (!pvStructInfo)
1103             *pcbStructInfo = bytesNeeded;
1104         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1105          pcbStructInfo, bytesNeeded)))
1106         {
1107             CERT_INFO *info;
1108
1109             info = (CERT_INFO *)((BYTE *)pvStructInfo -
1110              offsetof(CERT_INFO, cExtension));
1111             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1112              cbEncoded, &info->cExtension, info->rgExtension, &itemSize,
1113              pcbDecoded);
1114         }
1115     }
1116     return ret;
1117 }
1118
1119 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
1120  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1121  DWORD *pcbDecoded)
1122 {
1123     BOOL ret;
1124     DWORD dataLen;
1125
1126     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1127     {
1128         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1129
1130         ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
1131          dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1132         if (ret && pcbDecoded)
1133             *pcbDecoded = 1 + lenBytes + dataLen;
1134     }
1135     return ret;
1136 }
1137
1138 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
1139  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1140  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1141 {
1142     BOOL ret = TRUE;
1143     struct AsnDecodeSequenceItem items[] = {
1144      { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
1145        CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1146      { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
1147        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
1148        TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
1149      { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
1150        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1151        FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
1152      { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1153        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1154        Issuer.pbData) },
1155      { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1156        CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1157        FALSE, 0 },
1158      { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1159        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1160        Subject.pbData) },
1161      { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1162        CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1163        FALSE, TRUE, offsetof(CERT_INFO,
1164        SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1165      { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
1166        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1167        offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1168      { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
1169        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1170        offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1171      { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1172        CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1173        TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1174     };
1175
1176     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1177      pDecodePara, pvStructInfo, *pcbStructInfo);
1178
1179     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1180      pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1181      NULL, NULL);
1182     if (ret && pvStructInfo)
1183     {
1184         CERT_INFO *info;
1185
1186         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1187             info = *(CERT_INFO **)pvStructInfo;
1188         else
1189             info = pvStructInfo;
1190         if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1191          !info->Subject.cbData)
1192         {
1193             SetLastError(CRYPT_E_ASN1_CORRUPT);
1194             /* Don't need to deallocate, because it should have failed on the
1195              * first pass (and no memory was allocated.)
1196              */
1197             ret = FALSE;
1198         }
1199     }
1200
1201     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1202     return ret;
1203 }
1204
1205 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1206  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1207  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1208 {
1209     BOOL ret = FALSE;
1210
1211     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1212      pDecodePara, pvStructInfo, *pcbStructInfo);
1213
1214     __TRY
1215     {
1216         DWORD size = 0;
1217
1218         /* Unless told not to, first try to decode it as a signed cert. */
1219         if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1220         {
1221             PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1222
1223             ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1224              X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1225              &signedCert, &size);
1226             if (ret)
1227             {
1228                 size = 0;
1229                 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1230                  X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1231                  signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1232                  pvStructInfo, pcbStructInfo);
1233                 LocalFree(signedCert);
1234             }
1235         }
1236         /* Failing that, try it as an unsigned cert */
1237         if (!ret)
1238         {
1239             size = 0;
1240             ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1241              X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1242              pDecodePara, pvStructInfo, pcbStructInfo);
1243         }
1244     }
1245     __EXCEPT_PAGE_FAULT
1246     {
1247         SetLastError(STATUS_ACCESS_VIOLATION);
1248     }
1249     __ENDTRY
1250
1251     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1252     return ret;
1253 }
1254
1255 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1256  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1257  DWORD *pcbDecoded)
1258 {
1259     BOOL ret = TRUE;
1260     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1261      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1262      offsetof(CERT_EXTENSION, pszObjId) };
1263     DWORD itemSize;
1264
1265     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1266      pvStructInfo, *pcbStructInfo, pcbDecoded);
1267
1268     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1269      NULL, NULL, &itemSize, pcbDecoded);
1270     if (ret)
1271     {
1272         DWORD bytesNeeded;
1273
1274         /* The size expected by the caller includes the combination of
1275          * CRL_ENTRY's cExtension and rgExtension, in addition to the size of
1276          * all the decoded items.  CRYPT_AsnDecodeArrayNoAlloc only returns
1277          * the size of the decoded items, so add the size of cExtension and
1278          * rgExtension.
1279          */
1280         bytesNeeded = FINALMEMBERSIZE(CRL_ENTRY, cExtension) + itemSize;
1281         if (!pvStructInfo)
1282             *pcbStructInfo = bytesNeeded;
1283         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1284          pcbStructInfo, bytesNeeded)))
1285         {
1286             CRL_ENTRY *entry;
1287
1288             entry = (CRL_ENTRY *)((BYTE *)pvStructInfo -
1289              offsetof(CRL_ENTRY, cExtension));
1290             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1291              cbEncoded, &entry->cExtension, entry->rgExtension, &itemSize,
1292              pcbDecoded);
1293         }
1294     }
1295     return ret;
1296 }
1297
1298 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1299  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1300 {
1301     BOOL ret;
1302     struct AsnDecodeSequenceItem items[] = {
1303      { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1304        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1305        offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1306      { 0, offsetof(CRL_ENTRY, RevocationDate),
1307        CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1308      { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1309        CRYPT_AsnDecodeCRLEntryExtensions,
1310        FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1311        offsetof(CRL_ENTRY, rgExtension), 0 },
1312     };
1313     PCRL_ENTRY entry = pvStructInfo;
1314
1315     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1316      *pcbStructInfo);
1317
1318     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1319      pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1320      entry ? entry->SerialNumber.pbData : NULL);
1321     if (ret && entry && !entry->SerialNumber.cbData)
1322     {
1323         WARN("empty CRL entry serial number\n");
1324         SetLastError(CRYPT_E_ASN1_CORRUPT);
1325         ret = FALSE;
1326     }
1327     return ret;
1328 }
1329
1330 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1331  * whose rgCRLEntry member has been set prior to calling.
1332  */
1333 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1334  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1335 {
1336     BOOL ret;
1337     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1338      CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1339      offsetof(CRL_ENTRY, SerialNumber.pbData) };
1340     DWORD itemSize;
1341
1342     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1343      pvStructInfo, *pcbStructInfo, pcbDecoded);
1344
1345     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1346      NULL, NULL, &itemSize, pcbDecoded);
1347     if (ret)
1348     {
1349         DWORD bytesNeeded;
1350
1351         /* The size expected by the caller includes the combination of
1352          * CRL_INFO's cCRLEntry and rgCRLEntry, in addition to the size of
1353          * all the decoded items.  CRYPT_AsnDecodeArrayNoAlloc only returns
1354          * the size of the decoded items, so add the size of cCRLEntry and
1355          * rgCRLEntry.
1356          */
1357         bytesNeeded = offsetof(CRL_INFO, cExtension) -
1358          offsetof(CRL_INFO, cCRLEntry) + itemSize;
1359         if (!pvStructInfo)
1360             *pcbStructInfo = bytesNeeded;
1361         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1362          pcbStructInfo, bytesNeeded)))
1363         {
1364             CRL_INFO *info;
1365
1366             info = (CRL_INFO *)((BYTE *)pvStructInfo -
1367              offsetof(CRL_INFO, cCRLEntry));
1368             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1369              cbEncoded, &info->cCRLEntry, info->rgCRLEntry, &itemSize,
1370              pcbDecoded);
1371         }
1372     }
1373     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1374     return ret;
1375 }
1376
1377 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1378  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1379  DWORD *pcbDecoded)
1380 {
1381     BOOL ret = TRUE;
1382     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1383      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1384      offsetof(CERT_EXTENSION, pszObjId) };
1385     DWORD itemSize;
1386
1387     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1388      pvStructInfo, *pcbStructInfo, pcbDecoded);
1389
1390     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1391      NULL, NULL, &itemSize, pcbDecoded);
1392     if (ret)
1393     {
1394         DWORD bytesNeeded;
1395
1396         /* The size expected by the caller includes the combination of
1397          * CRL_INFO's cExtension and rgExtension, in addition to the size of
1398          * all the decoded items.  CRYPT_AsnDecodeArrayNoAlloc only returns
1399          * the size of the decoded items, so add the size of cExtension and
1400          * rgExtension.
1401          */
1402         bytesNeeded = FINALMEMBERSIZE(CRL_INFO, cExtension) + itemSize;
1403         if (!pvStructInfo)
1404             *pcbStructInfo = bytesNeeded;
1405         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1406          pcbStructInfo, bytesNeeded)))
1407         {
1408             CRL_INFO *info;
1409
1410             info = (CRL_INFO *)((BYTE *)pvStructInfo -
1411              offsetof(CRL_INFO, cExtension));
1412             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1413              cbEncoded, &info->cExtension, info->rgExtension, &itemSize,
1414              pcbDecoded);
1415         }
1416     }
1417     return ret;
1418 }
1419
1420 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1421  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1422  DWORD *pcbDecoded)
1423 {
1424     BOOL ret;
1425     DWORD dataLen;
1426
1427     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1428     {
1429         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1430
1431         ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1432          dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1433         if (ret && pcbDecoded)
1434             *pcbDecoded = 1 + lenBytes + dataLen;
1435     }
1436     return ret;
1437 }
1438
1439 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1440  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1441  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1442 {
1443     struct AsnDecodeSequenceItem items[] = {
1444      { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1445        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1446      { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1447        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1448        FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1449      { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1450        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1451        Issuer.pbData) },
1452      { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1453        sizeof(FILETIME), FALSE, FALSE, 0 },
1454      { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1455        sizeof(FILETIME), TRUE, FALSE, 0 },
1456      { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1457        CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1458        TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1459      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1460        CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1461        TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1462     };
1463     BOOL ret = TRUE;
1464
1465     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1466      pDecodePara, pvStructInfo, *pcbStructInfo);
1467
1468     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1469      pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1470      NULL, NULL);
1471
1472     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1473     return ret;
1474 }
1475
1476 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1477  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1478  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1479 {
1480     BOOL ret = FALSE;
1481
1482     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1483      pDecodePara, pvStructInfo, *pcbStructInfo);
1484
1485     __TRY
1486     {
1487         DWORD size = 0;
1488
1489         /* Unless told not to, first try to decode it as a signed crl. */
1490         if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1491         {
1492             PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1493
1494             ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1495              X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1496              &signedCrl, &size);
1497             if (ret)
1498             {
1499                 size = 0;
1500                 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1501                  X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1502                  signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1503                  pvStructInfo, pcbStructInfo);
1504                 LocalFree(signedCrl);
1505             }
1506         }
1507         /* Failing that, try it as an unsigned crl */
1508         if (!ret)
1509         {
1510             size = 0;
1511             ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1512              X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1513              dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1514         }
1515     }
1516     __EXCEPT_PAGE_FAULT
1517     {
1518         SetLastError(STATUS_ACCESS_VIOLATION);
1519     }
1520     __ENDTRY
1521
1522     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1523     return ret;
1524 }
1525
1526 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1527  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1528 {
1529     BOOL ret = TRUE;
1530     DWORD dataLen;
1531
1532     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1533      pvStructInfo, *pcbStructInfo);
1534
1535     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1536     {
1537         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1538         DWORD bytesNeeded = sizeof(LPSTR);
1539
1540         if (dataLen)
1541         {
1542             /* The largest possible string for the first two components
1543              * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1544              */
1545             char firstTwo[6];
1546             const BYTE *ptr;
1547
1548             snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1549              pbEncoded[1 + lenBytes] / 40,
1550              pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1551              * 40);
1552             bytesNeeded += strlen(firstTwo) + 1;
1553             for (ptr = pbEncoded + 2 + lenBytes; ret &&
1554              ptr - pbEncoded - 1 - lenBytes < dataLen; )
1555             {
1556                 /* large enough for ".4000000" */
1557                 char str[9];
1558                 int val = 0;
1559
1560                 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1561                  (*ptr & 0x80))
1562                 {
1563                     val <<= 7;
1564                     val |= *ptr & 0x7f;
1565                     ptr++;
1566                 }
1567                 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1568                  (*ptr & 0x80))
1569                 {
1570                     SetLastError(CRYPT_E_ASN1_CORRUPT);
1571                     ret = FALSE;
1572                 }
1573                 else
1574                 {
1575                     val <<= 7;
1576                     val |= *ptr++;
1577                     snprintf(str, sizeof(str), ".%d", val);
1578                     bytesNeeded += strlen(str);
1579                 }
1580             }
1581         }
1582         if (pcbDecoded)
1583             *pcbDecoded = 1 + lenBytes + dataLen;
1584         if (!pvStructInfo)
1585             *pcbStructInfo = bytesNeeded;
1586         else if (*pcbStructInfo < bytesNeeded)
1587         {
1588             *pcbStructInfo = bytesNeeded;
1589             SetLastError(ERROR_MORE_DATA);
1590             ret = FALSE;
1591         }
1592         else
1593         {
1594             if (dataLen)
1595             {
1596                 const BYTE *ptr;
1597                 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1598
1599                 *pszObjId = 0;
1600                 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1601                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1602                  40) * 40);
1603                 pszObjId += strlen(pszObjId);
1604                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1605                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
1606                 {
1607                     int val = 0;
1608
1609                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1610                      (*ptr & 0x80))
1611                     {
1612                         val <<= 7;
1613                         val |= *ptr & 0x7f;
1614                         ptr++;
1615                     }
1616                     val <<= 7;
1617                     val |= *ptr++;
1618                     sprintf(pszObjId, ".%d", val);
1619                     pszObjId += strlen(pszObjId);
1620                 }
1621             }
1622             else
1623                 *(LPSTR *)pvStructInfo = NULL;
1624             *pcbStructInfo = bytesNeeded;
1625         }
1626     }
1627     return ret;
1628 }
1629
1630 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1631  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1632 {
1633     BOOL ret;
1634
1635     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1636      pvStructInfo, *pcbStructInfo);
1637
1638     if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1639         ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1640          pvStructInfo, pcbStructInfo, pcbDecoded);
1641     else
1642     {
1643         SetLastError(CRYPT_E_ASN1_BADTAG);
1644         ret = FALSE;
1645     }
1646     return ret;
1647 }
1648
1649 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1650  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1651 {
1652     struct AsnDecodeSequenceItem items[] = {
1653      { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1654        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1655        offsetof(CERT_EXTENSION, pszObjId), 0 },
1656      { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1657        sizeof(BOOL), TRUE, FALSE, 0, 0 },
1658      { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1659        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1660        offsetof(CERT_EXTENSION, Value.pbData) },
1661     };
1662     BOOL ret = TRUE;
1663     PCERT_EXTENSION ext = pvStructInfo;
1664
1665     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1666      *pcbStructInfo);
1667
1668     if (ext)
1669         TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1670     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1671      pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1672      pcbDecoded, ext ? ext->pszObjId : NULL);
1673     if (ext)
1674         TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1675          debugstr_a(ext->pszObjId));
1676     TRACE("returning %d (%08x)\n", ret, GetLastError());
1677     return ret;
1678 }
1679
1680 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1681  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1682  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1683 {
1684     BOOL ret = TRUE;
1685
1686     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1687      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1688
1689     __TRY
1690     {
1691         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1692          CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1693          offsetof(CERT_EXTENSION, pszObjId) };
1694         DWORD itemSize;
1695
1696         ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1697          NULL, NULL, &itemSize, NULL);
1698         if (ret)
1699         {
1700             DWORD bytesNeeded;
1701
1702             /* CRYPT_AsnDecodeArrayNoAlloc only returns the size of the decoded
1703              * items, so add the size of CERT_EXTENSIONS.
1704              */
1705             bytesNeeded = sizeof(CERT_EXTENSIONS) + itemSize;
1706             if (!pvStructInfo)
1707                 *pcbStructInfo = bytesNeeded;
1708             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1709              pvStructInfo, pcbStructInfo, bytesNeeded)))
1710             {
1711                 CERT_EXTENSIONS *exts;
1712
1713                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1714                     pvStructInfo = *(BYTE **)pvStructInfo;
1715                 exts = (CERT_EXTENSIONS *)pvStructInfo;
1716                 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1717                  sizeof(CERT_EXTENSIONS));
1718                 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1719                  cbEncoded, &exts->cExtension, exts->rgExtension, &itemSize,
1720                  NULL);
1721             }
1722         }
1723     }
1724     __EXCEPT_PAGE_FAULT
1725     {
1726         SetLastError(STATUS_ACCESS_VIOLATION);
1727         ret = FALSE;
1728     }
1729     __ENDTRY
1730     return ret;
1731 }
1732
1733 /* Warning: this assumes the address of value->Value.pbData is already set, in
1734  * order to avoid overwriting memory.  (In some cases, it may change it, if it
1735  * doesn't copy anything to memory.)  Be sure to set it correctly!
1736  */
1737 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1738  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1739  DWORD *pcbDecoded)
1740 {
1741     BOOL ret = TRUE;
1742     DWORD dataLen;
1743     CERT_NAME_VALUE *value = pvStructInfo;
1744
1745     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1746     {
1747         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1748         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1749
1750         switch (pbEncoded[0])
1751         {
1752         case ASN_OCTETSTRING:
1753             valueType = CERT_RDN_OCTET_STRING;
1754             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1755                 bytesNeeded += dataLen;
1756             break;
1757         case ASN_NUMERICSTRING:
1758             valueType = CERT_RDN_NUMERIC_STRING;
1759             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1760                 bytesNeeded += dataLen;
1761             break;
1762         case ASN_PRINTABLESTRING:
1763             valueType = CERT_RDN_PRINTABLE_STRING;
1764             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1765                 bytesNeeded += dataLen;
1766             break;
1767         case ASN_IA5STRING:
1768             valueType = CERT_RDN_IA5_STRING;
1769             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1770                 bytesNeeded += dataLen;
1771             break;
1772         case ASN_T61STRING:
1773             valueType = CERT_RDN_T61_STRING;
1774             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1775                 bytesNeeded += dataLen;
1776             break;
1777         case ASN_VIDEOTEXSTRING:
1778             valueType = CERT_RDN_VIDEOTEX_STRING;
1779             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1780                 bytesNeeded += dataLen;
1781             break;
1782         case ASN_GRAPHICSTRING:
1783             valueType = CERT_RDN_GRAPHIC_STRING;
1784             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1785                 bytesNeeded += dataLen;
1786             break;
1787         case ASN_VISIBLESTRING:
1788             valueType = CERT_RDN_VISIBLE_STRING;
1789             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1790                 bytesNeeded += dataLen;
1791             break;
1792         case ASN_GENERALSTRING:
1793             valueType = CERT_RDN_GENERAL_STRING;
1794             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1795                 bytesNeeded += dataLen;
1796             break;
1797         case ASN_UNIVERSALSTRING:
1798             FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1799             SetLastError(CRYPT_E_ASN1_BADTAG);
1800             return FALSE;
1801         case ASN_BMPSTRING:
1802             valueType = CERT_RDN_BMP_STRING;
1803             bytesNeeded += dataLen;
1804             break;
1805         case ASN_UTF8STRING:
1806             valueType = CERT_RDN_UTF8_STRING;
1807             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1808              (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1809             break;
1810         default:
1811             SetLastError(CRYPT_E_ASN1_BADTAG);
1812             return FALSE;
1813         }
1814
1815         if (pcbDecoded)
1816             *pcbDecoded = 1 + lenBytes + dataLen;
1817         if (!value)
1818             *pcbStructInfo = bytesNeeded;
1819         else if (*pcbStructInfo < bytesNeeded)
1820         {
1821             *pcbStructInfo = bytesNeeded;
1822             SetLastError(ERROR_MORE_DATA);
1823             ret = FALSE;
1824         }
1825         else
1826         {
1827             *pcbStructInfo = bytesNeeded;
1828             value->dwValueType = valueType;
1829             if (dataLen)
1830             {
1831                 DWORD i;
1832
1833                 assert(value->Value.pbData);
1834                 switch (pbEncoded[0])
1835                 {
1836                 case ASN_OCTETSTRING:
1837                 case ASN_NUMERICSTRING:
1838                 case ASN_PRINTABLESTRING:
1839                 case ASN_IA5STRING:
1840                 case ASN_T61STRING:
1841                 case ASN_VIDEOTEXSTRING:
1842                 case ASN_GRAPHICSTRING:
1843                 case ASN_VISIBLESTRING:
1844                 case ASN_GENERALSTRING:
1845                     value->Value.cbData = dataLen;
1846                     if (dataLen)
1847                     {
1848                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1849                             memcpy(value->Value.pbData,
1850                              pbEncoded + 1 + lenBytes, dataLen);
1851                         else
1852                             value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1853                              lenBytes;
1854                     }
1855                     break;
1856                 case ASN_BMPSTRING:
1857                 {
1858                     LPWSTR str = (LPWSTR)value->Value.pbData;
1859
1860                     value->Value.cbData = dataLen;
1861                     for (i = 0; i < dataLen / 2; i++)
1862                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1863                          pbEncoded[1 + lenBytes + 2 * i + 1];
1864                     break;
1865                 }
1866                 case ASN_UTF8STRING:
1867                 {
1868                     LPWSTR str = (LPWSTR)value->Value.pbData;
1869
1870                     value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1871                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, 
1872                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1873                     break;
1874                 }
1875                 }
1876             }
1877             else
1878             {
1879                 value->Value.cbData = 0;
1880                 value->Value.pbData = NULL;
1881             }
1882         }
1883     }
1884     return ret;
1885 }
1886
1887 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1888  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1889  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1890 {
1891     BOOL ret = TRUE;
1892
1893     __TRY
1894     {
1895         ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1896          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1897         if (ret && pvStructInfo)
1898         {
1899             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1900              pcbStructInfo, *pcbStructInfo);
1901             if (ret)
1902             {
1903                 CERT_NAME_VALUE *value;
1904
1905                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1906                     pvStructInfo = *(BYTE **)pvStructInfo;
1907                 value = pvStructInfo;
1908                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1909                 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1910                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1911                  pcbStructInfo, NULL);
1912             }
1913         }
1914     }
1915     __EXCEPT_PAGE_FAULT
1916     {
1917         SetLastError(STATUS_ACCESS_VIOLATION);
1918         ret = FALSE;
1919     }
1920     __ENDTRY
1921     return ret;
1922 }
1923
1924 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1925  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1926  DWORD *pcbDecoded)
1927 {
1928     BOOL ret = TRUE;
1929     DWORD dataLen;
1930     CERT_NAME_VALUE *value = pvStructInfo;
1931
1932     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1933     {
1934         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1935         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1936
1937         switch (pbEncoded[0])
1938         {
1939         case ASN_NUMERICSTRING:
1940             valueType = CERT_RDN_NUMERIC_STRING;
1941             if (dataLen)
1942                 bytesNeeded += (dataLen + 1) * 2;
1943             break;
1944         case ASN_PRINTABLESTRING:
1945             valueType = CERT_RDN_PRINTABLE_STRING;
1946             if (dataLen)
1947                 bytesNeeded += (dataLen + 1) * 2;
1948             break;
1949         case ASN_IA5STRING:
1950             valueType = CERT_RDN_IA5_STRING;
1951             if (dataLen)
1952                 bytesNeeded += (dataLen + 1) * 2;
1953             break;
1954         case ASN_T61STRING:
1955             valueType = CERT_RDN_T61_STRING;
1956             if (dataLen)
1957                 bytesNeeded += (dataLen + 1) * 2;
1958             break;
1959         case ASN_VIDEOTEXSTRING:
1960             valueType = CERT_RDN_VIDEOTEX_STRING;
1961             if (dataLen)
1962                 bytesNeeded += (dataLen + 1) * 2;
1963             break;
1964         case ASN_GRAPHICSTRING:
1965             valueType = CERT_RDN_GRAPHIC_STRING;
1966             if (dataLen)
1967                 bytesNeeded += (dataLen + 1) * 2;
1968             break;
1969         case ASN_VISIBLESTRING:
1970             valueType = CERT_RDN_VISIBLE_STRING;
1971             if (dataLen)
1972                 bytesNeeded += (dataLen + 1) * 2;
1973             break;
1974         case ASN_GENERALSTRING:
1975             valueType = CERT_RDN_GENERAL_STRING;
1976             if (dataLen)
1977                 bytesNeeded += (dataLen + 1) * 2;
1978             break;
1979         case ASN_UNIVERSALSTRING:
1980             valueType = CERT_RDN_UNIVERSAL_STRING;
1981             if (dataLen)
1982                 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1983             break;
1984         case ASN_BMPSTRING:
1985             valueType = CERT_RDN_BMP_STRING;
1986             if (dataLen)
1987                 bytesNeeded += dataLen + sizeof(WCHAR);
1988             break;
1989         case ASN_UTF8STRING:
1990             valueType = CERT_RDN_UTF8_STRING;
1991             if (dataLen)
1992                 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1993                  (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1994             break;
1995         default:
1996             SetLastError(CRYPT_E_ASN1_BADTAG);
1997             return FALSE;
1998         }
1999
2000         if (pcbDecoded)
2001             *pcbDecoded = 1 + lenBytes + dataLen;
2002         if (!value)
2003             *pcbStructInfo = bytesNeeded;
2004         else if (*pcbStructInfo < bytesNeeded)
2005         {
2006             *pcbStructInfo = bytesNeeded;
2007             SetLastError(ERROR_MORE_DATA);
2008             ret = FALSE;
2009         }
2010         else
2011         {
2012             *pcbStructInfo = bytesNeeded;
2013             value->dwValueType = valueType;
2014             if (dataLen)
2015             {
2016                 DWORD i;
2017                 LPWSTR str = (LPWSTR)value->Value.pbData;
2018
2019                 assert(value->Value.pbData);
2020                 switch (pbEncoded[0])
2021                 {
2022                 case ASN_NUMERICSTRING:
2023                 case ASN_PRINTABLESTRING:
2024                 case ASN_IA5STRING:
2025                 case ASN_T61STRING:
2026                 case ASN_VIDEOTEXSTRING:
2027                 case ASN_GRAPHICSTRING:
2028                 case ASN_VISIBLESTRING:
2029                 case ASN_GENERALSTRING:
2030                     value->Value.cbData = dataLen * 2;
2031                     for (i = 0; i < dataLen; i++)
2032                         str[i] = pbEncoded[1 + lenBytes + i];
2033                     str[i] = 0;
2034                     break;
2035                 case ASN_UNIVERSALSTRING:
2036                     value->Value.cbData = dataLen / 2;
2037                     for (i = 0; i < dataLen / 4; i++)
2038                         str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2039                          | pbEncoded[1 + lenBytes + 2 * i + 3];
2040                     str[i] = 0;
2041                     break;
2042                 case ASN_BMPSTRING:
2043                     value->Value.cbData = dataLen;
2044                     for (i = 0; i < dataLen / 2; i++)
2045                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2046                          pbEncoded[1 + lenBytes + 2 * i + 1];
2047                     str[i] = 0;
2048                     break;
2049                 case ASN_UTF8STRING:
2050                     value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
2051                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2052                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
2053                     *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
2054                     value->Value.cbData += sizeof(WCHAR);
2055                     break;
2056                 }
2057             }
2058             else
2059             {
2060                 value->Value.cbData = 0;
2061                 value->Value.pbData = NULL;
2062             }
2063         }
2064     }
2065     return ret;
2066 }
2067
2068 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
2069  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2070  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2071 {
2072     BOOL ret = TRUE;
2073
2074     __TRY
2075     {
2076         ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
2077          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2078         if (ret && pvStructInfo)
2079         {
2080             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2081              pcbStructInfo, *pcbStructInfo);
2082             if (ret)
2083             {
2084                 CERT_NAME_VALUE *value;
2085
2086                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2087                     pvStructInfo = *(BYTE **)pvStructInfo;
2088                 value = pvStructInfo;
2089                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
2090                 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
2091                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2092                  pcbStructInfo, NULL);
2093             }
2094         }
2095     }
2096     __EXCEPT_PAGE_FAULT
2097     {
2098         SetLastError(STATUS_ACCESS_VIOLATION);
2099         ret = FALSE;
2100     }
2101     __ENDTRY
2102     return ret;
2103 }
2104
2105 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
2106  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2107 {
2108     BOOL ret;
2109     struct AsnDecodeSequenceItem items[] = {
2110      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
2111        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2112        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
2113      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
2114        CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
2115        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
2116     };
2117     CERT_RDN_ATTR *attr = pvStructInfo;
2118
2119     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2120      pvStructInfo, *pcbStructInfo);
2121
2122     if (attr)
2123         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
2124     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2125      pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
2126      attr ? attr->pszObjId : NULL);
2127     if (attr)
2128     {
2129         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
2130          debugstr_a(attr->pszObjId));
2131         TRACE("attr->dwValueType is %d\n", attr->dwValueType);
2132     }
2133     TRACE("returning %d (%08x)\n", ret, GetLastError());
2134     return ret;
2135 }
2136
2137 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
2138  DWORD dwFlags,  void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2139 {
2140     BOOL ret = TRUE;
2141     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2142      CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
2143      offsetof(CERT_RDN_ATTR, pszObjId) };
2144     PCERT_RDN rdn = pvStructInfo;
2145
2146     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2147      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2148      rdn ? rdn->rgRDNAttr : NULL);
2149     return ret;
2150 }
2151
2152 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
2153  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2154  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2155 {
2156     BOOL ret = TRUE;
2157
2158     __TRY
2159     {
2160         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2161          CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
2162          offsetof(CERT_RDN, rgRDNAttr) };
2163
2164         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2165          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2166     }
2167     __EXCEPT_PAGE_FAULT
2168     {
2169         SetLastError(STATUS_ACCESS_VIOLATION);
2170         ret = FALSE;
2171     }
2172     __ENDTRY
2173     return ret;
2174 }
2175
2176 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
2177  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2178  DWORD *pcbDecoded)
2179 {
2180     BOOL ret;
2181     struct AsnDecodeSequenceItem items[] = {
2182      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
2183        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2184        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
2185      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
2186        CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
2187        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
2188     };
2189     CERT_RDN_ATTR *attr = pvStructInfo;
2190
2191     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2192      pvStructInfo, *pcbStructInfo);
2193
2194     if (attr)
2195         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
2196     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2197      pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
2198      attr ? attr->pszObjId : NULL);
2199     if (attr)
2200     {
2201         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
2202          debugstr_a(attr->pszObjId));
2203         TRACE("attr->dwValueType is %d\n", attr->dwValueType);
2204     }
2205     TRACE("returning %d (%08x)\n", ret, GetLastError());
2206     return ret;
2207 }
2208
2209 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
2210  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2211 {
2212     BOOL ret = TRUE;
2213     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2214      CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
2215      offsetof(CERT_RDN_ATTR, pszObjId) };
2216     PCERT_RDN rdn = pvStructInfo;
2217
2218     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2219      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2220      rdn ? rdn->rgRDNAttr : NULL);
2221     return ret;
2222 }
2223
2224 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2225  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2226  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2227 {
2228     BOOL ret = TRUE;
2229
2230     __TRY
2231     {
2232         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2233          CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2234          offsetof(CERT_RDN, rgRDNAttr) };
2235
2236         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2237          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2238     }
2239     __EXCEPT_PAGE_FAULT
2240     {
2241         SetLastError(STATUS_ACCESS_VIOLATION);
2242         ret = FALSE;
2243     }
2244     __ENDTRY
2245     return ret;
2246 }
2247
2248 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2249  DWORD *pcbDecoded)
2250 {
2251     BOOL ret = TRUE, done = FALSE;
2252     DWORD indefiniteNestingLevels = 0, decoded = 0;
2253
2254     TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
2255
2256     do {
2257         DWORD dataLen;
2258
2259         if (!cbEncoded)
2260             done = TRUE;
2261         else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2262          &dataLen)))
2263         {
2264             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2265
2266             if (dataLen == CMSG_INDEFINITE_LENGTH)
2267             {
2268                 indefiniteNestingLevels++;
2269                 pbEncoded += 1 + lenBytes;
2270                 cbEncoded -= 1 + lenBytes;
2271                 decoded += 1 + lenBytes;
2272                 TRACE("indefiniteNestingLevels = %d\n",
2273                  indefiniteNestingLevels);
2274             }
2275             else
2276             {
2277                 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2278                  indefiniteNestingLevels)
2279                 {
2280                     indefiniteNestingLevels--;
2281                     TRACE("indefiniteNestingLevels = %d\n",
2282                      indefiniteNestingLevels);
2283                 }
2284                 pbEncoded += 1 + lenBytes + dataLen;
2285                 cbEncoded -= 1 + lenBytes + dataLen;
2286                 decoded += 1 + lenBytes + dataLen;
2287                 if (!indefiniteNestingLevels)
2288                     done = TRUE;
2289             }
2290         }
2291     } while (ret && !done);
2292     /* If we haven't found all 0 TLVs, we haven't found the end */
2293     if (ret && indefiniteNestingLevels)
2294     {
2295         SetLastError(CRYPT_E_ASN1_EOD);
2296         ret = FALSE;
2297     }
2298     if (ret)
2299         *pcbDecoded = decoded;
2300     TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2301     return ret;
2302 }
2303
2304 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2305  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2306  DWORD *pcbDecoded)
2307 {
2308     BOOL ret = TRUE;
2309     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2310
2311     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2312      pvStructInfo, *pcbStructInfo);
2313
2314     if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2315     {
2316         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2317             bytesNeeded += encodedLen;
2318         if (!pvStructInfo)
2319             *pcbStructInfo = bytesNeeded;
2320         else if (*pcbStructInfo < bytesNeeded)
2321         {
2322             SetLastError(ERROR_MORE_DATA);
2323             *pcbStructInfo = bytesNeeded;
2324             ret = FALSE;
2325         }
2326         else
2327         {
2328             PCRYPT_OBJID_BLOB blob = pvStructInfo;
2329
2330             *pcbStructInfo = bytesNeeded;
2331             blob->cbData = encodedLen;
2332             if (encodedLen)
2333             {
2334                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2335                     blob->pbData = (LPBYTE)pbEncoded;
2336                 else
2337                 {
2338                     assert(blob->pbData);
2339                     memcpy(blob->pbData, pbEncoded, blob->cbData);
2340                 }
2341             }
2342             else
2343                 blob->pbData = NULL;
2344         }
2345         if (pcbDecoded)
2346             *pcbDecoded = encodedLen;
2347     }
2348     return ret;
2349 }
2350
2351 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2352  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2353 {
2354     BOOL ret;
2355     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2356      CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2357     CTL_USAGE *usage = pvStructInfo;
2358
2359     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2360      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2361      usage ? usage->rgpszUsageIdentifier : NULL);
2362     return ret;
2363 }
2364
2365 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2366  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2367 {
2368     struct AsnDecodeSequenceItem items[] = {
2369      { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2370        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2371        offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2372      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2373        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2374        TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2375     };
2376     BOOL ret = TRUE;
2377     CTL_ENTRY *entry = pvStructInfo;
2378
2379     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2380      *pcbStructInfo);
2381
2382     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2383      pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2384      pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2385     return ret;
2386 }
2387
2388 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2389  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2390 {
2391     BOOL ret;
2392     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2393      CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2394      offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2395     struct GenericArray *entries = pvStructInfo;
2396
2397     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2398      pvStructInfo, *pcbStructInfo, pcbDecoded);
2399
2400     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2401      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2402      entries ? entries->rgItems : NULL);
2403     return ret;
2404 }
2405
2406 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2407  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2408  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2409 {
2410     BOOL ret = FALSE;
2411
2412     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2413      pDecodePara, pvStructInfo, *pcbStructInfo);
2414
2415     __TRY
2416     {
2417         struct AsnDecodeSequenceItem items[] = {
2418          { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2419            CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2420          { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2421            CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2422            offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2423          { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2424            CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2425            TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2426          { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2427            CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2428            TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2429          { 0, offsetof(CTL_INFO, ThisUpdate),
2430            CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2431            0 },
2432          { 0, offsetof(CTL_INFO, NextUpdate),
2433            CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2434            0 },
2435          { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2436            CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2437            FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2438          { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2439            CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2440            TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2441          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2442            CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2443            offsetof(CTL_INFO, rgExtension), 0 },
2444         };
2445
2446         TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2447          pDecodePara, pvStructInfo, *pcbStructInfo);
2448
2449         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2450          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2451          pcbStructInfo, NULL, NULL);
2452     }
2453     __EXCEPT_PAGE_FAULT
2454     {
2455         SetLastError(STATUS_ACCESS_VIOLATION);
2456     }
2457     __ENDTRY
2458     return ret;
2459 }
2460
2461 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2462  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2463  DWORD *pcbDecoded)
2464 {
2465     BOOL ret;
2466     struct AsnDecodeSequenceItem items[] = {
2467      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2468        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2469        offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2470      { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2471        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2472        offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2473     };
2474     PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2475
2476     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2477      pvStructInfo, *pcbStructInfo);
2478
2479     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2480      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2481      pcbDecoded, capability ? capability->pszObjId : NULL);
2482     TRACE("returning %d\n", ret);
2483     return ret;
2484 }
2485
2486 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2487  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2488  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2489 {
2490     BOOL ret = FALSE;
2491
2492     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2493      pDecodePara, pvStructInfo, *pcbStructInfo);
2494
2495     __TRY
2496     {
2497         DWORD bytesNeeded;
2498         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2499          CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2500          offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2501
2502         if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2503          NULL, NULL, &bytesNeeded, NULL)))
2504         {
2505             bytesNeeded += sizeof(CRYPT_SMIME_CAPABILITIES);
2506             if (!pvStructInfo)
2507                 *pcbStructInfo = bytesNeeded;
2508             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2509              pvStructInfo, pcbStructInfo, bytesNeeded)))
2510             {
2511                 PCRYPT_SMIME_CAPABILITIES capabilities;
2512
2513                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2514                     pvStructInfo = *(BYTE **)pvStructInfo;
2515                 capabilities = pvStructInfo;
2516                 capabilities->rgCapability =
2517                  (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2518                  sizeof(CRYPT_SMIME_CAPABILITIES));
2519                 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
2520                  pbEncoded, cbEncoded, &capabilities->cCapability,
2521                  capabilities->rgCapability, pcbStructInfo, NULL);
2522             }
2523         }
2524     }
2525     __EXCEPT_PAGE_FAULT
2526     {
2527         SetLastError(STATUS_ACCESS_VIOLATION);
2528     }
2529     __ENDTRY
2530     TRACE("returning %d\n", ret);
2531     return ret;
2532 }
2533
2534 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2535  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2536  DWORD *pcbDecoded)
2537 {
2538     BOOL ret = TRUE;
2539     DWORD dataLen;
2540     LPSTR *pStr = pvStructInfo;
2541
2542     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2543     {
2544         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2545         DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2546
2547         if (pbEncoded[0] != ASN_IA5STRING)
2548         {
2549             SetLastError(CRYPT_E_ASN1_CORRUPT);
2550             ret = FALSE;
2551         }
2552         else
2553         {
2554             bytesNeeded += dataLen;
2555             if (pcbDecoded)
2556                 *pcbDecoded = 1 + lenBytes + dataLen;
2557             if (!pvStructInfo)
2558                 *pcbStructInfo = bytesNeeded;
2559             else if (*pcbStructInfo < bytesNeeded)
2560             {
2561                 *pcbStructInfo = bytesNeeded;
2562                 SetLastError(ERROR_MORE_DATA);
2563                 ret = FALSE;
2564             }
2565             else
2566             {
2567                 *pcbStructInfo = bytesNeeded;
2568                 if (dataLen)
2569                 {
2570                     LPSTR str = *pStr;
2571
2572                     assert(str);
2573                     memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2574                     str[dataLen] = 0;
2575                 }
2576                 else
2577                     *pStr = NULL;
2578             }
2579         }
2580     }
2581     return ret;
2582 }
2583
2584 static BOOL CRYPT_AsnDecodeIntArray(const BYTE *pbEncoded,
2585  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2586  DWORD *pcbDecoded)
2587 {
2588     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2589      CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2590     struct GenericArray *array = pvStructInfo;
2591     BOOL ret;
2592
2593     TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2594      pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2595
2596     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2597      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2598      array ? array->rgItems : NULL);
2599     TRACE("returning %d\n", ret);
2600     return ret;
2601 }
2602
2603 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2604  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2605  DWORD *pcbDecoded)
2606 {
2607     BOOL ret;
2608     struct AsnDecodeSequenceItem items[] = {
2609      { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2610        pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2611        offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2612      { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2613        cNoticeNumbers), CRYPT_AsnDecodeIntArray, sizeof(struct GenericArray),
2614        FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2615        rgNoticeNumbers), 0 },
2616     };
2617     DWORD bytesNeeded;
2618
2619     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2620      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2621
2622     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2623      pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2624      NULL);
2625     if (ret)
2626     {
2627         /* The caller is expecting a pointer to a
2628          * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2629          * CRYPT_AsnDecodeSequence is decoding a
2630          * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.  Increment the bytes
2631          * needed, and decode again if the requisite space is available.
2632          */
2633         bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2634         if (!pvStructInfo)
2635             *pcbStructInfo = bytesNeeded;
2636         else if (*pcbStructInfo < bytesNeeded)
2637         {
2638             *pcbStructInfo = bytesNeeded;
2639             SetLastError(ERROR_MORE_DATA);
2640             ret = FALSE;
2641         }
2642         else
2643         {
2644             PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2645
2646             *pcbStructInfo = bytesNeeded;
2647             /* The pointer (pvStructInfo) passed in points to the first dynamic
2648              * pointer, so use it as the pointer to the
2649              * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2650              * appropriate offset for the first dynamic pointer within the
2651              * notice reference by pointing to the first memory location past
2652              * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2653              */
2654             noticeRef =
2655              *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2656             noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2657              sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2658             ret = CRYPT_AsnDecodeSequence(items,
2659              sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2660              NULL, noticeRef, &bytesNeeded, pcbDecoded,
2661              noticeRef->pszOrganization);
2662         }
2663     }
2664     TRACE("returning %d\n", ret);
2665     return ret;
2666 }
2667
2668 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2669  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2670  DWORD *pcbDecoded)
2671 {
2672     BOOL ret = TRUE;
2673     DWORD dataLen;
2674
2675     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2676     {
2677         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2678         DWORD bytesNeeded = sizeof(LPWSTR);
2679
2680         switch (pbEncoded[0])
2681         {
2682         case ASN_NUMERICSTRING:
2683             if (dataLen)
2684                 bytesNeeded += (dataLen + 1) * 2;
2685             break;
2686         case ASN_PRINTABLESTRING:
2687             if (dataLen)
2688                 bytesNeeded += (dataLen + 1) * 2;
2689             break;
2690         case ASN_IA5STRING:
2691             if (dataLen)
2692                 bytesNeeded += (dataLen + 1) * 2;
2693             break;
2694         case ASN_T61STRING:
2695             if (dataLen)
2696                 bytesNeeded += (dataLen + 1) * 2;
2697             break;
2698         case ASN_VIDEOTEXSTRING:
2699             if (dataLen)
2700                 bytesNeeded += (dataLen + 1) * 2;
2701             break;
2702         case ASN_GRAPHICSTRING:
2703             if (dataLen)
2704                 bytesNeeded += (dataLen + 1) * 2;
2705             break;
2706         case ASN_VISIBLESTRING:
2707             if (dataLen)
2708                 bytesNeeded += (dataLen + 1) * 2;
2709             break;
2710         case ASN_GENERALSTRING:
2711             if (dataLen)
2712                 bytesNeeded += (dataLen + 1) * 2;
2713             break;
2714         case ASN_UNIVERSALSTRING:
2715             if (dataLen)
2716                 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2717             break;
2718         case ASN_BMPSTRING:
2719             if (dataLen)
2720                 bytesNeeded += dataLen + sizeof(WCHAR);
2721             break;
2722         case ASN_UTF8STRING:
2723             if (dataLen)
2724                 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2725                  (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2726             break;
2727         default:
2728             SetLastError(CRYPT_E_ASN1_BADTAG);
2729             return FALSE;
2730         }
2731
2732         if (pcbDecoded)
2733             *pcbDecoded = 1 + lenBytes + dataLen;
2734         if (!pvStructInfo)
2735             *pcbStructInfo = bytesNeeded;
2736         else if (*pcbStructInfo < bytesNeeded)
2737         {
2738             *pcbStructInfo = bytesNeeded;
2739             SetLastError(ERROR_MORE_DATA);
2740             ret = FALSE;
2741         }
2742         else
2743         {
2744             LPWSTR *pStr = pvStructInfo;
2745
2746             *pcbStructInfo = bytesNeeded;
2747             if (dataLen)
2748             {
2749                 DWORD i;
2750                 LPWSTR str = *(LPWSTR *)pStr;
2751
2752                 assert(str);
2753                 switch (pbEncoded[0])
2754                 {
2755                 case ASN_NUMERICSTRING:
2756                 case ASN_PRINTABLESTRING:
2757                 case ASN_IA5STRING:
2758                 case ASN_T61STRING:
2759                 case ASN_VIDEOTEXSTRING:
2760                 case ASN_GRAPHICSTRING:
2761                 case ASN_VISIBLESTRING:
2762                 case ASN_GENERALSTRING:
2763                     for (i = 0; i < dataLen; i++)
2764                         str[i] = pbEncoded[1 + lenBytes + i];
2765                     str[i] = 0;
2766                     break;
2767                 case ASN_UNIVERSALSTRING:
2768                     for (i = 0; i < dataLen / 4; i++)
2769                         str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2770                          | pbEncoded[1 + lenBytes + 2 * i + 3];
2771                     str[i] = 0;
2772                     break;
2773                 case ASN_BMPSTRING:
2774                     for (i = 0; i < dataLen / 2; i++)
2775                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2776                          pbEncoded[1 + lenBytes + 2 * i + 1];
2777                     str[i] = 0;
2778                     break;
2779                 case ASN_UTF8STRING:
2780                 {
2781                     int len = MultiByteToWideChar(CP_UTF8, 0,
2782                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2783                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2784                     str[len] = 0;
2785                     break;
2786                 }
2787                 }
2788             }
2789             else
2790                 *pStr = NULL;
2791         }
2792     }
2793     return ret;
2794 }
2795
2796 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2797  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2798  DWORD *pcbStructInfo, DWORD *pcbDecoded)
2799 {
2800     BOOL ret;
2801     struct AsnDecodeSequenceItem items[] = {
2802      { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2803        pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2804        sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2805        offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2806      { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2807        CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2808        offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2809     };
2810     PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2811
2812     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2813      pvStructInfo, *pcbStructInfo);
2814
2815     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2816      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2817      pcbDecoded, notice ? notice->pNoticeReference : NULL);
2818     TRACE("returning %d\n", ret);
2819     return ret;
2820 }
2821
2822 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2823  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2824  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2825  void *pvStructInfo, DWORD *pcbStructInfo)
2826 {
2827     BOOL ret = FALSE;
2828
2829     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2830      pDecodePara, pvStructInfo, *pcbStructInfo);
2831
2832     __TRY
2833     {
2834         DWORD bytesNeeded;
2835
2836         ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2837          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2838          NULL);
2839         if (ret)
2840         {
2841             if (!pvStructInfo)
2842                 *pcbStructInfo = bytesNeeded;
2843             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2844              pvStructInfo, pcbStructInfo, bytesNeeded)))
2845             {
2846                 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2847
2848                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2849                     pvStructInfo = *(BYTE **)pvStructInfo;
2850                 notice = pvStructInfo;
2851                 notice->pNoticeReference =
2852                  (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2853                  ((BYTE *)pvStructInfo +
2854                  sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2855                 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2856                  pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2857                  pvStructInfo, &bytesNeeded, NULL);
2858             }
2859         }
2860     }
2861     __EXCEPT_PAGE_FAULT
2862     {
2863         SetLastError(STATUS_ACCESS_VIOLATION);
2864     }
2865     __ENDTRY
2866     TRACE("returning %d\n", ret);
2867     return ret;
2868 }
2869
2870 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2871  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2872  DWORD *pcbDecoded)
2873 {
2874     BOOL ret;
2875     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2876      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2877     DWORD bytesNeeded;
2878
2879     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2880      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2881
2882     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2883      NULL, NULL, &bytesNeeded, pcbDecoded)))
2884     {
2885         bytesNeeded += FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue);
2886         if (!pvStructInfo)
2887             *pcbStructInfo = bytesNeeded;
2888         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
2889          pcbStructInfo, bytesNeeded)))
2890         {
2891             CRYPT_ATTRIBUTE *attr = (CRYPT_ATTRIBUTE *)((BYTE *)pvStructInfo -
2892              offsetof(CRYPT_ATTRIBUTE, cValue));
2893
2894             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2895              &attr->cValue, attr->rgValue, pcbStructInfo, pcbDecoded);
2896         }
2897     }
2898     return ret;
2899 }
2900
2901 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2902  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2903  DWORD *pcbDecoded)
2904 {
2905     BOOL ret;
2906     struct AsnDecodeSequenceItem items[] = {
2907      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2908        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2909        offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2910      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2911        CRYPT_AsnDecodePKCSAttributeValue,
2912        FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2913        TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2914     };
2915     PCRYPT_ATTRIBUTE attr = pvStructInfo;
2916
2917     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2918      pvStructInfo, *pcbStructInfo);
2919
2920     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2921      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2922      pcbDecoded, attr ? attr->pszObjId : NULL);
2923     TRACE("returning %d\n", ret);
2924     return ret;
2925 }
2926
2927 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2928  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2929  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2930 {
2931     BOOL ret = FALSE;
2932
2933     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2934      pDecodePara, pvStructInfo, *pcbStructInfo);
2935
2936     __TRY
2937     {
2938         DWORD bytesNeeded;
2939
2940         ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2941          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2942         if (ret)
2943         {
2944             if (!pvStructInfo)
2945                 *pcbStructInfo = bytesNeeded;
2946             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2947              pvStructInfo, pcbStructInfo, bytesNeeded)))
2948             {
2949                 PCRYPT_ATTRIBUTE attr;
2950
2951                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2952                     pvStructInfo = *(BYTE **)pvStructInfo;
2953                 attr = pvStructInfo;
2954                 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2955                  sizeof(CRYPT_ATTRIBUTE));
2956                 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2957                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2958                  NULL);
2959             }
2960         }
2961     }
2962     __EXCEPT_PAGE_FAULT
2963     {
2964         SetLastError(STATUS_ACCESS_VIOLATION);
2965     }
2966     __ENDTRY
2967     TRACE("returning %d\n", ret);
2968     return ret;
2969 }
2970
2971 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2972  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2973  DWORD *pcbDecoded)
2974 {
2975     struct AsnArrayDescriptor arrayDesc = { 0,
2976      CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2977      offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2978     PCRYPT_ATTRIBUTES attrs = pvStructInfo;
2979     BOOL ret;
2980
2981     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2982      NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2983      NULL);
2984     return ret;
2985 }
2986
2987 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2988  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2989  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2990 {
2991     BOOL ret = FALSE;
2992
2993     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2994      pDecodePara, pvStructInfo, *pcbStructInfo);
2995
2996     __TRY
2997     {
2998         DWORD bytesNeeded;
2999
3000         if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
3001             SetLastError(CRYPT_E_ASN1_CORRUPT);
3002         else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
3003          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
3004          NULL)))
3005         {
3006             if (!pvStructInfo)
3007                 *pcbStructInfo = bytesNeeded;
3008             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3009              pvStructInfo, pcbStructInfo, bytesNeeded)))
3010             {
3011                 PCRYPT_ATTRIBUTES attrs;
3012
3013                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3014                     pvStructInfo = *(BYTE **)pvStructInfo;
3015                 attrs = pvStructInfo;
3016                 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
3017                  sizeof(CRYPT_ATTRIBUTES));
3018                 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
3019                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3020                  &bytesNeeded, NULL);
3021             }
3022         }
3023     }
3024     __EXCEPT_PAGE_FAULT
3025     {
3026         SetLastError(STATUS_ACCESS_VIOLATION);
3027     }
3028     __ENDTRY
3029     TRACE("returning %d\n", ret);
3030     return ret;
3031 }
3032
3033 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
3034  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3035 {
3036     CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
3037     BOOL ret = TRUE;
3038     struct AsnDecodeSequenceItem items[] = {
3039      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
3040        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3041        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
3042      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
3043        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
3044        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
3045     };
3046
3047     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3048      pvStructInfo, *pcbStructInfo, pcbDecoded);
3049
3050     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3051      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3052      pcbDecoded, algo ? algo->pszObjId : NULL);
3053     if (ret && pvStructInfo)
3054     {
3055         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
3056          debugstr_a(algo->pszObjId));
3057     }
3058     return ret;
3059 }
3060
3061 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
3062  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3063  DWORD *pcbDecoded)
3064 {
3065     BOOL ret = TRUE;
3066     struct AsnDecodeSequenceItem items[] = {
3067      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
3068        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3069        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
3070        Algorithm.pszObjId) },
3071      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
3072        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3073        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
3074     };
3075     PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
3076
3077     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3078      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3079      pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
3080     return ret;
3081 }
3082
3083 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
3084  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3085  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3086 {
3087     BOOL ret = TRUE;
3088
3089     __TRY
3090     {
3091         DWORD bytesNeeded;
3092
3093         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
3094          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3095         {
3096             if (!pvStructInfo)
3097                 *pcbStructInfo = bytesNeeded;
3098             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3099              pvStructInfo, pcbStructInfo, bytesNeeded)))
3100             {
3101                 PCERT_PUBLIC_KEY_INFO info;
3102
3103                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3104                     pvStructInfo = *(BYTE **)pvStructInfo;
3105                 info = pvStructInfo;
3106                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
3107                  sizeof(CERT_PUBLIC_KEY_INFO);
3108                 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
3109                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3110                  &bytesNeeded, NULL);
3111             }
3112         }
3113     }
3114     __EXCEPT_PAGE_FAULT
3115     {
3116         SetLastError(STATUS_ACCESS_VIOLATION);
3117         ret = FALSE;
3118     }
3119     __ENDTRY
3120     return ret;
3121 }
3122
3123 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
3124  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3125 {
3126     BOOL ret;
3127
3128     if (cbEncoded < 3)
3129     {
3130         SetLastError(CRYPT_E_ASN1_CORRUPT);
3131         return FALSE;
3132     }
3133     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
3134     {
3135         SetLastError(CRYPT_E_ASN1_CORRUPT);
3136         return FALSE;
3137     }
3138     if (pbEncoded[1] > 1)
3139     {
3140         SetLastError(CRYPT_E_ASN1_CORRUPT);
3141         return FALSE;
3142     }
3143     if (pcbDecoded)
3144         *pcbDecoded = 3;
3145     if (!pvStructInfo)
3146     {
3147         *pcbStructInfo = sizeof(BOOL);
3148         ret = TRUE;
3149     }
3150     else if (*pcbStructInfo < sizeof(BOOL))
3151     {
3152         *pcbStructInfo = sizeof(BOOL);
3153         SetLastError(ERROR_MORE_DATA);
3154         ret = FALSE;
3155     }
3156     else
3157     {
3158         *pcbStructInfo = sizeof(BOOL);
3159         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
3160         ret = TRUE;
3161     }
3162     TRACE("returning %d (%08x)\n", ret, GetLastError());
3163     return ret;
3164 }
3165
3166 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
3167  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3168 {
3169     PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
3170     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
3171     BOOL ret;
3172
3173     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3174      pvStructInfo, *pcbStructInfo);
3175
3176     if (cbEncoded < 2)
3177     {
3178         SetLastError(CRYPT_E_ASN1_CORRUPT);
3179         return FALSE;
3180     }
3181     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3182     if (1 + lenBytes > cbEncoded)
3183     {
3184         SetLastError(CRYPT_E_ASN1_CORRUPT);
3185         return FALSE;
3186     }
3187     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3188     {
3189         switch (pbEncoded[0] & ASN_TYPE_MASK)
3190         {
3191         case 1: /* rfc822Name */
3192         case 2: /* dNSName */
3193         case 6: /* uniformResourceIdentifier */
3194             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3195             break;
3196         case 4: /* directoryName */
3197         case 7: /* iPAddress */
3198             bytesNeeded += dataLen;
3199             break;
3200         case 8: /* registeredID */
3201             ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3202              &dataLen, NULL);
3203             if (ret)
3204             {
3205                 /* FIXME: ugly, shouldn't need to know internals of OID decode
3206                  * function to use it.
3207                  */
3208                 bytesNeeded += dataLen - sizeof(LPSTR);
3209             }
3210             break;
3211         case 0: /* otherName */
3212             FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3213             SetLastError(CRYPT_E_ASN1_BADTAG);
3214             ret = FALSE;
3215             break;
3216         case 3: /* x400Address, unimplemented */
3217         case 5: /* ediPartyName, unimplemented */
3218             TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3219             SetLastError(CRYPT_E_ASN1_BADTAG);
3220             ret = FALSE;
3221             break;
3222         default:
3223             TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3224             SetLastError(CRYPT_E_ASN1_CORRUPT);
3225             ret = FALSE;
3226         }
3227         if (ret)
3228         {
3229             if (pcbDecoded)
3230                 *pcbDecoded = 1 + lenBytes + dataLen;
3231             if (!entry)
3232                 *pcbStructInfo = bytesNeeded;
3233             else if (*pcbStructInfo < bytesNeeded)
3234             {
3235                 *pcbStructInfo = bytesNeeded;
3236                 SetLastError(ERROR_MORE_DATA);
3237                 ret = FALSE;
3238             }
3239             else
3240             {
3241                 *pcbStructInfo = bytesNeeded;
3242                 /* MS used values one greater than the asn1 ones.. sigh */
3243                 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3244                 switch (pbEncoded[0] & ASN_TYPE_MASK)
3245                 {
3246                 case 1: /* rfc822Name */
3247                 case 2: /* dNSName */
3248                 case 6: /* uniformResourceIdentifier */
3249                 {
3250                     DWORD i;
3251
3252                     for (i = 0; i < dataLen; i++)
3253                         entry->u.pwszURL[i] =
3254                          (WCHAR)pbEncoded[1 + lenBytes + i];
3255                     entry->u.pwszURL[i] = 0;
3256                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3257                      debugstr_w(entry->u.pwszURL));
3258                     break;
3259                 }
3260                 case 4: /* directoryName */
3261                     /* The data are memory-equivalent with the IPAddress case,
3262                      * fall-through
3263                      */
3264                 case 7: /* iPAddress */
3265                     /* The next data pointer is in the pwszURL spot, that is,
3266                      * the first 4 bytes.  Need to move it to the next spot.
3267                      */
3268                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3269                     entry->u.IPAddress.cbData = dataLen;
3270                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3271                      dataLen);
3272                     break;
3273                 case 8: /* registeredID */
3274                     ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3275                      &entry->u.pszRegisteredID, &dataLen, NULL);
3276                     break;
3277                 }
3278             }
3279         }
3280     }
3281     return ret;
3282 }
3283
3284 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3285  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3286  DWORD *pcbDecoded)
3287 {
3288     BOOL ret = TRUE;
3289     struct AsnArrayDescriptor arrayDesc = { 0,
3290      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3291      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3292     PCERT_ALT_NAME_INFO info = pvStructInfo;
3293
3294     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3295      pvStructInfo, *pcbStructInfo, pcbDecoded);
3296
3297     if (info)
3298         TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
3299     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3300      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3301      info ? info->rgAltEntry : NULL);
3302     return ret;
3303 }
3304
3305 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
3306 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
3307  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3308  DWORD *pcbDecoded)
3309 {
3310     BOOL ret;
3311
3312     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3313      pvStructInfo, *pcbStructInfo, pcbDecoded);
3314
3315     /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3316      * place.
3317      */
3318     ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3319      dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3320      pcbDecoded);
3321     if (ret && pvStructInfo)
3322     {
3323         CRYPT_DATA_BLOB *blob = pvStructInfo;
3324
3325         if (blob->cbData)
3326         {
3327             DWORD i;
3328             BYTE temp;
3329
3330             for (i = 0; i < blob->cbData / 2; i++)
3331             {
3332                 temp = blob->pbData[i];
3333                 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3334                 blob->pbData[blob->cbData - i - 1] = temp;
3335             }
3336         }
3337     }
3338     TRACE("returning %d (%08x)\n", ret, GetLastError());
3339     return ret;
3340 }
3341
3342 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3343  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3344  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3345 {
3346     BOOL ret;
3347
3348     __TRY
3349     {
3350         struct AsnDecodeSequenceItem items[] = {
3351          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3352            CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3353            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3354          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3355            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3356            CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3357            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3358          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3359            CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3360            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3361            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3362         };
3363
3364         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3365          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3366          pcbStructInfo, NULL, NULL);
3367     }
3368     __EXCEPT_PAGE_FAULT
3369     {
3370         SetLastError(STATUS_ACCESS_VIOLATION);
3371         ret = FALSE;
3372     }
3373     __ENDTRY
3374     return ret;
3375 }
3376
3377 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3378  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3379  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3380 {
3381     BOOL ret;
3382
3383     __TRY
3384     {
3385         struct AsnDecodeSequenceItem items[] = {
3386          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3387            CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3388            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3389          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3390            offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3391            CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3392            TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3393            AuthorityCertIssuer.rgAltEntry), 0 },
3394          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3395            AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3396            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3397            offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3398            AuthorityCertSerialNumber.pbData), 0 },
3399         };
3400
3401         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3402          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3403          pcbStructInfo, NULL, NULL);
3404     }
3405     __EXCEPT_PAGE_FAULT
3406     {
3407         SetLastError(STATUS_ACCESS_VIOLATION);
3408         ret = FALSE;
3409     }
3410     __ENDTRY
3411     return ret;
3412 }
3413
3414 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3415  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3416  DWORD *pcbDecoded)
3417 {
3418     struct AsnDecodeSequenceItem items[] = {
3419      { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3420        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3421        offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3422      { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3423        CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3424        TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3425     };
3426     CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3427
3428     return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3429      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3430      pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3431 }
3432
3433 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3434  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3435  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3436 {
3437     BOOL ret;
3438
3439     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3440      pDecodePara, pvStructInfo, *pcbStructInfo);
3441
3442     __TRY
3443     {
3444         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3445          CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3446          TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3447
3448         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3449          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3450     }
3451     __EXCEPT_PAGE_FAULT
3452     {
3453         SetLastError(STATUS_ACCESS_VIOLATION);
3454         ret = FALSE;
3455     }
3456     __ENDTRY
3457     return ret;
3458 }
3459
3460 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3461  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3462 {
3463     BOOL ret;
3464     DWORD dataLen;
3465
3466     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3467      pvStructInfo, *pcbStructInfo, pcbDecoded);
3468
3469     /* The caller has already checked the tag, no need to check it again.
3470      * Check the outer length is valid:
3471      */
3472     if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3473     {
3474         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3475         DWORD innerLen;
3476
3477         pbEncoded += 1 + lenBytes;
3478         cbEncoded -= 1 + lenBytes;
3479         if (dataLen == CMSG_INDEFINITE_LENGTH)
3480             cbEncoded -= 2; /* space for 0 TLV */
3481         /* Check the inner length is valid: */
3482         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3483         {
3484             DWORD decodedLen;
3485
3486             ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3487              pvStructInfo, pcbStructInfo, &decodedLen);
3488             if (dataLen == CMSG_INDEFINITE_LENGTH)
3489             {
3490                 if (*(pbEncoded + decodedLen) != 0 ||
3491                  *(pbEncoded + decodedLen + 1) != 0)
3492                 {
3493                     TRACE("expected 0 TLV, got {%02x,%02x}\n",
3494                      *(pbEncoded + decodedLen),
3495                      *(pbEncoded + decodedLen + 1));
3496                     SetLastError(CRYPT_E_ASN1_CORRUPT);
3497                     ret = FALSE;
3498                 }
3499                 else
3500                     decodedLen += 2;
3501             }
3502             if (ret && pcbDecoded)
3503             {
3504                 *pcbDecoded = 1 + lenBytes + decodedLen;
3505                 TRACE("decoded %d bytes\n", *pcbDecoded);
3506             }
3507         }
3508     }
3509     return ret;
3510 }
3511
3512 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3513  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3514  DWORD *pcbDecoded)
3515 {
3516     CRYPT_CONTENT_INFO *info = pvStructInfo;
3517     struct AsnDecodeSequenceItem items[] = {
3518      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3519        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3520        offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3521      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3522        offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3523        sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3524        offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3525     };
3526     BOOL ret;
3527
3528     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3529      pvStructInfo, *pcbStructInfo, pcbDecoded);
3530
3531     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3532      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3533      pcbDecoded, info ? info->pszObjId : NULL);
3534     return ret;
3535 }
3536
3537 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3538  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3539  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3540 {
3541     BOOL ret = FALSE;
3542
3543     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3544      pDecodePara, pvStructInfo, *pcbStructInfo);
3545
3546     __TRY
3547     {
3548         ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3549          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3550         if (ret && pvStructInfo)
3551         {
3552             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3553              pcbStructInfo, *pcbStructInfo);
3554             if (ret)
3555             {
3556                 CRYPT_CONTENT_INFO *info;
3557
3558                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3559                     pvStructInfo = *(BYTE **)pvStructInfo;
3560                 info = pvStructInfo;
3561                 info->pszObjId = (LPSTR)((BYTE *)info +
3562                  sizeof(CRYPT_CONTENT_INFO));
3563                 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3564                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3565                  pcbStructInfo, NULL);
3566             }
3567         }
3568     }
3569     __EXCEPT_PAGE_FAULT
3570     {
3571         SetLastError(STATUS_ACCESS_VIOLATION);
3572     }
3573     __ENDTRY
3574     return ret;
3575 }
3576
3577 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3578  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3579  CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3580 {
3581     BOOL ret;
3582     struct AsnDecodeSequenceItem items[] = {
3583      { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3584        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3585      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3586        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3587        FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3588        0 },
3589      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3590        CRYPT_AsnDecodePKCSContentInfoInternal,
3591        sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3592        ContentInfo.pszObjId), 0 },
3593      { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3594        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3595        offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3596     };
3597
3598     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3599      pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3600      NULL, NULL);
3601     return ret;
3602 }
3603
3604 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3605  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3606  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3607 {
3608     BOOL ret = TRUE;
3609
3610     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3611      pDecodePara, pvStructInfo, *pcbStructInfo);
3612
3613     __TRY
3614     {
3615         DWORD bytesNeeded;
3616
3617         if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3618          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3619         {
3620             if (!pvStructInfo)
3621                 *pcbStructInfo = bytesNeeded;
3622             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3623              pvStructInfo, pcbStructInfo, bytesNeeded)))
3624             {
3625                 CERT_ALT_NAME_INFO *name;
3626
3627                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3628                     pvStructInfo = *(BYTE **)pvStructInfo;
3629                 name = pvStructInfo;
3630                 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3631                  ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3632                 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3633                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3634                  &bytesNeeded, NULL);
3635             }
3636         }
3637     }
3638     __EXCEPT_PAGE_FAULT
3639     {
3640         SetLastError(STATUS_ACCESS_VIOLATION);
3641         ret = FALSE;
3642     }
3643     __ENDTRY
3644     return ret;
3645 }
3646
3647 struct PATH_LEN_CONSTRAINT
3648 {
3649     BOOL  fPathLenConstraint;
3650     DWORD dwPathLenConstraint;
3651 };
3652
3653 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3654  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3655  DWORD *pcbDecoded)
3656 {
3657     BOOL ret = TRUE;
3658     DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3659
3660     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3661      pvStructInfo, *pcbStructInfo, pcbDecoded);
3662
3663     if (!pvStructInfo)
3664     {
3665         ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3666          &size, pcbDecoded);
3667         *pcbStructInfo = bytesNeeded;
3668     }
3669     else if (*pcbStructInfo < bytesNeeded)
3670     {
3671         SetLastError(ERROR_MORE_DATA);
3672         *pcbStructInfo = bytesNeeded;
3673         ret = FALSE;
3674     }
3675     else
3676     {
3677         struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3678
3679         *pcbStructInfo = bytesNeeded;
3680         size = sizeof(constraint->dwPathLenConstraint);
3681         ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3682          &constraint->dwPathLenConstraint, &size, pcbDecoded);
3683         if (ret)
3684             constraint->fPathLenConstraint = TRUE;
3685         TRACE("got an int, dwPathLenConstraint is %d\n",
3686          constraint->dwPathLenConstraint);
3687     }
3688     TRACE("returning %d (%08x)\n", ret, GetLastError());
3689     return ret;
3690 }
3691
3692 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3693  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3694  DWORD *pcbDecoded)
3695 {
3696     BOOL ret;
3697     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3698      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3699      offsetof(CERT_NAME_BLOB, pbData) };
3700     struct GenericArray *entries = pvStructInfo;
3701
3702     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3703      pvStructInfo, *pcbStructInfo, pcbDecoded);
3704
3705     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3706      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3707      entries ? entries->rgItems : NULL);
3708     TRACE("Returning %d (%08x)\n", ret, GetLastError());
3709     return ret;
3710 }
3711
3712 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3713  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3714  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3715 {
3716     BOOL ret;
3717
3718     __TRY
3719     {
3720         struct AsnDecodeSequenceItem items[] = {
3721          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3722            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
3723            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3724          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3725            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3726            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3727          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3728            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3729            sizeof(struct GenericArray), TRUE, TRUE,
3730            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3731         };
3732
3733         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3734          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3735          pcbStructInfo, NULL, NULL);
3736     }
3737     __EXCEPT_PAGE_FAULT
3738     {
3739         SetLastError(STATUS_ACCESS_VIOLATION);
3740         ret = FALSE;
3741     }
3742     __ENDTRY
3743     return ret;
3744 }
3745
3746 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3747  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3748  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3749 {
3750     BOOL ret;
3751
3752     __TRY
3753     {
3754         struct AsnDecodeSequenceItem items[] = {
3755          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3756            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3757          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3758            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3759            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3760         };
3761
3762         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3763          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3764          pcbStructInfo, NULL, NULL);
3765     }
3766     __EXCEPT_PAGE_FAULT
3767     {
3768         SetLastError(STATUS_ACCESS_VIOLATION);
3769         ret = FALSE;
3770     }
3771     __ENDTRY
3772     return ret;
3773 }
3774
3775 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3776  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3777  DWORD *pcbDecoded)
3778 {
3779     struct AsnDecodeSequenceItem items[] = {
3780      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3781        pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3782        FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3783        0 },
3784      { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3785        CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3786        offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3787     };
3788     BOOL ret;
3789     CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3790
3791     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3792      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3793
3794     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3795      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3796      pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3797     return ret;
3798 }
3799
3800 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3801  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3802  DWORD *pcbDecoded)
3803 {
3804     BOOL ret;
3805     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3806      CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3807      offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3808     struct GenericArray *entries = pvStructInfo;
3809
3810     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3811      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3812
3813     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3814      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3815      entries ? entries->rgItems : NULL);
3816     TRACE("Returning %d (%08x)\n", ret, GetLastError());
3817     return ret;
3818 }
3819
3820 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3821  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3822 {
3823     struct AsnDecodeSequenceItem items[] = {
3824      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3825        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3826        offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3827      { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3828        CRYPT_AsnDecodePolicyQualifiers, sizeof(struct GenericArray), TRUE,
3829        TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3830     };
3831     CERT_POLICY_INFO *info = pvStructInfo;
3832     BOOL ret;
3833
3834     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3835      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3836
3837     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3838      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3839      pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3840     return ret;
3841 }
3842
3843 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3844  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3845  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3846 {
3847     BOOL ret = FALSE;
3848
3849     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3850      pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3851
3852     __TRY
3853     {
3854         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3855          CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3856          offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3857
3858         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3859          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3860     }
3861     __EXCEPT_PAGE_FAULT
3862     {
3863         SetLastError(STATUS_ACCESS_VIOLATION);
3864     }
3865     __ENDTRY
3866     return ret;
3867 }
3868
3869 #define RSA1_MAGIC 0x31415352
3870
3871 struct DECODED_RSA_PUB_KEY
3872 {
3873     DWORD              pubexp;
3874     CRYPT_INTEGER_BLOB modulus;
3875 };
3876
3877 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3878  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3879  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3880 {
3881     BOOL ret;
3882
3883     __TRY
3884     {
3885         struct AsnDecodeSequenceItem items[] = {
3886          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3887            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3888            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3889            0 },
3890          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3891            CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3892         };
3893         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3894         DWORD size = 0;
3895
3896         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3897          pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3898          &size, NULL, NULL);
3899         if (ret)
3900         {
3901             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3902              decodedKey->modulus.cbData;
3903
3904             if (!pvStructInfo)
3905             {
3906                 *pcbStructInfo = bytesNeeded;
3907                 ret = TRUE;
3908             }
3909             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3910              pvStructInfo, pcbStructInfo, bytesNeeded)))
3911             {
3912                 BLOBHEADER *hdr;
3913                 RSAPUBKEY *rsaPubKey;
3914
3915                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3916                     pvStructInfo = *(BYTE **)pvStructInfo;
3917                 hdr = pvStructInfo;
3918                 hdr->bType = PUBLICKEYBLOB;
3919                 hdr->bVersion = CUR_BLOB_VERSION;
3920                 hdr->reserved = 0;
3921                 hdr->aiKeyAlg = CALG_RSA_KEYX;
3922                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3923                  sizeof(BLOBHEADER));
3924                 rsaPubKey->magic = RSA1_MAGIC;
3925                 rsaPubKey->pubexp = decodedKey->pubexp;
3926                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3927                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3928                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3929                  decodedKey->modulus.cbData);
3930             }
3931             LocalFree(decodedKey);
3932         }
3933     }
3934     __EXCEPT_PAGE_FAULT
3935     {
3936         SetLastError(STATUS_ACCESS_VIOLATION);
3937         ret = FALSE;
3938     }
3939     __ENDTRY
3940     return ret;
3941 }
3942
3943 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3944  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3945  DWORD *pcbDecoded)
3946 {
3947     BOOL ret;
3948     DWORD bytesNeeded, dataLen;
3949
3950     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3951      pvStructInfo, *pcbStructInfo, pcbDecoded);
3952
3953     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3954     {
3955         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3956
3957         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3958             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3959         else
3960             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3961         if (pcbDecoded)
3962             *pcbDecoded = 1 + lenBytes + dataLen;
3963         if (!pvStructInfo)
3964             *pcbStructInfo = bytesNeeded;
3965         else if (*pcbStructInfo < bytesNeeded)
3966         {
3967             SetLastError(ERROR_MORE_DATA);
3968             *pcbStructInfo = bytesNeeded;
3969             ret = FALSE;
3970         }
3971         else
3972         {
3973             CRYPT_DATA_BLOB *blob;
3974
3975             *pcbStructInfo = bytesNeeded;
3976             blob = pvStructInfo;
3977             blob->cbData = dataLen;
3978             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3979                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3980             else
3981             {
3982                 assert(blob->pbData);
3983                 if (blob->cbData)
3984                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3985                      blob->cbData);
3986             }
3987         }
3988     }
3989     return ret;
3990 }
3991
3992 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3993  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3994  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3995 {
3996     BOOL ret;
3997
3998     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3999      pDecodePara, pvStructInfo, *pcbStructInfo);
4000
4001     __TRY
4002     {
4003         DWORD bytesNeeded;
4004
4005         if (!cbEncoded)
4006         {
4007             SetLastError(CRYPT_E_ASN1_CORRUPT);
4008             ret = FALSE;
4009         }
4010         else if (pbEncoded[0] != ASN_OCTETSTRING)
4011         {
4012             SetLastError(CRYPT_E_ASN1_BADTAG);
4013             ret = FALSE;
4014         }
4015         else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4016          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4017         {
4018             if (!pvStructInfo)
4019                 *pcbStructInfo = bytesNeeded;
4020             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4021              pvStructInfo, pcbStructInfo, bytesNeeded)))
4022             {
4023                 CRYPT_DATA_BLOB *blob;
4024
4025                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4026                     pvStructInfo = *(BYTE **)pvStructInfo;
4027                 blob = pvStructInfo;
4028                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4029                 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4030                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4031                  &bytesNeeded, NULL);
4032             }
4033         }
4034     }
4035     __EXCEPT_PAGE_FAULT
4036     {
4037         SetLastError(STATUS_ACCESS_VIOLATION);
4038         ret = FALSE;
4039     }
4040     __ENDTRY
4041     return ret;
4042 }
4043
4044 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4045  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4046 {
4047     BOOL ret;
4048     DWORD bytesNeeded, dataLen;
4049     BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4050
4051     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
4052      pvStructInfo, *pcbStructInfo, pcbDecoded);
4053
4054     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4055     {
4056         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4057             bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4058         else
4059             bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4060         if (pcbDecoded)
4061             *pcbDecoded = 1 + lenBytes + dataLen;
4062         if (!pvStructInfo)
4063             *pcbStructInfo = bytesNeeded;
4064         else if (*pcbStructInfo < bytesNeeded)
4065         {
4066             *pcbStructInfo = bytesNeeded;
4067             SetLastError(ERROR_MORE_DATA);
4068             ret = FALSE;
4069         }
4070         else
4071         {
4072             CRYPT_BIT_BLOB *blob;
4073
4074             *pcbStructInfo = bytesNeeded;
4075             blob = pvStructInfo;
4076             blob->cbData = dataLen - 1;
4077             blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4078             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4079             {
4080                 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4081             }
4082             else
4083             {
4084                 assert(blob->pbData);
4085                 if (blob->cbData)
4086                 {
4087                     BYTE mask = 0xff << blob->cUnusedBits;
4088
4089                     memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4090                      blob->cbData);
4091                     blob->pbData[blob->cbData - 1] &= mask;
4092                 }
4093             }
4094         }
4095     }
4096     return ret;
4097 }
4098
4099 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4100  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4101  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4102 {
4103     BOOL ret;
4104
4105     TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4106      pDecodePara, pvStructInfo, pcbStructInfo);
4107
4108     __TRY
4109     {
4110         DWORD bytesNeeded;
4111
4112         if (!cbEncoded)
4113         {
4114             SetLastError(CRYPT_E_ASN1_CORRUPT);
4115             ret = FALSE;
4116         }
4117         else if (pbEncoded[0] != ASN_BITSTRING)
4118         {
4119             SetLastError(CRYPT_E_ASN1_BADTAG);
4120             ret = FALSE;
4121         }
4122         else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4123          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4124         {
4125             if (!pvStructInfo)
4126                 *pcbStructInfo = bytesNeeded;
4127             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4128              pvStructInfo, pcbStructInfo, bytesNeeded)))
4129             {
4130                 CRYPT_BIT_BLOB *blob;
4131
4132                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4133                     pvStructInfo = *(BYTE **)pvStructInfo;
4134                 blob = pvStructInfo;
4135                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4136                 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4137                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4138                  &bytesNeeded, NULL);
4139             }
4140         }
4141     }
4142     __EXCEPT_PAGE_FAULT
4143     {
4144         SetLastError(STATUS_ACCESS_VIOLATION);
4145         ret = FALSE;
4146     }
4147     __ENDTRY
4148     TRACE("returning %d (%08x)\n", ret, GetLastError());
4149     return ret;
4150 }
4151
4152 /* Ignores tag.  Only allows integers 4 bytes or smaller in size. */
4153 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4154  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4155 {
4156     BOOL ret;
4157     BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
4158     CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
4159     DWORD size = sizeof(buf);
4160
4161     blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
4162     ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
4163      &size, pcbDecoded);
4164     if (ret)
4165     {
4166         if (!pvStructInfo)
4167             *pcbStructInfo = sizeof(int);
4168         else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4169         {
4170             int val, i;
4171
4172             if (blob->pbData[blob->cbData - 1] & 0x80)
4173             {
4174                 /* initialize to a negative value to sign-extend */
4175                 val = -1;
4176             }
4177             else
4178                 val = 0;
4179             for (i = 0; i < blob->cbData; i++)
4180             {
4181                 val <<= 8;
4182                 val |= blob->pbData[blob->cbData - i - 1];
4183             }
4184             memcpy(pvStructInfo, &val, sizeof(int));
4185         }
4186     }
4187     else if (GetLastError() == ERROR_MORE_DATA)
4188         SetLastError(CRYPT_E_ASN1_LARGE);
4189     return ret;
4190 }
4191
4192 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4193  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4194  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4195 {
4196     BOOL ret;
4197
4198     __TRY
4199     {
4200         DWORD bytesNeeded;
4201
4202         if (!cbEncoded)
4203         {
4204             SetLastError(CRYPT_E_ASN1_EOD);
4205             ret = FALSE;
4206         }
4207         else if (pbEncoded[0] != ASN_INTEGER)
4208         {
4209             SetLastError(CRYPT_E_ASN1_BADTAG);
4210             ret = FALSE;
4211         }
4212         else
4213             ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4214              dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4215         if (ret)
4216         {
4217             if (!pvStructInfo)
4218                 *pcbStructInfo = bytesNeeded;
4219             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4220              pvStructInfo, pcbStructInfo, bytesNeeded)))
4221             {
4222                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4223                     pvStructInfo = *(BYTE **)pvStructInfo;
4224                 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4225                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4226                  &bytesNeeded, NULL);
4227             }
4228         }
4229     }
4230     __EXCEPT_PAGE_FAULT
4231     {
4232         SetLastError(STATUS_ACCESS_VIOLATION);
4233         ret = FALSE;
4234     }
4235     __ENDTRY
4236     return ret;
4237 }
4238
4239 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4240  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4241  DWORD *pcbDecoded)
4242 {
4243     BOOL ret;
4244     DWORD bytesNeeded, dataLen;
4245
4246     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4247     {
4248         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4249
4250         bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4251         if (pcbDecoded)
4252             *pcbDecoded = 1 + lenBytes + dataLen;
4253         if (!pvStructInfo)
4254             *pcbStructInfo = bytesNeeded;
4255         else if (*pcbStructInfo < bytesNeeded)
4256         {
4257             *pcbStructInfo = bytesNeeded;
4258             SetLastError(ERROR_MORE_DATA);
4259             ret = FALSE;
4260         }
4261         else
4262         {
4263             CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4264
4265             *pcbStructInfo = bytesNeeded;
4266             blob->cbData = dataLen;
4267             assert(blob->pbData);
4268             if (blob->cbData)
4269             {
4270                 DWORD i;
4271
4272                 for (i = 0; i < blob->cbData; i++)
4273                 {
4274                     blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4275                      dataLen - i - 1);
4276                 }
4277             }
4278         }
4279     }
4280     return ret;
4281 }
4282
4283 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4284  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4285  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4286 {
4287     BOOL ret;
4288
4289     __TRY
4290     {
4291         DWORD bytesNeeded;
4292
4293         if (pbEncoded[0] != ASN_INTEGER)
4294         {
4295             SetLastError(CRYPT_E_ASN1_BADTAG);
4296             ret = FALSE;
4297         }
4298         else
4299             ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4300              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4301         if (ret)
4302         {
4303             if (!pvStructInfo)
4304                 *pcbStructInfo = bytesNeeded;
4305             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4306              pvStructInfo, pcbStructInfo, bytesNeeded)))
4307             {
4308                 CRYPT_INTEGER_BLOB *blob;
4309
4310                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4311                     pvStructInfo = *(BYTE **)pvStructInfo;
4312                 blob = pvStructInfo;
4313                 blob->pbData = (BYTE *)pvStructInfo +
4314                  sizeof(CRYPT_INTEGER_BLOB);
4315                 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4316                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4317                  &bytesNeeded, NULL);
4318             }
4319         }
4320     }
4321     __EXCEPT_PAGE_FAULT
4322     {
4323         SetLastError(STATUS_ACCESS_VIOLATION);
4324         ret = FALSE;
4325     }
4326     __ENDTRY
4327     return ret;
4328 }
4329
4330 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4331  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4332  DWORD *pcbDecoded)
4333 {
4334     BOOL ret;
4335
4336     if (pbEncoded[0] == ASN_INTEGER)
4337     {
4338         DWORD bytesNeeded, dataLen;
4339
4340         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4341         {
4342             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4343
4344             if (pcbDecoded)
4345                 *pcbDecoded = 1 + lenBytes + dataLen;
4346             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4347             if (!pvStructInfo)
4348                 *pcbStructInfo = bytesNeeded;
4349             else if (*pcbStructInfo < bytesNeeded)
4350             {
4351                 *pcbStructInfo = bytesNeeded;
4352                 SetLastError(ERROR_MORE_DATA);
4353                 ret = FALSE;
4354             }
4355             else
4356             {
4357                 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4358
4359                 *pcbStructInfo = bytesNeeded;
4360                 blob->cbData = dataLen;
4361                 assert(blob->pbData);
4362                 /* remove leading zero byte if it exists */
4363                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4364                 {
4365                     blob->cbData--;
4366                     blob->pbData++;
4367                 }
4368                 if (blob->cbData)
4369                 {
4370                     DWORD i;
4371
4372                     for (i = 0; i < blob->cbData; i++)
4373                     {
4374                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4375                          dataLen - i - 1);
4376                     }
4377                 }
4378             }
4379         }
4380     }
4381     else
4382     {
4383         SetLastError(CRYPT_E_ASN1_BADTAG);
4384         ret = FALSE;
4385     }
4386     return ret;
4387 }
4388
4389 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4390  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4391  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4392 {
4393     BOOL ret;
4394
4395     __TRY
4396     {
4397         DWORD bytesNeeded;
4398
4399         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4400          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4401         {
4402             if (!pvStructInfo)
4403                 *pcbStructInfo = bytesNeeded;
4404             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4405              pvStructInfo, pcbStructInfo, bytesNeeded)))
4406             {
4407                 CRYPT_INTEGER_BLOB *blob;
4408
4409                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4410                     pvStructInfo = *(BYTE **)pvStructInfo;
4411                 blob = pvStructInfo;
4412                 blob->pbData = (BYTE *)pvStructInfo +
4413                  sizeof(CRYPT_INTEGER_BLOB);
4414                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4415                  cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4416                  &bytesNeeded, NULL);
4417             }
4418         }
4419     }
4420     __EXCEPT_PAGE_FAULT
4421     {
4422         SetLastError(STATUS_ACCESS_VIOLATION);
4423         ret = FALSE;
4424     }
4425     __ENDTRY
4426     return ret;
4427 }
4428
4429 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4430  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4431  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4432 {
4433     BOOL ret;
4434
4435     if (!pvStructInfo)
4436     {
4437         *pcbStructInfo = sizeof(int);
4438         return TRUE;
4439     }
4440     __TRY
4441     {
4442         if (pbEncoded[0] == ASN_ENUMERATED)
4443         {
4444             unsigned int val = 0, i;
4445
4446             if (cbEncoded <= 1)
4447             {
4448                 SetLastError(CRYPT_E_ASN1_EOD);
4449                 ret = FALSE;
4450             }
4451             else if (pbEncoded[1] == 0)
4452             {
4453                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4454                 ret = FALSE;
4455             }
4456             else
4457             {
4458                 /* A little strange looking, but we have to accept a sign byte:
4459                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
4460                  * assuming a small length is okay here, it has to be in short
4461                  * form.
4462                  */
4463                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4464                 {
4465                     SetLastError(CRYPT_E_ASN1_LARGE);
4466                     return FALSE;
4467                 }
4468                 for (i = 0; i < pbEncoded[1]; i++)
4469                 {
4470                     val <<= 8;
4471                     val |= pbEncoded[2 + i];
4472                 }
4473                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4474                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4475                 {
4476                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4477                         pvStructInfo = *(BYTE **)pvStructInfo;
4478                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
4479                 }
4480             }
4481         }
4482         else
4483         {
4484             SetLastError(CRYPT_E_ASN1_BADTAG);
4485             ret = FALSE;
4486         }
4487     }
4488     __EXCEPT_PAGE_FAULT
4489     {
4490         SetLastError(STATUS_ACCESS_VIOLATION);
4491         ret = FALSE;
4492     }
4493     __ENDTRY
4494     return ret;
4495 }
4496
4497 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4498  * if it fails.
4499  */
4500 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4501  do { \
4502     BYTE i; \
4503  \
4504     (word) = 0; \
4505     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4506     { \
4507         if (!isdigit(*(pbEncoded))) \
4508         { \
4509             SetLastError(CRYPT_E_ASN1_CORRUPT); \
4510             ret = FALSE; \
4511         } \
4512         else \
4513         { \
4514             (word) *= 10; \
4515             (word) += *(pbEncoded)++ - '0'; \
4516         } \
4517     } \
4518  } while (0)
4519
4520 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4521  SYSTEMTIME *sysTime)
4522 {
4523     BOOL ret = TRUE;
4524
4525     if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4526     {
4527         WORD hours, minutes = 0;
4528         BYTE sign = *pbEncoded++;
4529
4530         len--;
4531         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4532         if (ret && hours >= 24)
4533         {
4534             SetLastError(CRYPT_E_ASN1_CORRUPT);
4535             ret = FALSE;
4536         }
4537         else if (len >= 2)
4538         {
4539             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4540             if (ret && minutes >= 60)
4541             {
4542                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4543                 ret = FALSE;
4544             }
4545         }
4546         if (ret)
4547         {
4548             if (sign == '+')
4549             {
4550                 sysTime->wHour += hours;
4551                 sysTime->wMinute += minutes;
4552             }
4553             else
4554             {
4555                 if (hours > sysTime->wHour)
4556                 {
4557                     sysTime->wDay--;
4558                     sysTime->wHour = 24 - (hours - sysTime->wHour);
4559                 }
4560                 else
4561                     sysTime->wHour -= hours;
4562                 if (minutes > sysTime->wMinute)
4563                 {
4564                     sysTime->wHour--;
4565                     sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4566                 }
4567                 else
4568                     sysTime->wMinute -= minutes;
4569             }
4570         }
4571     }
4572     return ret;
4573 }
4574
4575 #define MIN_ENCODED_TIME_LENGTH 10
4576
4577 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4578  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4579  DWORD *pcbDecoded)
4580 {
4581     BOOL ret = FALSE;
4582
4583     if (pbEncoded[0] == ASN_UTCTIME)
4584     {
4585         if (cbEncoded <= 1)
4586             SetLastError(CRYPT_E_ASN1_EOD);
4587         else if (pbEncoded[1] > 0x7f)
4588         {
4589             /* long-form date strings really can't be valid */
4590             SetLastError(CRYPT_E_ASN1_CORRUPT);
4591         }
4592         else
4593         {
4594             SYSTEMTIME sysTime = { 0 };
4595             BYTE len = pbEncoded[1];
4596
4597             if (len < MIN_ENCODED_TIME_LENGTH)
4598                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4599             else
4600             {
4601                 ret = TRUE;
4602                 if (pcbDecoded)
4603                     *pcbDecoded = 2 + len;
4604                 pbEncoded += 2;
4605                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4606                 if (sysTime.wYear >= 50)
4607                     sysTime.wYear += 1900;
4608                 else
4609                     sysTime.wYear += 2000;
4610                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4611                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4612                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4613                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4614                 if (ret && len > 0)
4615                 {
4616                     if (len >= 2 && isdigit(*pbEncoded) &&
4617                      isdigit(*(pbEncoded + 1)))
4618                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4619                          sysTime.wSecond);
4620                     else if (isdigit(*pbEncoded))
4621                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4622                          sysTime.wSecond);
4623                     if (ret)
4624                         ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4625                          &sysTime);
4626                 }
4627                 if (ret)
4628                 {
4629                     if (!pvStructInfo)
4630                         *pcbStructInfo = sizeof(FILETIME);
4631                     else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4632                      sizeof(FILETIME))))
4633                         ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4634                 }
4635             }
4636         }
4637     }
4638     else
4639         SetLastError(CRYPT_E_ASN1_BADTAG);
4640     return ret;
4641 }
4642
4643 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4644  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4645  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4646 {
4647     BOOL ret = FALSE;
4648
4649     __TRY
4650     {
4651         DWORD bytesNeeded;
4652
4653         ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4654          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4655         if (ret)
4656         {
4657             if (!pvStructInfo)
4658                 *pcbStructInfo = bytesNeeded;
4659             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4660              pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4661             {
4662                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4663                     pvStructInfo = *(BYTE **)pvStructInfo;
4664                 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4665                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4666                  &bytesNeeded, NULL);
4667             }
4668         }
4669     }
4670     __EXCEPT_PAGE_FAULT
4671     {
4672         SetLastError(STATUS_ACCESS_VIOLATION);
4673     }
4674     __ENDTRY
4675     return ret;
4676 }
4677
4678 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4679  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4680  DWORD *pcbDecoded)
4681 {
4682     BOOL ret = FALSE;
4683
4684     if (pbEncoded[0] == ASN_GENERALTIME)
4685     {
4686         if (cbEncoded <= 1)
4687             SetLastError(CRYPT_E_ASN1_EOD);
4688         else if (pbEncoded[1] > 0x7f)
4689         {
4690             /* long-form date strings really can't be valid */
4691             SetLastError(CRYPT_E_ASN1_CORRUPT);
4692         }
4693         else
4694         {
4695             BYTE len = pbEncoded[1];
4696
4697             if (len < MIN_ENCODED_TIME_LENGTH)
4698                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4699             else
4700             {
4701                 SYSTEMTIME sysTime = { 0 };
4702
4703                 ret = TRUE;
4704                 if (pcbDecoded)
4705                     *pcbDecoded = 2 + len;
4706                 pbEncoded += 2;
4707                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4708                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4709                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4710                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4711                 if (ret && len > 0)
4712                 {
4713                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4714                      sysTime.wMinute);
4715                     if (ret && len > 0)
4716                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4717                          sysTime.wSecond);
4718                     if (ret && len > 0 && (*pbEncoded == '.' ||
4719                      *pbEncoded == ','))
4720                     {
4721                         BYTE digits;
4722
4723                         pbEncoded++;
4724                         len--;
4725                         /* workaround macro weirdness */
4726                         digits = min(len, 3);
4727                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4728                          sysTime.wMilliseconds);
4729                     }
4730                     if (ret)
4731                         ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4732                          &sysTime);
4733                 }
4734                 if (ret)
4735                 {
4736                     if (!pvStructInfo)
4737                         *pcbStructInfo = sizeof(FILETIME);
4738                     else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4739                      sizeof(FILETIME))))
4740                         ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4741                 }
4742             }
4743         }
4744     }
4745     else
4746         SetLastError(CRYPT_E_ASN1_BADTAG);
4747     return ret;
4748 }
4749
4750 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4751  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4752  DWORD *pcbDecoded)
4753 {
4754     BOOL ret;
4755     InternalDecodeFunc decode = NULL;
4756
4757     if (pbEncoded[0] == ASN_UTCTIME)
4758         decode = CRYPT_AsnDecodeUtcTimeInternal;
4759     else if (pbEncoded[0] == ASN_GENERALTIME)
4760         decode = CRYPT_AsnDecodeGeneralizedTime;
4761     if (decode)
4762         ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4763          pcbStructInfo, pcbDecoded);
4764     else
4765     {
4766         SetLastError(CRYPT_E_ASN1_BADTAG);
4767         ret = FALSE;
4768     }
4769     return ret;
4770 }
4771
4772 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4773  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4774  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4775 {
4776     BOOL ret;
4777
4778     __TRY
4779     {
4780         DWORD bytesNeeded;
4781
4782         ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4783          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4784         if (ret)
4785         {
4786             if (!pvStructInfo)
4787                 *pcbStructInfo = bytesNeeded;
4788             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4789              pvStructInfo, pcbStructInfo, bytesNeeded)))
4790             {
4791                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4792                     pvStructInfo = *(BYTE **)pvStructInfo;
4793                 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4794                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4795                  &bytesNeeded, NULL);
4796             }
4797         }
4798     }
4799     __EXCEPT_PAGE_FAULT
4800     {
4801         SetLastError(STATUS_ACCESS_VIOLATION);
4802         ret = FALSE;
4803     }
4804     __ENDTRY
4805     return ret;
4806 }
4807
4808 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4809  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4810  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4811 {
4812     BOOL ret = TRUE;
4813
4814     __TRY
4815     {
4816         if (pbEncoded[0] == ASN_SEQUENCEOF)
4817         {
4818             DWORD bytesNeeded, dataLen, remainingLen, cValue;
4819
4820             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4821             {
4822                 BYTE lenBytes;
4823                 const BYTE *ptr;
4824
4825                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4826                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4827                 cValue = 0;
4828                 ptr = pbEncoded + 1 + lenBytes;
4829                 remainingLen = dataLen;
4830                 while (ret && remainingLen)
4831                 {
4832                     DWORD nextLen;
4833
4834                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4835                     if (ret)
4836                     {
4837                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4838
4839                         remainingLen -= 1 + nextLenBytes + nextLen;
4840                         ptr += 1 + nextLenBytes + nextLen;
4841                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
4842                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4843                             bytesNeeded += 1 + nextLenBytes + nextLen;
4844                         cValue++;
4845                     }
4846                 }
4847                 if (ret)
4848                 {
4849                     CRYPT_SEQUENCE_OF_ANY *seq;
4850                     BYTE *nextPtr;
4851                     DWORD i;
4852
4853                     if (!pvStructInfo)
4854                         *pcbStructInfo = bytesNeeded;
4855                     else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4856                      pvStructInfo, pcbStructInfo, bytesNeeded)))
4857                     {
4858                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4859                             pvStructInfo = *(BYTE **)pvStructInfo;
4860                         seq = pvStructInfo;
4861                         seq->cValue = cValue;
4862                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4863                          sizeof(*seq));
4864                         nextPtr = (BYTE *)seq->rgValue +
4865                          cValue * sizeof(CRYPT_DER_BLOB);
4866                         ptr = pbEncoded + 1 + lenBytes;
4867                         remainingLen = dataLen;
4868                         i = 0;
4869                         while (ret && remainingLen)
4870                         {
4871                             DWORD nextLen;
4872
4873                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4874                             if (ret)
4875                             {
4876                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4877
4878                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
4879                                  nextLen;
4880                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4881                                     seq->rgValue[i].pbData = (BYTE *)ptr;
4882                                 else
4883                                 {
4884                                     seq->rgValue[i].pbData = nextPtr;
4885                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
4886                                      nextLen);
4887                                     nextPtr += 1 + nextLenBytes + nextLen;
4888                                 }
4889                                 remainingLen -= 1 + nextLenBytes + nextLen;
4890                                 ptr += 1 + nextLenBytes + nextLen;
4891                                 i++;
4892                             }
4893                         }
4894                     }
4895                 }
4896             }
4897         }
4898         else
4899         {
4900             SetLastError(CRYPT_E_ASN1_BADTAG);
4901             ret = FALSE;
4902         }
4903     }
4904     __EXCEPT_PAGE_FAULT
4905     {
4906         SetLastError(STATUS_ACCESS_VIOLATION);
4907         ret = FALSE;
4908     }
4909     __ENDTRY
4910     return ret;
4911 }
4912
4913 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4914  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4915  DWORD *pcbDecoded)
4916 {
4917     BOOL ret;
4918
4919     if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4920     {
4921         DWORD bytesNeeded, dataLen;
4922
4923         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4924         {
4925             struct AsnArrayDescriptor arrayDesc = {
4926              ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4927              sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4928              offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4929             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4930             DWORD nameLen;
4931
4932             if (dataLen)
4933             {
4934                 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
4935                  pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4936                  NULL, NULL, &nameLen, NULL);
4937                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
4938             }
4939             else
4940                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4941             if (pcbDecoded)
4942                 *pcbDecoded = 1 + lenBytes + dataLen;
4943             if (!pvStructInfo)
4944                 *pcbStructInfo = bytesNeeded;
4945             else if (*pcbStructInfo < bytesNeeded)
4946             {
4947                 *pcbStructInfo = bytesNeeded;
4948                 SetLastError(ERROR_MORE_DATA);
4949                 ret = FALSE;
4950             }
4951             else
4952             {
4953                 CRL_DIST_POINT_NAME *name = pvStructInfo;
4954
4955                 *pcbStructInfo = bytesNeeded;
4956                 if (dataLen)
4957                 {
4958                     name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4959                     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
4960                      pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4961                      &name->u.FullName.cAltEntry, name->u.FullName.rgAltEntry,
4962                      &nameLen, NULL);
4963                 }
4964                 else
4965                     name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4966             }
4967         }
4968     }
4969     else
4970     {
4971         SetLastError(CRYPT_E_ASN1_BADTAG);
4972         ret = FALSE;
4973     }
4974     return ret;
4975 }
4976
4977 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4978  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4979 {
4980     struct AsnDecodeSequenceItem items[] = {
4981      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4982        DistPointName), CRYPT_AsnDecodeDistPointName,
4983        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4984        DistPointName.u.FullName.rgAltEntry), 0 },
4985      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4986        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4987        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4988      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4989        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4990        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4991     };
4992     CRL_DIST_POINT *point = pvStructInfo;
4993     BOOL ret;
4994
4995     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4996      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4997      pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
4998     return ret;
4999 }
5000
5001 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5002  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5003  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5004 {
5005     BOOL ret;
5006
5007     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5008      pDecodePara, pvStructInfo, *pcbStructInfo);
5009
5010     __TRY
5011     {
5012         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5013          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5014          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5015
5016         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5017          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
5018     }
5019     __EXCEPT_PAGE_FAULT
5020     {
5021         SetLastError(STATUS_ACCESS_VIOLATION);
5022         ret = FALSE;
5023     }
5024     __ENDTRY
5025     return ret;
5026 }
5027
5028 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5029  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5030  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5031 {
5032     BOOL ret;
5033
5034     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5035      pDecodePara, pvStructInfo, *pcbStructInfo);
5036
5037     __TRY
5038     {
5039         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5040          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5041
5042         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5043          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
5044     }
5045     __EXCEPT_PAGE_FAULT
5046     {
5047         SetLastError(STATUS_ACCESS_VIOLATION);
5048         ret = FALSE;
5049     }
5050     __ENDTRY
5051     return ret;
5052 }
5053
5054 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5055  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5056  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5057 {
5058     BOOL ret;
5059
5060     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5061      pDecodePara, pvStructInfo, *pcbStructInfo);
5062
5063     __TRY
5064     {
5065         struct AsnDecodeSequenceItem items[] = {
5066          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5067            DistPointName), CRYPT_AsnDecodeDistPointName,
5068            sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5069            offsetof(CRL_ISSUING_DIST_POINT,
5070            DistPointName.u.FullName.rgAltEntry), 0 },
5071          { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5072            fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5073            FALSE, 0 },
5074          { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5075            fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5076            FALSE, 0 },
5077          { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5078            OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5079            sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5080            OnlySomeReasonFlags.pbData), 0 },
5081          { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5082            fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5083         };
5084
5085         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5086          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5087          pcbStructInfo, NULL, NULL);
5088     }
5089     __EXCEPT_PAGE_FAULT
5090     {
5091         SetLastError(STATUS_ACCESS_VIOLATION);
5092         ret = FALSE;
5093     }
5094     __ENDTRY
5095     return ret;
5096 }
5097
5098 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5099  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5100  DWORD *pcbDecoded)
5101 {
5102     BOOL ret = FALSE;
5103
5104     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5105      pvStructInfo, *pcbStructInfo, pcbDecoded);
5106
5107     if (!cbEncoded)
5108     {
5109         SetLastError(CRYPT_E_ASN1_EOD);
5110         return FALSE;
5111     }
5112     if (pbEncoded[0] != (ASN_CONTEXT | 1))
5113     {
5114         SetLastError(CRYPT_E_ASN1_BADTAG);
5115         return FALSE;
5116     }
5117     /* The BOOL is implicit:  if the integer is present, then it's TRUE */
5118     ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5119      pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
5120      pcbDecoded);
5121     if (ret && pvStructInfo)
5122         *(BOOL *)pvStructInfo = TRUE;
5123     TRACE("returning %d\n", ret);
5124     return ret;
5125 }
5126
5127 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5128  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5129  DWORD *pcbDecoded)
5130 {
5131     BOOL ret;
5132     struct AsnDecodeSequenceItem items[] = {
5133      { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5134        CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5135        offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5136      { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5137        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5138      { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5139        CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
5140        0 },
5141     };
5142     CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5143
5144     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5145      pvStructInfo, *pcbStructInfo, pcbDecoded);
5146
5147     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5148      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5149      pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5150     if (pcbDecoded)
5151     {
5152         TRACE("%d\n", *pcbDecoded);
5153         if (*pcbDecoded < cbEncoded)
5154             TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5155              *(pbEncoded + *pcbDecoded + 1));
5156     }
5157     TRACE("returning %d\n", ret);
5158     return ret;
5159 }
5160
5161 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5162  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5163  DWORD *pcbDecoded)
5164 {
5165     BOOL ret = TRUE;
5166     struct AsnArrayDescriptor arrayDesc = { 0,
5167      CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5168      offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5169     DWORD bytesNeeded;
5170
5171     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5172      pvStructInfo, *pcbStructInfo, pcbDecoded);
5173
5174     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5175      NULL, NULL, &bytesNeeded, pcbDecoded)))
5176     {
5177         bytesNeeded += MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO,
5178          cPermittedSubtree, cExcludedSubtree);
5179         if (!pvStructInfo)
5180             *pcbStructInfo = bytesNeeded;
5181         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5182          pcbStructInfo, bytesNeeded)))
5183         {
5184             CERT_NAME_CONSTRAINTS_INFO *info = (CERT_NAME_CONSTRAINTS_INFO *)
5185              ((BYTE *)pvStructInfo -
5186              offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree));
5187
5188             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5189              &info->cPermittedSubtree, info->rgPermittedSubtree, &bytesNeeded,
5190              pcbDecoded);
5191         }
5192     }
5193     return ret;
5194 }
5195
5196 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5197  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5198  DWORD *pcbDecoded)
5199 {
5200     BOOL ret = TRUE;
5201     struct AsnArrayDescriptor arrayDesc = { 0,
5202      CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5203      offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5204     DWORD bytesNeeded;
5205
5206     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5207      pvStructInfo, *pcbStructInfo, pcbDecoded);
5208
5209     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5210      NULL, NULL, &bytesNeeded, pcbDecoded)))
5211     {
5212         bytesNeeded += FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO,
5213          cExcludedSubtree);
5214         if (!pvStructInfo)
5215             *pcbStructInfo = bytesNeeded;
5216         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5217          pcbStructInfo, bytesNeeded)))
5218         {
5219             CERT_NAME_CONSTRAINTS_INFO *info = (CERT_NAME_CONSTRAINTS_INFO *)
5220              ((BYTE *)pvStructInfo -
5221              offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree));
5222
5223             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5224              &info->cExcludedSubtree, info->rgExcludedSubtree, &bytesNeeded,
5225              pcbDecoded);
5226         }
5227     }
5228     return ret;
5229 }
5230
5231 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5232  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5233  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5234 {
5235     BOOL ret = FALSE;
5236
5237     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5238      pDecodePara, pvStructInfo, *pcbStructInfo);
5239
5240     __TRY
5241     {
5242         struct AsnDecodeSequenceItem items[] = {
5243          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5244            offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5245            CRYPT_AsnDecodePermittedSubtree,
5246            MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5247            cExcludedSubtree), TRUE, TRUE,
5248            offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5249          { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5250            offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5251            CRYPT_AsnDecodeExcludedSubtree,
5252            FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5253            TRUE, TRUE,
5254            offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5255         };
5256
5257         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5258          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5259          pcbStructInfo, NULL, NULL);
5260     }
5261     __EXCEPT_PAGE_FAULT
5262     {
5263         SetLastError(STATUS_ACCESS_VIOLATION);
5264     }
5265     __ENDTRY
5266     return ret;
5267 }
5268
5269 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5270  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5271  DWORD *pcbDecoded)
5272 {
5273     BOOL ret;
5274     struct AsnDecodeSequenceItem items[] = {
5275      { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5276        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5277        Issuer.pbData) },
5278      { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5279        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5280        TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5281     };
5282     CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5283
5284     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5285      pvStructInfo, *pcbStructInfo, pcbDecoded);
5286
5287     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5288      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5289      pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5290     if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5291     {
5292         SetLastError(CRYPT_E_ASN1_CORRUPT);
5293         ret = FALSE;
5294     }
5295     TRACE("returning %d\n", ret);
5296     return ret;
5297 }
5298
5299 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5300  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5301  DWORD *pcbDecoded)
5302 {
5303     CMSG_SIGNER_INFO *info = pvStructInfo;
5304     struct AsnDecodeSequenceItem items[] = {
5305      { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5306        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5307      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5308        CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5309        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5310      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5311        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5312        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5313      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5314        offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5315        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5316        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5317      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5318        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5319        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5320        HashEncryptionAlgorithm.pszObjId), 0 },
5321      { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5322        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5323        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5324      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5325        offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5326        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5327        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5328     };
5329     BOOL ret;
5330
5331     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5332      pvStructInfo, *pcbStructInfo);
5333
5334     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5335      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5336      pcbDecoded, info ? info->Issuer.pbData : NULL);
5337     return ret;
5338 }
5339
5340 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5341  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5342  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5343 {
5344     BOOL ret = FALSE;
5345
5346     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5347      pDecodePara, pvStructInfo, *pcbStructInfo);
5348
5349     __TRY
5350     {
5351         ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5352          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5353         if (ret && pvStructInfo)
5354         {
5355             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5356              pcbStructInfo, *pcbStructInfo);
5357             if (ret)
5358             {
5359                 CMSG_SIGNER_INFO *info;
5360
5361                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5362                     pvStructInfo = *(BYTE **)pvStructInfo;
5363                 info = pvStructInfo;
5364                 info->Issuer.pbData = ((BYTE *)info +
5365                  sizeof(CMSG_SIGNER_INFO));
5366                 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5367                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5368                  pcbStructInfo, NULL);
5369             }
5370         }
5371     }
5372     __EXCEPT_PAGE_FAULT
5373     {
5374         SetLastError(STATUS_ACCESS_VIOLATION);
5375     }
5376     __ENDTRY
5377     TRACE("returning %d\n", ret);
5378     return ret;
5379 }
5380
5381 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5382  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5383  DWORD *pcbDecoded)
5384 {
5385     BOOL ret;
5386     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
5387      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5388     DWORD bytesNeeded;
5389
5390     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5391      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5392
5393     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5394      NULL, NULL, &bytesNeeded, pcbDecoded)))
5395     {
5396         bytesNeeded += MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded);
5397         if (!pvStructInfo)
5398             *pcbStructInfo = bytesNeeded;
5399         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5400          pcbStructInfo, bytesNeeded)))
5401         {
5402             CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5403              ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cCertEncoded));
5404
5405             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5406              &info->cCertEncoded, info->rgCertEncoded, &bytesNeeded,
5407              pcbDecoded);
5408         }
5409     }
5410     return ret;
5411 }
5412
5413 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5414  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5415  DWORD *pcbDecoded)
5416 {
5417     BOOL ret;
5418     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
5419      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5420     DWORD bytesNeeded;
5421
5422     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5423      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5424
5425     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5426      NULL, NULL, &bytesNeeded, pcbDecoded)))
5427     {
5428         bytesNeeded += MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content);
5429         if (!pvStructInfo)
5430             *pcbStructInfo = bytesNeeded;
5431         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5432          pcbStructInfo, bytesNeeded)))
5433         {
5434             CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5435              ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cCrlEncoded));
5436
5437             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5438              &info->cCrlEncoded, info->rgCrlEncoded, &bytesNeeded,
5439              pcbDecoded);
5440         }
5441     }
5442     return ret;
5443 }
5444
5445 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5446  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5447  DWORD *pcbDecoded)
5448 {
5449     CERT_ID *id = pvStructInfo;
5450     BOOL ret = FALSE;
5451
5452     if (*pbEncoded == ASN_SEQUENCEOF)
5453     {
5454         ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5455          id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5456         if (ret)
5457         {
5458             if (id)
5459                 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5460             if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5461                 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5462                  sizeof(CERT_ISSUER_SERIAL_NUMBER);
5463             else
5464                 *pcbStructInfo = sizeof(CERT_ID);
5465         }
5466     }
5467     else if (*pbEncoded == (ASN_CONTEXT | 0))
5468     {
5469         ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5470          id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5471         if (ret)
5472         {
5473             if (id)
5474                 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5475             if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5476                 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5477                  sizeof(CRYPT_DATA_BLOB);
5478             else
5479                 *pcbStructInfo = sizeof(CERT_ID);
5480         }
5481     }
5482     else
5483         SetLastError(CRYPT_E_ASN1_BADTAG);
5484     return ret;
5485 }
5486
5487 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5488  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5489  DWORD *pcbDecoded)
5490 {
5491     CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5492     struct AsnDecodeSequenceItem items[] = {
5493      { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5494        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5495      { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5496        CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5497        offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5498      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5499        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5500        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5501      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5502        offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5503        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5504        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5505      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5506        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5507        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5508        HashEncryptionAlgorithm.pszObjId), 0 },
5509      { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5510        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5511        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5512      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5513        offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5514        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5515        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5516     };
5517     BOOL ret;
5518
5519     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5520      pvStructInfo, *pcbStructInfo);
5521
5522     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5523      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5524      pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5525     return ret;
5526 }
5527
5528 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5529  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5530  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5531 {
5532     BOOL ret = FALSE;
5533
5534     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5535      pDecodePara, pvStructInfo, *pcbStructInfo);
5536
5537     __TRY
5538     {
5539         ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5540          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5541         if (ret && pvStructInfo)
5542         {
5543             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5544              pcbStructInfo, *pcbStructInfo);
5545             if (ret)
5546             {
5547                 CMSG_CMS_SIGNER_INFO *info;
5548
5549                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5550                     pvStructInfo = *(BYTE **)pvStructInfo;
5551                 info = pvStructInfo;
5552                 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5553                  sizeof(CMSG_CMS_SIGNER_INFO));
5554                 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5555                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5556                  pcbStructInfo, NULL);
5557             }
5558         }
5559     }
5560     __EXCEPT_PAGE_FAULT
5561     {
5562         SetLastError(STATUS_ACCESS_VIOLATION);
5563     }
5564     __ENDTRY
5565     TRACE("returning %d\n", ret);
5566     return ret;
5567 }
5568
5569 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5570  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5571 {
5572     BOOL ret;
5573     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5574      CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5575      offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5576     struct GenericArray *array = pvStructInfo;
5577
5578     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5579      pvStructInfo, *pcbStructInfo, pcbDecoded);
5580
5581     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5582      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
5583      array ? array->rgItems : NULL);
5584     return ret;
5585 }
5586
5587 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5588  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5589  CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5590 {
5591     BOOL ret = FALSE;
5592     struct AsnDecodeSequenceItem items[] = {
5593      { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5594        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5595      /* Placeholder for the hash algorithms - redundant with those in the
5596       * signers, so just ignore them.
5597       */
5598      { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5599      { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5600        CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5601        FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5602      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5603        offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5604        MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5605        offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5606      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5607        offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5608        MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5609        offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5610      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5611        CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
5612        offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5613     };
5614
5615     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5616      pDecodePara, signedInfo, *pcbSignedInfo);
5617
5618     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5619      pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5620      NULL, NULL);
5621     TRACE("returning %d\n", ret);
5622     return ret;
5623 }
5624
5625 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5626  LPCSTR lpszStructType)
5627 {
5628     CryptDecodeObjectExFunc decodeFunc = NULL;
5629
5630     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5631      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5632     {
5633         SetLastError(ERROR_FILE_NOT_FOUND);
5634         return NULL;
5635     }
5636     if (!HIWORD(lpszStructType))
5637     {
5638         switch (LOWORD(lpszStructType))
5639         {
5640         case LOWORD(X509_CERT):
5641             decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5642             break;
5643         case LOWORD(X509_CERT_TO_BE_SIGNED):
5644             decodeFunc = CRYPT_AsnDecodeCert;
5645             break;
5646         case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5647             decodeFunc = CRYPT_AsnDecodeCRL;
5648             break;
5649         case LOWORD(X509_EXTENSIONS):
5650             decodeFunc = CRYPT_AsnDecodeExtensions;
5651             break;
5652         case LOWORD(X509_NAME_VALUE):
5653             decodeFunc = CRYPT_AsnDecodeNameValue;
5654             break;
5655         case LOWORD(X509_NAME):
5656             decodeFunc = CRYPT_AsnDecodeName;
5657             break;
5658         case LOWORD(X509_PUBLIC_KEY_INFO):
5659             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5660             break;
5661         case LOWORD(X509_AUTHORITY_KEY_ID):
5662             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5663             break;
5664         case LOWORD(X509_ALTERNATE_NAME):
5665             decodeFunc = CRYPT_AsnDecodeAltName;
5666             break;
5667         case LOWORD(X509_BASIC_CONSTRAINTS):
5668             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5669             break;
5670         case LOWORD(X509_BASIC_CONSTRAINTS2):
5671             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5672             break;
5673         case LOWORD(X509_CERT_POLICIES):
5674             decodeFunc = CRYPT_AsnDecodeCertPolicies;
5675             break;
5676         case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5677             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5678             break;
5679         case LOWORD(X509_UNICODE_NAME):
5680             decodeFunc = CRYPT_AsnDecodeUnicodeName;
5681             break;
5682         case LOWORD(PKCS_ATTRIBUTE):
5683             decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5684             break;
5685         case LOWORD(X509_UNICODE_NAME_VALUE):
5686             decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5687             break;
5688         case LOWORD(X509_OCTET_STRING):
5689             decodeFunc = CRYPT_AsnDecodeOctets;
5690             break;
5691         case LOWORD(X509_BITS):
5692         case LOWORD(X509_KEY_USAGE):
5693             decodeFunc = CRYPT_AsnDecodeBits;
5694             break;
5695         case LOWORD(X509_INTEGER):
5696             decodeFunc = CRYPT_AsnDecodeInt;
5697             break;
5698         case LOWORD(X509_MULTI_BYTE_INTEGER):
5699             decodeFunc = CRYPT_AsnDecodeInteger;
5700             break;
5701         case LOWORD(X509_MULTI_BYTE_UINT):
5702             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5703             break;
5704         case LOWORD(X509_ENUMERATED):
5705             decodeFunc = CRYPT_AsnDecodeEnumerated;
5706             break;
5707         case LOWORD(X509_CHOICE_OF_TIME):
5708             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5709             break;
5710         case LOWORD(X509_AUTHORITY_KEY_ID2):
5711             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5712             break;
5713         case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5714             decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5715             break;
5716         case LOWORD(PKCS_CONTENT_INFO):
5717             decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5718             break;
5719         case LOWORD(X509_SEQUENCE_OF_ANY):
5720             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5721             break;
5722         case LOWORD(PKCS_UTC_TIME):
5723             decodeFunc = CRYPT_AsnDecodeUtcTime;
5724             break;
5725         case LOWORD(X509_CRL_DIST_POINTS):
5726             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5727             break;
5728         case LOWORD(X509_ENHANCED_KEY_USAGE):
5729             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5730             break;
5731         case LOWORD(PKCS_CTL):
5732             decodeFunc = CRYPT_AsnDecodeCTL;
5733             break;
5734         case LOWORD(PKCS_SMIME_CAPABILITIES):
5735             decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5736             break;
5737         case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5738             decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5739             break;
5740         case LOWORD(PKCS_ATTRIBUTES):
5741             decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5742             break;
5743         case LOWORD(X509_ISSUING_DIST_POINT):
5744             decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5745             break;
5746         case LOWORD(X509_NAME_CONSTRAINTS):
5747             decodeFunc = CRYPT_AsnDecodeNameConstraints;
5748             break;
5749         case LOWORD(PKCS7_SIGNER_INFO):
5750             decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5751             break;
5752         case LOWORD(CMS_SIGNER_INFO):
5753             decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5754             break;
5755         }
5756     }
5757     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5758         decodeFunc = CRYPT_AsnDecodeExtensions;
5759     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5760         decodeFunc = CRYPT_AsnDecodeUtcTime;
5761     else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5762         decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5763     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5764         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5765     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5766         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5767     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5768         decodeFunc = CRYPT_AsnDecodeEnumerated;
5769     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5770         decodeFunc = CRYPT_AsnDecodeBits;
5771     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5772         decodeFunc = CRYPT_AsnDecodeOctets;
5773     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5774         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5775     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5776         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5777     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5778         decodeFunc = CRYPT_AsnDecodeAltName;
5779     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5780         decodeFunc = CRYPT_AsnDecodeAltName;
5781     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5782         decodeFunc = CRYPT_AsnDecodeAltName;
5783     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5784         decodeFunc = CRYPT_AsnDecodeAltName;
5785     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5786         decodeFunc = CRYPT_AsnDecodeAltName;
5787     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5788         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5789     else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5790         decodeFunc = CRYPT_AsnDecodeCertPolicies;
5791     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5792         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5793     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5794         decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5795     else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5796         decodeFunc = CRYPT_AsnDecodeNameConstraints;
5797     else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5798         decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5799     else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5800         decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5801     else if (!strcmp(lpszStructType, szOID_CTL))
5802         decodeFunc = CRYPT_AsnDecodeCTL;
5803     return decodeFunc;
5804 }
5805
5806 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5807  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5808 {
5809     static HCRYPTOIDFUNCSET set = NULL;
5810     CryptDecodeObjectFunc decodeFunc = NULL;
5811
5812     if (!set)
5813         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5814     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5815      (void **)&decodeFunc, hFunc);
5816     return decodeFunc;
5817 }
5818
5819 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5820  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5821 {
5822     static HCRYPTOIDFUNCSET set = NULL;
5823     CryptDecodeObjectExFunc decodeFunc = NULL;
5824
5825     if (!set)
5826         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5827     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5828      (void **)&decodeFunc, hFunc);
5829     return decodeFunc;
5830 }
5831
5832 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5833  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5834  DWORD *pcbStructInfo)
5835 {
5836     BOOL ret = FALSE;
5837     CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5838     CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5839     HCRYPTOIDFUNCADDR hFunc = NULL;
5840
5841     TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5842      debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5843      pvStructInfo, pcbStructInfo);
5844
5845     if (!pvStructInfo && !pcbStructInfo)
5846     {
5847         SetLastError(ERROR_INVALID_PARAMETER);
5848         return FALSE;
5849     }
5850     if (cbEncoded > MAX_ENCODED_LEN)
5851     {
5852         SetLastError(CRYPT_E_ASN1_LARGE);
5853         return FALSE;
5854     }
5855
5856     if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5857      lpszStructType)))
5858     {
5859         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5860          debugstr_a(lpszStructType));
5861         pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5862          lpszStructType, &hFunc);
5863         if (!pCryptDecodeObject)
5864             pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5865              lpszStructType, &hFunc);
5866     }
5867     if (pCryptDecodeObject)
5868         ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5869          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5870     else if (pCryptDecodeObjectEx)
5871         ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5872          pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5873          pvStructInfo, pcbStructInfo);
5874     if (hFunc)
5875         CryptFreeOIDFunctionAddress(hFunc, 0);
5876     TRACE_(crypt)("returning %d\n", ret);
5877     return ret;
5878 }
5879
5880 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5881  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5882  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5883 {
5884     BOOL ret = FALSE;
5885     CryptDecodeObjectExFunc decodeFunc;
5886     HCRYPTOIDFUNCADDR hFunc = NULL;
5887
5888     TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5889      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5890      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5891
5892     if (!pvStructInfo && !pcbStructInfo)
5893     {
5894         SetLastError(ERROR_INVALID_PARAMETER);
5895         return FALSE;
5896     }
5897     if (cbEncoded > MAX_ENCODED_LEN)
5898     {
5899         SetLastError(CRYPT_E_ASN1_LARGE);
5900         return FALSE;
5901     }
5902
5903     SetLastError(NOERROR);
5904     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5905         *(BYTE **)pvStructInfo = NULL;
5906     decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5907     if (!decodeFunc)
5908     {
5909         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5910          debugstr_a(lpszStructType));
5911         decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5912          &hFunc);
5913     }
5914     if (decodeFunc)
5915         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5916          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5917     else
5918     {
5919         CryptDecodeObjectFunc pCryptDecodeObject =
5920          CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5921
5922         /* Try CryptDecodeObject function.  Don't call CryptDecodeObject
5923          * directly, as that could cause an infinite loop.
5924          */
5925         if (pCryptDecodeObject)
5926         {
5927             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5928             {
5929                 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5930                  pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5931                 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5932                  pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5933                     ret = pCryptDecodeObject(dwCertEncodingType,
5934                      lpszStructType, pbEncoded, cbEncoded, dwFlags,
5935                      *(BYTE **)pvStructInfo, pcbStructInfo);
5936             }
5937             else
5938                 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5939                  pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5940         }
5941     }
5942     if (hFunc)
5943         CryptFreeOIDFunctionAddress(hFunc, 0);
5944     TRACE_(crypt)("returning %d\n", ret);
5945     return ret;
5946 }
5947
5948 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
5949 {
5950     BOOL ret;
5951
5952     TRACE_(crypt)("(%p)\n", pPFX);
5953
5954     /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
5955      * version integer of length 1 (3 encoded byes) and at least one other
5956      * datum (two encoded bytes), plus at least two bytes for the outer
5957      * sequence.  Thus, even an empty PFX blob is at least 7 bytes in length.
5958      */
5959     if (pPFX->cbData < 7)
5960         ret = FALSE;
5961     else if (pPFX->pbData[0] == ASN_SEQUENCE)
5962     {
5963         DWORD len;
5964
5965         if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
5966         {
5967             BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
5968
5969             /* Need at least three bytes for the integer version */
5970             if (pPFX->cbData < 1 + lenLen + 3)
5971                 ret = FALSE;
5972             else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
5973              pPFX->pbData[1 + lenLen + 1] != 1 ||          /* Definite length */
5974              pPFX->pbData[1 + lenLen + 2] != 3)            /* PFX version */
5975                 ret = FALSE;
5976         }
5977     }
5978     else
5979         ret = FALSE;
5980     return ret;
5981 }
5982
5983 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
5984  DWORD dwFlags)
5985 {
5986     FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
5987     return NULL;
5988 }