crypt32: Explicitly pass array pointer when decoding CTL entries rather than assuming...
[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     DWORD bytesNeeded;
2396
2397     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2398      pvStructInfo, *pcbStructInfo, pcbDecoded);
2399
2400     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2401      NULL, NULL, &bytesNeeded, pcbDecoded);
2402     if (ret)
2403     {
2404         /* The size expected by the caller includes the combination of
2405          * CTL_INFO's cCTLEntry and rgCTLEntry, in addition to the size of
2406          * all the decoded items.  CRYPT_AsnDecodeArrayNoAlloc only returns
2407          * the size of the decoded items, so add the size of cCTLEntry and
2408          * rgCTLEntry.
2409          */
2410         bytesNeeded += MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension);
2411         if (!pvStructInfo)
2412             *pcbStructInfo = bytesNeeded;
2413         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
2414          pcbStructInfo, bytesNeeded)))
2415         {
2416             CTL_INFO *info;
2417
2418             info = (CTL_INFO *)((BYTE *)pvStructInfo -
2419              offsetof(CTL_INFO, cCTLEntry));
2420             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
2421              cbEncoded, &info->cCTLEntry, info->rgCTLEntry, &bytesNeeded,
2422              pcbDecoded);
2423         }
2424     }
2425     return ret;
2426 }
2427
2428 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2429  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2430  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2431 {
2432     BOOL ret = FALSE;
2433
2434     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2435      pDecodePara, pvStructInfo, *pcbStructInfo);
2436
2437     __TRY
2438     {
2439         struct AsnDecodeSequenceItem items[] = {
2440          { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2441            CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2442          { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2443            CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2444            offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2445          { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2446            CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2447            TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2448          { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2449            CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2450            TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2451          { 0, offsetof(CTL_INFO, ThisUpdate),
2452            CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2453            0 },
2454          { 0, offsetof(CTL_INFO, NextUpdate),
2455            CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2456            0 },
2457          { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2458            CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2459            FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2460          { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2461            CRYPT_AsnDecodeCTLEntries,
2462            MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2463            TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2464          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2465            CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2466            offsetof(CTL_INFO, rgExtension), 0 },
2467         };
2468
2469         TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2470          pDecodePara, pvStructInfo, *pcbStructInfo);
2471
2472         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2473          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2474          pcbStructInfo, NULL, NULL);
2475     }
2476     __EXCEPT_PAGE_FAULT
2477     {
2478         SetLastError(STATUS_ACCESS_VIOLATION);
2479     }
2480     __ENDTRY
2481     return ret;
2482 }
2483
2484 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2485  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2486  DWORD *pcbDecoded)
2487 {
2488     BOOL ret;
2489     struct AsnDecodeSequenceItem items[] = {
2490      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2491        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2492        offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2493      { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2494        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2495        offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2496     };
2497     PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2498
2499     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2500      pvStructInfo, *pcbStructInfo);
2501
2502     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2503      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2504      pcbDecoded, capability ? capability->pszObjId : NULL);
2505     TRACE("returning %d\n", ret);
2506     return ret;
2507 }
2508
2509 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2510  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2511  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2512 {
2513     BOOL ret = FALSE;
2514
2515     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2516      pDecodePara, pvStructInfo, *pcbStructInfo);
2517
2518     __TRY
2519     {
2520         DWORD bytesNeeded;
2521         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2522          CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2523          offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2524
2525         if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2526          NULL, NULL, &bytesNeeded, NULL)))
2527         {
2528             bytesNeeded += sizeof(CRYPT_SMIME_CAPABILITIES);
2529             if (!pvStructInfo)
2530                 *pcbStructInfo = bytesNeeded;
2531             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2532              pvStructInfo, pcbStructInfo, bytesNeeded)))
2533             {
2534                 PCRYPT_SMIME_CAPABILITIES capabilities;
2535
2536                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2537                     pvStructInfo = *(BYTE **)pvStructInfo;
2538                 capabilities = pvStructInfo;
2539                 capabilities->rgCapability =
2540                  (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2541                  sizeof(CRYPT_SMIME_CAPABILITIES));
2542                 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
2543                  pbEncoded, cbEncoded, &capabilities->cCapability,
2544                  capabilities->rgCapability, pcbStructInfo, NULL);
2545             }
2546         }
2547     }
2548     __EXCEPT_PAGE_FAULT
2549     {
2550         SetLastError(STATUS_ACCESS_VIOLATION);
2551     }
2552     __ENDTRY
2553     TRACE("returning %d\n", ret);
2554     return ret;
2555 }
2556
2557 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2558  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2559  DWORD *pcbDecoded)
2560 {
2561     BOOL ret = TRUE;
2562     DWORD dataLen;
2563     LPSTR *pStr = pvStructInfo;
2564
2565     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2566     {
2567         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2568         DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2569
2570         if (pbEncoded[0] != ASN_IA5STRING)
2571         {
2572             SetLastError(CRYPT_E_ASN1_CORRUPT);
2573             ret = FALSE;
2574         }
2575         else
2576         {
2577             bytesNeeded += dataLen;
2578             if (pcbDecoded)
2579                 *pcbDecoded = 1 + lenBytes + dataLen;
2580             if (!pvStructInfo)
2581                 *pcbStructInfo = bytesNeeded;
2582             else if (*pcbStructInfo < bytesNeeded)
2583             {
2584                 *pcbStructInfo = bytesNeeded;
2585                 SetLastError(ERROR_MORE_DATA);
2586                 ret = FALSE;
2587             }
2588             else
2589             {
2590                 *pcbStructInfo = bytesNeeded;
2591                 if (dataLen)
2592                 {
2593                     LPSTR str = *pStr;
2594
2595                     assert(str);
2596                     memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2597                     str[dataLen] = 0;
2598                 }
2599                 else
2600                     *pStr = NULL;
2601             }
2602         }
2603     }
2604     return ret;
2605 }
2606
2607 static BOOL CRYPT_AsnDecodeIntArray(const BYTE *pbEncoded,
2608  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2609  DWORD *pcbDecoded)
2610 {
2611     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2612      CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2613     struct GenericArray *array = pvStructInfo;
2614     BOOL ret;
2615
2616     TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2617      pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2618
2619     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2620      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2621      array ? array->rgItems : NULL);
2622     TRACE("returning %d\n", ret);
2623     return ret;
2624 }
2625
2626 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2627  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2628  DWORD *pcbDecoded)
2629 {
2630     BOOL ret;
2631     struct AsnDecodeSequenceItem items[] = {
2632      { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2633        pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2634        offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2635      { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2636        cNoticeNumbers), CRYPT_AsnDecodeIntArray, sizeof(struct GenericArray),
2637        FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2638        rgNoticeNumbers), 0 },
2639     };
2640     DWORD bytesNeeded;
2641
2642     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2643      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2644
2645     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2646      pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2647      NULL);
2648     if (ret)
2649     {
2650         /* The caller is expecting a pointer to a
2651          * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2652          * CRYPT_AsnDecodeSequence is decoding a
2653          * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.  Increment the bytes
2654          * needed, and decode again if the requisite space is available.
2655          */
2656         bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2657         if (!pvStructInfo)
2658             *pcbStructInfo = bytesNeeded;
2659         else if (*pcbStructInfo < bytesNeeded)
2660         {
2661             *pcbStructInfo = bytesNeeded;
2662             SetLastError(ERROR_MORE_DATA);
2663             ret = FALSE;
2664         }
2665         else
2666         {
2667             PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2668
2669             *pcbStructInfo = bytesNeeded;
2670             /* The pointer (pvStructInfo) passed in points to the first dynamic
2671              * pointer, so use it as the pointer to the
2672              * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2673              * appropriate offset for the first dynamic pointer within the
2674              * notice reference by pointing to the first memory location past
2675              * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2676              */
2677             noticeRef =
2678              *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2679             noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2680              sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2681             ret = CRYPT_AsnDecodeSequence(items,
2682              sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2683              NULL, noticeRef, &bytesNeeded, pcbDecoded,
2684              noticeRef->pszOrganization);
2685         }
2686     }
2687     TRACE("returning %d\n", ret);
2688     return ret;
2689 }
2690
2691 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2692  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2693  DWORD *pcbDecoded)
2694 {
2695     BOOL ret = TRUE;
2696     DWORD dataLen;
2697
2698     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2699     {
2700         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2701         DWORD bytesNeeded = sizeof(LPWSTR);
2702
2703         switch (pbEncoded[0])
2704         {
2705         case ASN_NUMERICSTRING:
2706             if (dataLen)
2707                 bytesNeeded += (dataLen + 1) * 2;
2708             break;
2709         case ASN_PRINTABLESTRING:
2710             if (dataLen)
2711                 bytesNeeded += (dataLen + 1) * 2;
2712             break;
2713         case ASN_IA5STRING:
2714             if (dataLen)
2715                 bytesNeeded += (dataLen + 1) * 2;
2716             break;
2717         case ASN_T61STRING:
2718             if (dataLen)
2719                 bytesNeeded += (dataLen + 1) * 2;
2720             break;
2721         case ASN_VIDEOTEXSTRING:
2722             if (dataLen)
2723                 bytesNeeded += (dataLen + 1) * 2;
2724             break;
2725         case ASN_GRAPHICSTRING:
2726             if (dataLen)
2727                 bytesNeeded += (dataLen + 1) * 2;
2728             break;
2729         case ASN_VISIBLESTRING:
2730             if (dataLen)
2731                 bytesNeeded += (dataLen + 1) * 2;
2732             break;
2733         case ASN_GENERALSTRING:
2734             if (dataLen)
2735                 bytesNeeded += (dataLen + 1) * 2;
2736             break;
2737         case ASN_UNIVERSALSTRING:
2738             if (dataLen)
2739                 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2740             break;
2741         case ASN_BMPSTRING:
2742             if (dataLen)
2743                 bytesNeeded += dataLen + sizeof(WCHAR);
2744             break;
2745         case ASN_UTF8STRING:
2746             if (dataLen)
2747                 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2748                  (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2749             break;
2750         default:
2751             SetLastError(CRYPT_E_ASN1_BADTAG);
2752             return FALSE;
2753         }
2754
2755         if (pcbDecoded)
2756             *pcbDecoded = 1 + lenBytes + dataLen;
2757         if (!pvStructInfo)
2758             *pcbStructInfo = bytesNeeded;
2759         else if (*pcbStructInfo < bytesNeeded)
2760         {
2761             *pcbStructInfo = bytesNeeded;
2762             SetLastError(ERROR_MORE_DATA);
2763             ret = FALSE;
2764         }
2765         else
2766         {
2767             LPWSTR *pStr = pvStructInfo;
2768
2769             *pcbStructInfo = bytesNeeded;
2770             if (dataLen)
2771             {
2772                 DWORD i;
2773                 LPWSTR str = *(LPWSTR *)pStr;
2774
2775                 assert(str);
2776                 switch (pbEncoded[0])
2777                 {
2778                 case ASN_NUMERICSTRING:
2779                 case ASN_PRINTABLESTRING:
2780                 case ASN_IA5STRING:
2781                 case ASN_T61STRING:
2782                 case ASN_VIDEOTEXSTRING:
2783                 case ASN_GRAPHICSTRING:
2784                 case ASN_VISIBLESTRING:
2785                 case ASN_GENERALSTRING:
2786                     for (i = 0; i < dataLen; i++)
2787                         str[i] = pbEncoded[1 + lenBytes + i];
2788                     str[i] = 0;
2789                     break;
2790                 case ASN_UNIVERSALSTRING:
2791                     for (i = 0; i < dataLen / 4; i++)
2792                         str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2793                          | pbEncoded[1 + lenBytes + 2 * i + 3];
2794                     str[i] = 0;
2795                     break;
2796                 case ASN_BMPSTRING:
2797                     for (i = 0; i < dataLen / 2; i++)
2798                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2799                          pbEncoded[1 + lenBytes + 2 * i + 1];
2800                     str[i] = 0;
2801                     break;
2802                 case ASN_UTF8STRING:
2803                 {
2804                     int len = MultiByteToWideChar(CP_UTF8, 0,
2805                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2806                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2807                     str[len] = 0;
2808                     break;
2809                 }
2810                 }
2811             }
2812             else
2813                 *pStr = NULL;
2814         }
2815     }
2816     return ret;
2817 }
2818
2819 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2820  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2821  DWORD *pcbStructInfo, DWORD *pcbDecoded)
2822 {
2823     BOOL ret;
2824     struct AsnDecodeSequenceItem items[] = {
2825      { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2826        pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2827        sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2828        offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2829      { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2830        CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2831        offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2832     };
2833     PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2834
2835     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2836      pvStructInfo, *pcbStructInfo);
2837
2838     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2839      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2840      pcbDecoded, notice ? notice->pNoticeReference : NULL);
2841     TRACE("returning %d\n", ret);
2842     return ret;
2843 }
2844
2845 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2846  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2847  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2848  void *pvStructInfo, DWORD *pcbStructInfo)
2849 {
2850     BOOL ret = FALSE;
2851
2852     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2853      pDecodePara, pvStructInfo, *pcbStructInfo);
2854
2855     __TRY
2856     {
2857         DWORD bytesNeeded;
2858
2859         ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2860          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2861          NULL);
2862         if (ret)
2863         {
2864             if (!pvStructInfo)
2865                 *pcbStructInfo = bytesNeeded;
2866             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2867              pvStructInfo, pcbStructInfo, bytesNeeded)))
2868             {
2869                 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2870
2871                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2872                     pvStructInfo = *(BYTE **)pvStructInfo;
2873                 notice = pvStructInfo;
2874                 notice->pNoticeReference =
2875                  (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2876                  ((BYTE *)pvStructInfo +
2877                  sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2878                 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2879                  pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2880                  pvStructInfo, &bytesNeeded, NULL);
2881             }
2882         }
2883     }
2884     __EXCEPT_PAGE_FAULT
2885     {
2886         SetLastError(STATUS_ACCESS_VIOLATION);
2887     }
2888     __ENDTRY
2889     TRACE("returning %d\n", ret);
2890     return ret;
2891 }
2892
2893 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2894  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2895  DWORD *pcbDecoded)
2896 {
2897     BOOL ret;
2898     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2899      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2900     DWORD bytesNeeded;
2901
2902     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2903      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2904
2905     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2906      NULL, NULL, &bytesNeeded, pcbDecoded)))
2907     {
2908         bytesNeeded += FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue);
2909         if (!pvStructInfo)
2910             *pcbStructInfo = bytesNeeded;
2911         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
2912          pcbStructInfo, bytesNeeded)))
2913         {
2914             CRYPT_ATTRIBUTE *attr = (CRYPT_ATTRIBUTE *)((BYTE *)pvStructInfo -
2915              offsetof(CRYPT_ATTRIBUTE, cValue));
2916
2917             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2918              &attr->cValue, attr->rgValue, pcbStructInfo, pcbDecoded);
2919         }
2920     }
2921     return ret;
2922 }
2923
2924 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2925  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2926  DWORD *pcbDecoded)
2927 {
2928     BOOL ret;
2929     struct AsnDecodeSequenceItem items[] = {
2930      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2931        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2932        offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2933      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2934        CRYPT_AsnDecodePKCSAttributeValue,
2935        FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2936        TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2937     };
2938     PCRYPT_ATTRIBUTE attr = pvStructInfo;
2939
2940     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2941      pvStructInfo, *pcbStructInfo);
2942
2943     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2944      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2945      pcbDecoded, attr ? attr->pszObjId : NULL);
2946     TRACE("returning %d\n", ret);
2947     return ret;
2948 }
2949
2950 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2951  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2952  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2953 {
2954     BOOL ret = FALSE;
2955
2956     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2957      pDecodePara, pvStructInfo, *pcbStructInfo);
2958
2959     __TRY
2960     {
2961         DWORD bytesNeeded;
2962
2963         ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2964          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2965         if (ret)
2966         {
2967             if (!pvStructInfo)
2968                 *pcbStructInfo = bytesNeeded;
2969             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2970              pvStructInfo, pcbStructInfo, bytesNeeded)))
2971             {
2972                 PCRYPT_ATTRIBUTE attr;
2973
2974                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2975                     pvStructInfo = *(BYTE **)pvStructInfo;
2976                 attr = pvStructInfo;
2977                 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2978                  sizeof(CRYPT_ATTRIBUTE));
2979                 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2980                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2981                  NULL);
2982             }
2983         }
2984     }
2985     __EXCEPT_PAGE_FAULT
2986     {
2987         SetLastError(STATUS_ACCESS_VIOLATION);
2988     }
2989     __ENDTRY
2990     TRACE("returning %d\n", ret);
2991     return ret;
2992 }
2993
2994 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2995  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2996  DWORD *pcbDecoded)
2997 {
2998     struct AsnArrayDescriptor arrayDesc = { 0,
2999      CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
3000      offsetof(CRYPT_ATTRIBUTE, pszObjId) };
3001     PCRYPT_ATTRIBUTES attrs = pvStructInfo;
3002     BOOL ret;
3003
3004     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3005      NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
3006      NULL);
3007     return ret;
3008 }
3009
3010 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
3011  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3012  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3013 {
3014     BOOL ret = FALSE;
3015
3016     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3017      pDecodePara, pvStructInfo, *pcbStructInfo);
3018
3019     __TRY
3020     {
3021         DWORD bytesNeeded;
3022
3023         if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
3024             SetLastError(CRYPT_E_ASN1_CORRUPT);
3025         else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
3026          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
3027          NULL)))
3028         {
3029             if (!pvStructInfo)
3030                 *pcbStructInfo = bytesNeeded;
3031             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3032              pvStructInfo, pcbStructInfo, bytesNeeded)))
3033             {
3034                 PCRYPT_ATTRIBUTES attrs;
3035
3036                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3037                     pvStructInfo = *(BYTE **)pvStructInfo;
3038                 attrs = pvStructInfo;
3039                 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
3040                  sizeof(CRYPT_ATTRIBUTES));
3041                 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
3042                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3043                  &bytesNeeded, NULL);
3044             }
3045         }
3046     }
3047     __EXCEPT_PAGE_FAULT
3048     {
3049         SetLastError(STATUS_ACCESS_VIOLATION);
3050     }
3051     __ENDTRY
3052     TRACE("returning %d\n", ret);
3053     return ret;
3054 }
3055
3056 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
3057  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3058 {
3059     CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
3060     BOOL ret = TRUE;
3061     struct AsnDecodeSequenceItem items[] = {
3062      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
3063        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3064        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
3065      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
3066        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
3067        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
3068     };
3069
3070     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3071      pvStructInfo, *pcbStructInfo, pcbDecoded);
3072
3073     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3074      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3075      pcbDecoded, algo ? algo->pszObjId : NULL);
3076     if (ret && pvStructInfo)
3077     {
3078         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
3079          debugstr_a(algo->pszObjId));
3080     }
3081     return ret;
3082 }
3083
3084 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
3085  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3086  DWORD *pcbDecoded)
3087 {
3088     BOOL ret = TRUE;
3089     struct AsnDecodeSequenceItem items[] = {
3090      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
3091        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3092        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
3093        Algorithm.pszObjId) },
3094      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
3095        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3096        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
3097     };
3098     PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
3099
3100     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3101      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3102      pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
3103     return ret;
3104 }
3105
3106 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
3107  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3108  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3109 {
3110     BOOL ret = TRUE;
3111
3112     __TRY
3113     {
3114         DWORD bytesNeeded;
3115
3116         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
3117          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3118         {
3119             if (!pvStructInfo)
3120                 *pcbStructInfo = bytesNeeded;
3121             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3122              pvStructInfo, pcbStructInfo, bytesNeeded)))
3123             {
3124                 PCERT_PUBLIC_KEY_INFO info;
3125
3126                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3127                     pvStructInfo = *(BYTE **)pvStructInfo;
3128                 info = pvStructInfo;
3129                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
3130                  sizeof(CERT_PUBLIC_KEY_INFO);
3131                 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
3132                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3133                  &bytesNeeded, NULL);
3134             }
3135         }
3136     }
3137     __EXCEPT_PAGE_FAULT
3138     {
3139         SetLastError(STATUS_ACCESS_VIOLATION);
3140         ret = FALSE;
3141     }
3142     __ENDTRY
3143     return ret;
3144 }
3145
3146 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
3147  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3148 {
3149     BOOL ret;
3150
3151     if (cbEncoded < 3)
3152     {
3153         SetLastError(CRYPT_E_ASN1_CORRUPT);
3154         return FALSE;
3155     }
3156     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
3157     {
3158         SetLastError(CRYPT_E_ASN1_CORRUPT);
3159         return FALSE;
3160     }
3161     if (pbEncoded[1] > 1)
3162     {
3163         SetLastError(CRYPT_E_ASN1_CORRUPT);
3164         return FALSE;
3165     }
3166     if (pcbDecoded)
3167         *pcbDecoded = 3;
3168     if (!pvStructInfo)
3169     {
3170         *pcbStructInfo = sizeof(BOOL);
3171         ret = TRUE;
3172     }
3173     else if (*pcbStructInfo < sizeof(BOOL))
3174     {
3175         *pcbStructInfo = sizeof(BOOL);
3176         SetLastError(ERROR_MORE_DATA);
3177         ret = FALSE;
3178     }
3179     else
3180     {
3181         *pcbStructInfo = sizeof(BOOL);
3182         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
3183         ret = TRUE;
3184     }
3185     TRACE("returning %d (%08x)\n", ret, GetLastError());
3186     return ret;
3187 }
3188
3189 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
3190  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3191 {
3192     PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
3193     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
3194     BOOL ret;
3195
3196     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3197      pvStructInfo, *pcbStructInfo);
3198
3199     if (cbEncoded < 2)
3200     {
3201         SetLastError(CRYPT_E_ASN1_CORRUPT);
3202         return FALSE;
3203     }
3204     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3205     if (1 + lenBytes > cbEncoded)
3206     {
3207         SetLastError(CRYPT_E_ASN1_CORRUPT);
3208         return FALSE;
3209     }
3210     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3211     {
3212         switch (pbEncoded[0] & ASN_TYPE_MASK)
3213         {
3214         case 1: /* rfc822Name */
3215         case 2: /* dNSName */
3216         case 6: /* uniformResourceIdentifier */
3217             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3218             break;
3219         case 4: /* directoryName */
3220         case 7: /* iPAddress */
3221             bytesNeeded += dataLen;
3222             break;
3223         case 8: /* registeredID */
3224             ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3225              &dataLen, NULL);
3226             if (ret)
3227             {
3228                 /* FIXME: ugly, shouldn't need to know internals of OID decode
3229                  * function to use it.
3230                  */
3231                 bytesNeeded += dataLen - sizeof(LPSTR);
3232             }
3233             break;
3234         case 0: /* otherName */
3235             FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3236             SetLastError(CRYPT_E_ASN1_BADTAG);
3237             ret = FALSE;
3238             break;
3239         case 3: /* x400Address, unimplemented */
3240         case 5: /* ediPartyName, unimplemented */
3241             TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3242             SetLastError(CRYPT_E_ASN1_BADTAG);
3243             ret = FALSE;
3244             break;
3245         default:
3246             TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3247             SetLastError(CRYPT_E_ASN1_CORRUPT);
3248             ret = FALSE;
3249         }
3250         if (ret)
3251         {
3252             if (pcbDecoded)
3253                 *pcbDecoded = 1 + lenBytes + dataLen;
3254             if (!entry)
3255                 *pcbStructInfo = bytesNeeded;
3256             else if (*pcbStructInfo < bytesNeeded)
3257             {
3258                 *pcbStructInfo = bytesNeeded;
3259                 SetLastError(ERROR_MORE_DATA);
3260                 ret = FALSE;
3261             }
3262             else
3263             {
3264                 *pcbStructInfo = bytesNeeded;
3265                 /* MS used values one greater than the asn1 ones.. sigh */
3266                 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3267                 switch (pbEncoded[0] & ASN_TYPE_MASK)
3268                 {
3269                 case 1: /* rfc822Name */
3270                 case 2: /* dNSName */
3271                 case 6: /* uniformResourceIdentifier */
3272                 {
3273                     DWORD i;
3274
3275                     for (i = 0; i < dataLen; i++)
3276                         entry->u.pwszURL[i] =
3277                          (WCHAR)pbEncoded[1 + lenBytes + i];
3278                     entry->u.pwszURL[i] = 0;
3279                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3280                      debugstr_w(entry->u.pwszURL));
3281                     break;
3282                 }
3283                 case 4: /* directoryName */
3284                     /* The data are memory-equivalent with the IPAddress case,
3285                      * fall-through
3286                      */
3287                 case 7: /* iPAddress */
3288                     /* The next data pointer is in the pwszURL spot, that is,
3289                      * the first 4 bytes.  Need to move it to the next spot.
3290                      */
3291                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3292                     entry->u.IPAddress.cbData = dataLen;
3293                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3294                      dataLen);
3295                     break;
3296                 case 8: /* registeredID */
3297                     ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3298                      &entry->u.pszRegisteredID, &dataLen, NULL);
3299                     break;
3300                 }
3301             }
3302         }
3303     }
3304     return ret;
3305 }
3306
3307 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3308  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3309  DWORD *pcbDecoded)
3310 {
3311     BOOL ret = TRUE;
3312     struct AsnArrayDescriptor arrayDesc = { 0,
3313      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3314      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3315     PCERT_ALT_NAME_INFO info = pvStructInfo;
3316
3317     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3318      pvStructInfo, *pcbStructInfo, pcbDecoded);
3319
3320     if (info)
3321         TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
3322     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3323      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3324      info ? info->rgAltEntry : NULL);
3325     return ret;
3326 }
3327
3328 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
3329 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
3330  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3331  DWORD *pcbDecoded)
3332 {
3333     BOOL ret;
3334
3335     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3336      pvStructInfo, *pcbStructInfo, pcbDecoded);
3337
3338     /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3339      * place.
3340      */
3341     ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3342      dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3343      pcbDecoded);
3344     if (ret && pvStructInfo)
3345     {
3346         CRYPT_DATA_BLOB *blob = pvStructInfo;
3347
3348         if (blob->cbData)
3349         {
3350             DWORD i;
3351             BYTE temp;
3352
3353             for (i = 0; i < blob->cbData / 2; i++)
3354             {
3355                 temp = blob->pbData[i];
3356                 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3357                 blob->pbData[blob->cbData - i - 1] = temp;
3358             }
3359         }
3360     }
3361     TRACE("returning %d (%08x)\n", ret, GetLastError());
3362     return ret;
3363 }
3364
3365 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3366  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3367  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3368 {
3369     BOOL ret;
3370
3371     __TRY
3372     {
3373         struct AsnDecodeSequenceItem items[] = {
3374          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3375            CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3376            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3377          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3378            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3379            CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3380            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3381          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3382            CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3383            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3384            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3385         };
3386
3387         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3388          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3389          pcbStructInfo, NULL, NULL);
3390     }
3391     __EXCEPT_PAGE_FAULT
3392     {
3393         SetLastError(STATUS_ACCESS_VIOLATION);
3394         ret = FALSE;
3395     }
3396     __ENDTRY
3397     return ret;
3398 }
3399
3400 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3401  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3402  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3403 {
3404     BOOL ret;
3405
3406     __TRY
3407     {
3408         struct AsnDecodeSequenceItem items[] = {
3409          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3410            CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3411            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3412          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3413            offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3414            CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3415            TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3416            AuthorityCertIssuer.rgAltEntry), 0 },
3417          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3418            AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3419            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3420            offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3421            AuthorityCertSerialNumber.pbData), 0 },
3422         };
3423
3424         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3425          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3426          pcbStructInfo, NULL, NULL);
3427     }
3428     __EXCEPT_PAGE_FAULT
3429     {
3430         SetLastError(STATUS_ACCESS_VIOLATION);
3431         ret = FALSE;
3432     }
3433     __ENDTRY
3434     return ret;
3435 }
3436
3437 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3438  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3439  DWORD *pcbDecoded)
3440 {
3441     struct AsnDecodeSequenceItem items[] = {
3442      { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3443        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3444        offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3445      { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3446        CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3447        TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3448     };
3449     CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3450
3451     return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3452      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3453      pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3454 }
3455
3456 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3457  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3458  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3459 {
3460     BOOL ret;
3461
3462     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3463      pDecodePara, pvStructInfo, *pcbStructInfo);
3464
3465     __TRY
3466     {
3467         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3468          CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3469          TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3470
3471         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3472          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3473     }
3474     __EXCEPT_PAGE_FAULT
3475     {
3476         SetLastError(STATUS_ACCESS_VIOLATION);
3477         ret = FALSE;
3478     }
3479     __ENDTRY
3480     return ret;
3481 }
3482
3483 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3484  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3485 {
3486     BOOL ret;
3487     DWORD dataLen;
3488
3489     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3490      pvStructInfo, *pcbStructInfo, pcbDecoded);
3491
3492     /* The caller has already checked the tag, no need to check it again.
3493      * Check the outer length is valid:
3494      */
3495     if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3496     {
3497         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3498         DWORD innerLen;
3499
3500         pbEncoded += 1 + lenBytes;
3501         cbEncoded -= 1 + lenBytes;
3502         if (dataLen == CMSG_INDEFINITE_LENGTH)
3503             cbEncoded -= 2; /* space for 0 TLV */
3504         /* Check the inner length is valid: */
3505         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3506         {
3507             DWORD decodedLen;
3508
3509             ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3510              pvStructInfo, pcbStructInfo, &decodedLen);
3511             if (dataLen == CMSG_INDEFINITE_LENGTH)
3512             {
3513                 if (*(pbEncoded + decodedLen) != 0 ||
3514                  *(pbEncoded + decodedLen + 1) != 0)
3515                 {
3516                     TRACE("expected 0 TLV, got {%02x,%02x}\n",
3517                      *(pbEncoded + decodedLen),
3518                      *(pbEncoded + decodedLen + 1));
3519                     SetLastError(CRYPT_E_ASN1_CORRUPT);
3520                     ret = FALSE;
3521                 }
3522                 else
3523                     decodedLen += 2;
3524             }
3525             if (ret && pcbDecoded)
3526             {
3527                 *pcbDecoded = 1 + lenBytes + decodedLen;
3528                 TRACE("decoded %d bytes\n", *pcbDecoded);
3529             }
3530         }
3531     }
3532     return ret;
3533 }
3534
3535 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3536  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3537  DWORD *pcbDecoded)
3538 {
3539     CRYPT_CONTENT_INFO *info = pvStructInfo;
3540     struct AsnDecodeSequenceItem items[] = {
3541      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3542        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3543        offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3544      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3545        offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3546        sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3547        offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3548     };
3549     BOOL ret;
3550
3551     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3552      pvStructInfo, *pcbStructInfo, pcbDecoded);
3553
3554     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3555      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3556      pcbDecoded, info ? info->pszObjId : NULL);
3557     return ret;
3558 }
3559
3560 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3561  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3562  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3563 {
3564     BOOL ret = FALSE;
3565
3566     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3567      pDecodePara, pvStructInfo, *pcbStructInfo);
3568
3569     __TRY
3570     {
3571         ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3572          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3573         if (ret && pvStructInfo)
3574         {
3575             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3576              pcbStructInfo, *pcbStructInfo);
3577             if (ret)
3578             {
3579                 CRYPT_CONTENT_INFO *info;
3580
3581                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3582                     pvStructInfo = *(BYTE **)pvStructInfo;
3583                 info = pvStructInfo;
3584                 info->pszObjId = (LPSTR)((BYTE *)info +
3585                  sizeof(CRYPT_CONTENT_INFO));
3586                 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3587                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3588                  pcbStructInfo, NULL);
3589             }
3590         }
3591     }
3592     __EXCEPT_PAGE_FAULT
3593     {
3594         SetLastError(STATUS_ACCESS_VIOLATION);
3595     }
3596     __ENDTRY
3597     return ret;
3598 }
3599
3600 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3601  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3602  CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3603 {
3604     BOOL ret;
3605     struct AsnDecodeSequenceItem items[] = {
3606      { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3607        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3608      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3609        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3610        FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3611        0 },
3612      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3613        CRYPT_AsnDecodePKCSContentInfoInternal,
3614        sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3615        ContentInfo.pszObjId), 0 },
3616      { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3617        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3618        offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3619     };
3620
3621     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3622      pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3623      NULL, NULL);
3624     return ret;
3625 }
3626
3627 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3628  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3629  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3630 {
3631     BOOL ret = TRUE;
3632
3633     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3634      pDecodePara, pvStructInfo, *pcbStructInfo);
3635
3636     __TRY
3637     {
3638         DWORD bytesNeeded;
3639
3640         if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3641          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3642         {
3643             if (!pvStructInfo)
3644                 *pcbStructInfo = bytesNeeded;
3645             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3646              pvStructInfo, pcbStructInfo, bytesNeeded)))
3647             {
3648                 CERT_ALT_NAME_INFO *name;
3649
3650                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3651                     pvStructInfo = *(BYTE **)pvStructInfo;
3652                 name = pvStructInfo;
3653                 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3654                  ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3655                 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3656                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3657                  &bytesNeeded, NULL);
3658             }
3659         }
3660     }
3661     __EXCEPT_PAGE_FAULT
3662     {
3663         SetLastError(STATUS_ACCESS_VIOLATION);
3664         ret = FALSE;
3665     }
3666     __ENDTRY
3667     return ret;
3668 }
3669
3670 struct PATH_LEN_CONSTRAINT
3671 {
3672     BOOL  fPathLenConstraint;
3673     DWORD dwPathLenConstraint;
3674 };
3675
3676 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3677  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3678  DWORD *pcbDecoded)
3679 {
3680     BOOL ret = TRUE;
3681     DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3682
3683     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3684      pvStructInfo, *pcbStructInfo, pcbDecoded);
3685
3686     if (!pvStructInfo)
3687     {
3688         ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3689          &size, pcbDecoded);
3690         *pcbStructInfo = bytesNeeded;
3691     }
3692     else if (*pcbStructInfo < bytesNeeded)
3693     {
3694         SetLastError(ERROR_MORE_DATA);
3695         *pcbStructInfo = bytesNeeded;
3696         ret = FALSE;
3697     }
3698     else
3699     {
3700         struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3701
3702         *pcbStructInfo = bytesNeeded;
3703         size = sizeof(constraint->dwPathLenConstraint);
3704         ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3705          &constraint->dwPathLenConstraint, &size, pcbDecoded);
3706         if (ret)
3707             constraint->fPathLenConstraint = TRUE;
3708         TRACE("got an int, dwPathLenConstraint is %d\n",
3709          constraint->dwPathLenConstraint);
3710     }
3711     TRACE("returning %d (%08x)\n", ret, GetLastError());
3712     return ret;
3713 }
3714
3715 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3716  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3717  DWORD *pcbDecoded)
3718 {
3719     BOOL ret;
3720     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3721      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3722      offsetof(CERT_NAME_BLOB, pbData) };
3723     struct GenericArray *entries = pvStructInfo;
3724
3725     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3726      pvStructInfo, *pcbStructInfo, pcbDecoded);
3727
3728     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3729      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3730      entries ? entries->rgItems : NULL);
3731     TRACE("Returning %d (%08x)\n", ret, GetLastError());
3732     return ret;
3733 }
3734
3735 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3736  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3737  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3738 {
3739     BOOL ret;
3740
3741     __TRY
3742     {
3743         struct AsnDecodeSequenceItem items[] = {
3744          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3745            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
3746            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3747          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3748            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3749            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3750          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3751            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3752            sizeof(struct GenericArray), TRUE, TRUE,
3753            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3754         };
3755
3756         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3757          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3758          pcbStructInfo, NULL, NULL);
3759     }
3760     __EXCEPT_PAGE_FAULT
3761     {
3762         SetLastError(STATUS_ACCESS_VIOLATION);
3763         ret = FALSE;
3764     }
3765     __ENDTRY
3766     return ret;
3767 }
3768
3769 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3770  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3771  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3772 {
3773     BOOL ret;
3774
3775     __TRY
3776     {
3777         struct AsnDecodeSequenceItem items[] = {
3778          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3779            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3780          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3781            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3782            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3783         };
3784
3785         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3786          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3787          pcbStructInfo, NULL, NULL);
3788     }
3789     __EXCEPT_PAGE_FAULT
3790     {
3791         SetLastError(STATUS_ACCESS_VIOLATION);
3792         ret = FALSE;
3793     }
3794     __ENDTRY
3795     return ret;
3796 }
3797
3798 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3799  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3800  DWORD *pcbDecoded)
3801 {
3802     struct AsnDecodeSequenceItem items[] = {
3803      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3804        pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3805        FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3806        0 },
3807      { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3808        CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3809        offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3810     };
3811     BOOL ret;
3812     CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3813
3814     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3815      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3816
3817     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3818      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3819      pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3820     return ret;
3821 }
3822
3823 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3824  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3825  DWORD *pcbDecoded)
3826 {
3827     BOOL ret;
3828     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3829      CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3830      offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3831     struct GenericArray *entries = pvStructInfo;
3832
3833     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3834      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3835
3836     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3837      NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3838      entries ? entries->rgItems : NULL);
3839     TRACE("Returning %d (%08x)\n", ret, GetLastError());
3840     return ret;
3841 }
3842
3843 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3844  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3845 {
3846     struct AsnDecodeSequenceItem items[] = {
3847      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3848        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3849        offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3850      { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3851        CRYPT_AsnDecodePolicyQualifiers, sizeof(struct GenericArray), TRUE,
3852        TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3853     };
3854     CERT_POLICY_INFO *info = pvStructInfo;
3855     BOOL ret;
3856
3857     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3858      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3859
3860     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3861      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3862      pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3863     return ret;
3864 }
3865
3866 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3867  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3868  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3869 {
3870     BOOL ret = FALSE;
3871
3872     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3873      pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3874
3875     __TRY
3876     {
3877         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3878          CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3879          offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3880
3881         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3882          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3883     }
3884     __EXCEPT_PAGE_FAULT
3885     {
3886         SetLastError(STATUS_ACCESS_VIOLATION);
3887     }
3888     __ENDTRY
3889     return ret;
3890 }
3891
3892 #define RSA1_MAGIC 0x31415352
3893
3894 struct DECODED_RSA_PUB_KEY
3895 {
3896     DWORD              pubexp;
3897     CRYPT_INTEGER_BLOB modulus;
3898 };
3899
3900 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3901  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3902  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3903 {
3904     BOOL ret;
3905
3906     __TRY
3907     {
3908         struct AsnDecodeSequenceItem items[] = {
3909          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3910            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3911            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3912            0 },
3913          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3914            CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3915         };
3916         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3917         DWORD size = 0;
3918
3919         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3920          pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3921          &size, NULL, NULL);
3922         if (ret)
3923         {
3924             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3925              decodedKey->modulus.cbData;
3926
3927             if (!pvStructInfo)
3928             {
3929                 *pcbStructInfo = bytesNeeded;
3930                 ret = TRUE;
3931             }
3932             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3933              pvStructInfo, pcbStructInfo, bytesNeeded)))
3934             {
3935                 BLOBHEADER *hdr;
3936                 RSAPUBKEY *rsaPubKey;
3937
3938                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3939                     pvStructInfo = *(BYTE **)pvStructInfo;
3940                 hdr = pvStructInfo;
3941                 hdr->bType = PUBLICKEYBLOB;
3942                 hdr->bVersion = CUR_BLOB_VERSION;
3943                 hdr->reserved = 0;
3944                 hdr->aiKeyAlg = CALG_RSA_KEYX;
3945                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3946                  sizeof(BLOBHEADER));
3947                 rsaPubKey->magic = RSA1_MAGIC;
3948                 rsaPubKey->pubexp = decodedKey->pubexp;
3949                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3950                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3951                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3952                  decodedKey->modulus.cbData);
3953             }
3954             LocalFree(decodedKey);
3955         }
3956     }
3957     __EXCEPT_PAGE_FAULT
3958     {
3959         SetLastError(STATUS_ACCESS_VIOLATION);
3960         ret = FALSE;
3961     }
3962     __ENDTRY
3963     return ret;
3964 }
3965
3966 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3967  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3968  DWORD *pcbDecoded)
3969 {
3970     BOOL ret;
3971     DWORD bytesNeeded, dataLen;
3972
3973     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3974      pvStructInfo, *pcbStructInfo, pcbDecoded);
3975
3976     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3977     {
3978         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3979
3980         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3981             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3982         else
3983             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3984         if (pcbDecoded)
3985             *pcbDecoded = 1 + lenBytes + dataLen;
3986         if (!pvStructInfo)
3987             *pcbStructInfo = bytesNeeded;
3988         else if (*pcbStructInfo < bytesNeeded)
3989         {
3990             SetLastError(ERROR_MORE_DATA);
3991             *pcbStructInfo = bytesNeeded;
3992             ret = FALSE;
3993         }
3994         else
3995         {
3996             CRYPT_DATA_BLOB *blob;
3997
3998             *pcbStructInfo = bytesNeeded;
3999             blob = pvStructInfo;
4000             blob->cbData = dataLen;
4001             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4002                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4003             else
4004             {
4005                 assert(blob->pbData);
4006                 if (blob->cbData)
4007                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4008                      blob->cbData);
4009             }
4010         }
4011     }
4012     return ret;
4013 }
4014
4015 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
4016  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4017  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4018 {
4019     BOOL ret;
4020
4021     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4022      pDecodePara, pvStructInfo, *pcbStructInfo);
4023
4024     __TRY
4025     {
4026         DWORD bytesNeeded;
4027
4028         if (!cbEncoded)
4029         {
4030             SetLastError(CRYPT_E_ASN1_CORRUPT);
4031             ret = FALSE;
4032         }
4033         else if (pbEncoded[0] != ASN_OCTETSTRING)
4034         {
4035             SetLastError(CRYPT_E_ASN1_BADTAG);
4036             ret = FALSE;
4037         }
4038         else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4039          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4040         {
4041             if (!pvStructInfo)
4042                 *pcbStructInfo = bytesNeeded;
4043             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4044              pvStructInfo, pcbStructInfo, bytesNeeded)))
4045             {
4046                 CRYPT_DATA_BLOB *blob;
4047
4048                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4049                     pvStructInfo = *(BYTE **)pvStructInfo;
4050                 blob = pvStructInfo;
4051                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4052                 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4053                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4054                  &bytesNeeded, NULL);
4055             }
4056         }
4057     }
4058     __EXCEPT_PAGE_FAULT
4059     {
4060         SetLastError(STATUS_ACCESS_VIOLATION);
4061         ret = FALSE;
4062     }
4063     __ENDTRY
4064     return ret;
4065 }
4066
4067 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4068  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4069 {
4070     BOOL ret;
4071     DWORD bytesNeeded, dataLen;
4072     BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4073
4074     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
4075      pvStructInfo, *pcbStructInfo, pcbDecoded);
4076
4077     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4078     {
4079         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4080             bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4081         else
4082             bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4083         if (pcbDecoded)
4084             *pcbDecoded = 1 + lenBytes + dataLen;
4085         if (!pvStructInfo)
4086             *pcbStructInfo = bytesNeeded;
4087         else if (*pcbStructInfo < bytesNeeded)
4088         {
4089             *pcbStructInfo = bytesNeeded;
4090             SetLastError(ERROR_MORE_DATA);
4091             ret = FALSE;
4092         }
4093         else
4094         {
4095             CRYPT_BIT_BLOB *blob;
4096
4097             *pcbStructInfo = bytesNeeded;
4098             blob = pvStructInfo;
4099             blob->cbData = dataLen - 1;
4100             blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4101             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4102             {
4103                 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4104             }
4105             else
4106             {
4107                 assert(blob->pbData);
4108                 if (blob->cbData)
4109                 {
4110                     BYTE mask = 0xff << blob->cUnusedBits;
4111
4112                     memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4113                      blob->cbData);
4114                     blob->pbData[blob->cbData - 1] &= mask;
4115                 }
4116             }
4117         }
4118     }
4119     return ret;
4120 }
4121
4122 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4123  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4124  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4125 {
4126     BOOL ret;
4127
4128     TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4129      pDecodePara, pvStructInfo, pcbStructInfo);
4130
4131     __TRY
4132     {
4133         DWORD bytesNeeded;
4134
4135         if (!cbEncoded)
4136         {
4137             SetLastError(CRYPT_E_ASN1_CORRUPT);
4138             ret = FALSE;
4139         }
4140         else if (pbEncoded[0] != ASN_BITSTRING)
4141         {
4142             SetLastError(CRYPT_E_ASN1_BADTAG);
4143             ret = FALSE;
4144         }
4145         else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4146          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4147         {
4148             if (!pvStructInfo)
4149                 *pcbStructInfo = bytesNeeded;
4150             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4151              pvStructInfo, pcbStructInfo, bytesNeeded)))
4152             {
4153                 CRYPT_BIT_BLOB *blob;
4154
4155                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4156                     pvStructInfo = *(BYTE **)pvStructInfo;
4157                 blob = pvStructInfo;
4158                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4159                 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4160                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4161                  &bytesNeeded, NULL);
4162             }
4163         }
4164     }
4165     __EXCEPT_PAGE_FAULT
4166     {
4167         SetLastError(STATUS_ACCESS_VIOLATION);
4168         ret = FALSE;
4169     }
4170     __ENDTRY
4171     TRACE("returning %d (%08x)\n", ret, GetLastError());
4172     return ret;
4173 }
4174
4175 /* Ignores tag.  Only allows integers 4 bytes or smaller in size. */
4176 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4177  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4178 {
4179     BOOL ret;
4180     BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
4181     CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
4182     DWORD size = sizeof(buf);
4183
4184     blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
4185     ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
4186      &size, pcbDecoded);
4187     if (ret)
4188     {
4189         if (!pvStructInfo)
4190             *pcbStructInfo = sizeof(int);
4191         else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4192         {
4193             int val, i;
4194
4195             if (blob->pbData[blob->cbData - 1] & 0x80)
4196             {
4197                 /* initialize to a negative value to sign-extend */
4198                 val = -1;
4199             }
4200             else
4201                 val = 0;
4202             for (i = 0; i < blob->cbData; i++)
4203             {
4204                 val <<= 8;
4205                 val |= blob->pbData[blob->cbData - i - 1];
4206             }
4207             memcpy(pvStructInfo, &val, sizeof(int));
4208         }
4209     }
4210     else if (GetLastError() == ERROR_MORE_DATA)
4211         SetLastError(CRYPT_E_ASN1_LARGE);
4212     return ret;
4213 }
4214
4215 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4216  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4217  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4218 {
4219     BOOL ret;
4220
4221     __TRY
4222     {
4223         DWORD bytesNeeded;
4224
4225         if (!cbEncoded)
4226         {
4227             SetLastError(CRYPT_E_ASN1_EOD);
4228             ret = FALSE;
4229         }
4230         else if (pbEncoded[0] != ASN_INTEGER)
4231         {
4232             SetLastError(CRYPT_E_ASN1_BADTAG);
4233             ret = FALSE;
4234         }
4235         else
4236             ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4237              dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4238         if (ret)
4239         {
4240             if (!pvStructInfo)
4241                 *pcbStructInfo = bytesNeeded;
4242             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4243              pvStructInfo, pcbStructInfo, bytesNeeded)))
4244             {
4245                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4246                     pvStructInfo = *(BYTE **)pvStructInfo;
4247                 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4248                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4249                  &bytesNeeded, NULL);
4250             }
4251         }
4252     }
4253     __EXCEPT_PAGE_FAULT
4254     {
4255         SetLastError(STATUS_ACCESS_VIOLATION);
4256         ret = FALSE;
4257     }
4258     __ENDTRY
4259     return ret;
4260 }
4261
4262 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4263  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4264  DWORD *pcbDecoded)
4265 {
4266     BOOL ret;
4267     DWORD bytesNeeded, dataLen;
4268
4269     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4270     {
4271         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4272
4273         bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4274         if (pcbDecoded)
4275             *pcbDecoded = 1 + lenBytes + dataLen;
4276         if (!pvStructInfo)
4277             *pcbStructInfo = bytesNeeded;
4278         else if (*pcbStructInfo < bytesNeeded)
4279         {
4280             *pcbStructInfo = bytesNeeded;
4281             SetLastError(ERROR_MORE_DATA);
4282             ret = FALSE;
4283         }
4284         else
4285         {
4286             CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4287
4288             *pcbStructInfo = bytesNeeded;
4289             blob->cbData = dataLen;
4290             assert(blob->pbData);
4291             if (blob->cbData)
4292             {
4293                 DWORD i;
4294
4295                 for (i = 0; i < blob->cbData; i++)
4296                 {
4297                     blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4298                      dataLen - i - 1);
4299                 }
4300             }
4301         }
4302     }
4303     return ret;
4304 }
4305
4306 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4307  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4308  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4309 {
4310     BOOL ret;
4311
4312     __TRY
4313     {
4314         DWORD bytesNeeded;
4315
4316         if (pbEncoded[0] != ASN_INTEGER)
4317         {
4318             SetLastError(CRYPT_E_ASN1_BADTAG);
4319             ret = FALSE;
4320         }
4321         else
4322             ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4323              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4324         if (ret)
4325         {
4326             if (!pvStructInfo)
4327                 *pcbStructInfo = bytesNeeded;
4328             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4329              pvStructInfo, pcbStructInfo, bytesNeeded)))
4330             {
4331                 CRYPT_INTEGER_BLOB *blob;
4332
4333                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4334                     pvStructInfo = *(BYTE **)pvStructInfo;
4335                 blob = pvStructInfo;
4336                 blob->pbData = (BYTE *)pvStructInfo +
4337                  sizeof(CRYPT_INTEGER_BLOB);
4338                 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4339                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4340                  &bytesNeeded, NULL);
4341             }
4342         }
4343     }
4344     __EXCEPT_PAGE_FAULT
4345     {
4346         SetLastError(STATUS_ACCESS_VIOLATION);
4347         ret = FALSE;
4348     }
4349     __ENDTRY
4350     return ret;
4351 }
4352
4353 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4354  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4355  DWORD *pcbDecoded)
4356 {
4357     BOOL ret;
4358
4359     if (pbEncoded[0] == ASN_INTEGER)
4360     {
4361         DWORD bytesNeeded, dataLen;
4362
4363         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4364         {
4365             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4366
4367             if (pcbDecoded)
4368                 *pcbDecoded = 1 + lenBytes + dataLen;
4369             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4370             if (!pvStructInfo)
4371                 *pcbStructInfo = bytesNeeded;
4372             else if (*pcbStructInfo < bytesNeeded)
4373             {
4374                 *pcbStructInfo = bytesNeeded;
4375                 SetLastError(ERROR_MORE_DATA);
4376                 ret = FALSE;
4377             }
4378             else
4379             {
4380                 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4381
4382                 *pcbStructInfo = bytesNeeded;
4383                 blob->cbData = dataLen;
4384                 assert(blob->pbData);
4385                 /* remove leading zero byte if it exists */
4386                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4387                 {
4388                     blob->cbData--;
4389                     blob->pbData++;
4390                 }
4391                 if (blob->cbData)
4392                 {
4393                     DWORD i;
4394
4395                     for (i = 0; i < blob->cbData; i++)
4396                     {
4397                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4398                          dataLen - i - 1);
4399                     }
4400                 }
4401             }
4402         }
4403     }
4404     else
4405     {
4406         SetLastError(CRYPT_E_ASN1_BADTAG);
4407         ret = FALSE;
4408     }
4409     return ret;
4410 }
4411
4412 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4413  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4414  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4415 {
4416     BOOL ret;
4417
4418     __TRY
4419     {
4420         DWORD bytesNeeded;
4421
4422         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4423          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4424         {
4425             if (!pvStructInfo)
4426                 *pcbStructInfo = bytesNeeded;
4427             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4428              pvStructInfo, pcbStructInfo, bytesNeeded)))
4429             {
4430                 CRYPT_INTEGER_BLOB *blob;
4431
4432                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4433                     pvStructInfo = *(BYTE **)pvStructInfo;
4434                 blob = pvStructInfo;
4435                 blob->pbData = (BYTE *)pvStructInfo +
4436                  sizeof(CRYPT_INTEGER_BLOB);
4437                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4438                  cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4439                  &bytesNeeded, NULL);
4440             }
4441         }
4442     }
4443     __EXCEPT_PAGE_FAULT
4444     {
4445         SetLastError(STATUS_ACCESS_VIOLATION);
4446         ret = FALSE;
4447     }
4448     __ENDTRY
4449     return ret;
4450 }
4451
4452 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4453  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4454  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4455 {
4456     BOOL ret;
4457
4458     if (!pvStructInfo)
4459     {
4460         *pcbStructInfo = sizeof(int);
4461         return TRUE;
4462     }
4463     __TRY
4464     {
4465         if (pbEncoded[0] == ASN_ENUMERATED)
4466         {
4467             unsigned int val = 0, i;
4468
4469             if (cbEncoded <= 1)
4470             {
4471                 SetLastError(CRYPT_E_ASN1_EOD);
4472                 ret = FALSE;
4473             }
4474             else if (pbEncoded[1] == 0)
4475             {
4476                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4477                 ret = FALSE;
4478             }
4479             else
4480             {
4481                 /* A little strange looking, but we have to accept a sign byte:
4482                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
4483                  * assuming a small length is okay here, it has to be in short
4484                  * form.
4485                  */
4486                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4487                 {
4488                     SetLastError(CRYPT_E_ASN1_LARGE);
4489                     return FALSE;
4490                 }
4491                 for (i = 0; i < pbEncoded[1]; i++)
4492                 {
4493                     val <<= 8;
4494                     val |= pbEncoded[2 + i];
4495                 }
4496                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4497                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4498                 {
4499                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4500                         pvStructInfo = *(BYTE **)pvStructInfo;
4501                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
4502                 }
4503             }
4504         }
4505         else
4506         {
4507             SetLastError(CRYPT_E_ASN1_BADTAG);
4508             ret = FALSE;
4509         }
4510     }
4511     __EXCEPT_PAGE_FAULT
4512     {
4513         SetLastError(STATUS_ACCESS_VIOLATION);
4514         ret = FALSE;
4515     }
4516     __ENDTRY
4517     return ret;
4518 }
4519
4520 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4521  * if it fails.
4522  */
4523 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4524  do { \
4525     BYTE i; \
4526  \
4527     (word) = 0; \
4528     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4529     { \
4530         if (!isdigit(*(pbEncoded))) \
4531         { \
4532             SetLastError(CRYPT_E_ASN1_CORRUPT); \
4533             ret = FALSE; \
4534         } \
4535         else \
4536         { \
4537             (word) *= 10; \
4538             (word) += *(pbEncoded)++ - '0'; \
4539         } \
4540     } \
4541  } while (0)
4542
4543 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4544  SYSTEMTIME *sysTime)
4545 {
4546     BOOL ret = TRUE;
4547
4548     if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4549     {
4550         WORD hours, minutes = 0;
4551         BYTE sign = *pbEncoded++;
4552
4553         len--;
4554         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4555         if (ret && hours >= 24)
4556         {
4557             SetLastError(CRYPT_E_ASN1_CORRUPT);
4558             ret = FALSE;
4559         }
4560         else if (len >= 2)
4561         {
4562             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4563             if (ret && minutes >= 60)
4564             {
4565                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4566                 ret = FALSE;
4567             }
4568         }
4569         if (ret)
4570         {
4571             if (sign == '+')
4572             {
4573                 sysTime->wHour += hours;
4574                 sysTime->wMinute += minutes;
4575             }
4576             else
4577             {
4578                 if (hours > sysTime->wHour)
4579                 {
4580                     sysTime->wDay--;
4581                     sysTime->wHour = 24 - (hours - sysTime->wHour);
4582                 }
4583                 else
4584                     sysTime->wHour -= hours;
4585                 if (minutes > sysTime->wMinute)
4586                 {
4587                     sysTime->wHour--;
4588                     sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4589                 }
4590                 else
4591                     sysTime->wMinute -= minutes;
4592             }
4593         }
4594     }
4595     return ret;
4596 }
4597
4598 #define MIN_ENCODED_TIME_LENGTH 10
4599
4600 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4601  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4602  DWORD *pcbDecoded)
4603 {
4604     BOOL ret = FALSE;
4605
4606     if (pbEncoded[0] == ASN_UTCTIME)
4607     {
4608         if (cbEncoded <= 1)
4609             SetLastError(CRYPT_E_ASN1_EOD);
4610         else if (pbEncoded[1] > 0x7f)
4611         {
4612             /* long-form date strings really can't be valid */
4613             SetLastError(CRYPT_E_ASN1_CORRUPT);
4614         }
4615         else
4616         {
4617             SYSTEMTIME sysTime = { 0 };
4618             BYTE len = pbEncoded[1];
4619
4620             if (len < MIN_ENCODED_TIME_LENGTH)
4621                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4622             else
4623             {
4624                 ret = TRUE;
4625                 if (pcbDecoded)
4626                     *pcbDecoded = 2 + len;
4627                 pbEncoded += 2;
4628                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4629                 if (sysTime.wYear >= 50)
4630                     sysTime.wYear += 1900;
4631                 else
4632                     sysTime.wYear += 2000;
4633                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4634                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4635                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4636                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4637                 if (ret && len > 0)
4638                 {
4639                     if (len >= 2 && isdigit(*pbEncoded) &&
4640                      isdigit(*(pbEncoded + 1)))
4641                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4642                          sysTime.wSecond);
4643                     else if (isdigit(*pbEncoded))
4644                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4645                          sysTime.wSecond);
4646                     if (ret)
4647                         ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4648                          &sysTime);
4649                 }
4650                 if (ret)
4651                 {
4652                     if (!pvStructInfo)
4653                         *pcbStructInfo = sizeof(FILETIME);
4654                     else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4655                      sizeof(FILETIME))))
4656                         ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4657                 }
4658             }
4659         }
4660     }
4661     else
4662         SetLastError(CRYPT_E_ASN1_BADTAG);
4663     return ret;
4664 }
4665
4666 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4667  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4668  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4669 {
4670     BOOL ret = FALSE;
4671
4672     __TRY
4673     {
4674         DWORD bytesNeeded;
4675
4676         ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4677          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4678         if (ret)
4679         {
4680             if (!pvStructInfo)
4681                 *pcbStructInfo = bytesNeeded;
4682             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4683              pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4684             {
4685                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4686                     pvStructInfo = *(BYTE **)pvStructInfo;
4687                 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4688                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4689                  &bytesNeeded, NULL);
4690             }
4691         }
4692     }
4693     __EXCEPT_PAGE_FAULT
4694     {
4695         SetLastError(STATUS_ACCESS_VIOLATION);
4696     }
4697     __ENDTRY
4698     return ret;
4699 }
4700
4701 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4702  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4703  DWORD *pcbDecoded)
4704 {
4705     BOOL ret = FALSE;
4706
4707     if (pbEncoded[0] == ASN_GENERALTIME)
4708     {
4709         if (cbEncoded <= 1)
4710             SetLastError(CRYPT_E_ASN1_EOD);
4711         else if (pbEncoded[1] > 0x7f)
4712         {
4713             /* long-form date strings really can't be valid */
4714             SetLastError(CRYPT_E_ASN1_CORRUPT);
4715         }
4716         else
4717         {
4718             BYTE len = pbEncoded[1];
4719
4720             if (len < MIN_ENCODED_TIME_LENGTH)
4721                 SetLastError(CRYPT_E_ASN1_CORRUPT);
4722             else
4723             {
4724                 SYSTEMTIME sysTime = { 0 };
4725
4726                 ret = TRUE;
4727                 if (pcbDecoded)
4728                     *pcbDecoded = 2 + len;
4729                 pbEncoded += 2;
4730                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4731                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4732                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4733                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4734                 if (ret && len > 0)
4735                 {
4736                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4737                      sysTime.wMinute);
4738                     if (ret && len > 0)
4739                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4740                          sysTime.wSecond);
4741                     if (ret && len > 0 && (*pbEncoded == '.' ||
4742                      *pbEncoded == ','))
4743                     {
4744                         BYTE digits;
4745
4746                         pbEncoded++;
4747                         len--;
4748                         /* workaround macro weirdness */
4749                         digits = min(len, 3);
4750                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4751                          sysTime.wMilliseconds);
4752                     }
4753                     if (ret)
4754                         ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4755                          &sysTime);
4756                 }
4757                 if (ret)
4758                 {
4759                     if (!pvStructInfo)
4760                         *pcbStructInfo = sizeof(FILETIME);
4761                     else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4762                      sizeof(FILETIME))))
4763                         ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4764                 }
4765             }
4766         }
4767     }
4768     else
4769         SetLastError(CRYPT_E_ASN1_BADTAG);
4770     return ret;
4771 }
4772
4773 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4774  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4775  DWORD *pcbDecoded)
4776 {
4777     BOOL ret;
4778     InternalDecodeFunc decode = NULL;
4779
4780     if (pbEncoded[0] == ASN_UTCTIME)
4781         decode = CRYPT_AsnDecodeUtcTimeInternal;
4782     else if (pbEncoded[0] == ASN_GENERALTIME)
4783         decode = CRYPT_AsnDecodeGeneralizedTime;
4784     if (decode)
4785         ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4786          pcbStructInfo, pcbDecoded);
4787     else
4788     {
4789         SetLastError(CRYPT_E_ASN1_BADTAG);
4790         ret = FALSE;
4791     }
4792     return ret;
4793 }
4794
4795 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4796  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4797  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4798 {
4799     BOOL ret;
4800
4801     __TRY
4802     {
4803         DWORD bytesNeeded;
4804
4805         ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4806          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4807         if (ret)
4808         {
4809             if (!pvStructInfo)
4810                 *pcbStructInfo = bytesNeeded;
4811             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4812              pvStructInfo, pcbStructInfo, bytesNeeded)))
4813             {
4814                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4815                     pvStructInfo = *(BYTE **)pvStructInfo;
4816                 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4817                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4818                  &bytesNeeded, NULL);
4819             }
4820         }
4821     }
4822     __EXCEPT_PAGE_FAULT
4823     {
4824         SetLastError(STATUS_ACCESS_VIOLATION);
4825         ret = FALSE;
4826     }
4827     __ENDTRY
4828     return ret;
4829 }
4830
4831 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4832  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4833  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4834 {
4835     BOOL ret = TRUE;
4836
4837     __TRY
4838     {
4839         if (pbEncoded[0] == ASN_SEQUENCEOF)
4840         {
4841             DWORD bytesNeeded, dataLen, remainingLen, cValue;
4842
4843             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4844             {
4845                 BYTE lenBytes;
4846                 const BYTE *ptr;
4847
4848                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4849                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4850                 cValue = 0;
4851                 ptr = pbEncoded + 1 + lenBytes;
4852                 remainingLen = dataLen;
4853                 while (ret && remainingLen)
4854                 {
4855                     DWORD nextLen;
4856
4857                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4858                     if (ret)
4859                     {
4860                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4861
4862                         remainingLen -= 1 + nextLenBytes + nextLen;
4863                         ptr += 1 + nextLenBytes + nextLen;
4864                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
4865                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4866                             bytesNeeded += 1 + nextLenBytes + nextLen;
4867                         cValue++;
4868                     }
4869                 }
4870                 if (ret)
4871                 {
4872                     CRYPT_SEQUENCE_OF_ANY *seq;
4873                     BYTE *nextPtr;
4874                     DWORD i;
4875
4876                     if (!pvStructInfo)
4877                         *pcbStructInfo = bytesNeeded;
4878                     else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4879                      pvStructInfo, pcbStructInfo, bytesNeeded)))
4880                     {
4881                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4882                             pvStructInfo = *(BYTE **)pvStructInfo;
4883                         seq = pvStructInfo;
4884                         seq->cValue = cValue;
4885                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4886                          sizeof(*seq));
4887                         nextPtr = (BYTE *)seq->rgValue +
4888                          cValue * sizeof(CRYPT_DER_BLOB);
4889                         ptr = pbEncoded + 1 + lenBytes;
4890                         remainingLen = dataLen;
4891                         i = 0;
4892                         while (ret && remainingLen)
4893                         {
4894                             DWORD nextLen;
4895
4896                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4897                             if (ret)
4898                             {
4899                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4900
4901                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
4902                                  nextLen;
4903                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4904                                     seq->rgValue[i].pbData = (BYTE *)ptr;
4905                                 else
4906                                 {
4907                                     seq->rgValue[i].pbData = nextPtr;
4908                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
4909                                      nextLen);
4910                                     nextPtr += 1 + nextLenBytes + nextLen;
4911                                 }
4912                                 remainingLen -= 1 + nextLenBytes + nextLen;
4913                                 ptr += 1 + nextLenBytes + nextLen;
4914                                 i++;
4915                             }
4916                         }
4917                     }
4918                 }
4919             }
4920         }
4921         else
4922         {
4923             SetLastError(CRYPT_E_ASN1_BADTAG);
4924             ret = FALSE;
4925         }
4926     }
4927     __EXCEPT_PAGE_FAULT
4928     {
4929         SetLastError(STATUS_ACCESS_VIOLATION);
4930         ret = FALSE;
4931     }
4932     __ENDTRY
4933     return ret;
4934 }
4935
4936 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4937  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4938  DWORD *pcbDecoded)
4939 {
4940     BOOL ret;
4941
4942     if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4943     {
4944         DWORD bytesNeeded, dataLen;
4945
4946         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4947         {
4948             struct AsnArrayDescriptor arrayDesc = {
4949              ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4950              sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4951              offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4952             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4953             DWORD nameLen;
4954
4955             if (dataLen)
4956             {
4957                 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
4958                  pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4959                  NULL, NULL, &nameLen, NULL);
4960                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
4961             }
4962             else
4963                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4964             if (pcbDecoded)
4965                 *pcbDecoded = 1 + lenBytes + dataLen;
4966             if (!pvStructInfo)
4967                 *pcbStructInfo = bytesNeeded;
4968             else if (*pcbStructInfo < bytesNeeded)
4969             {
4970                 *pcbStructInfo = bytesNeeded;
4971                 SetLastError(ERROR_MORE_DATA);
4972                 ret = FALSE;
4973             }
4974             else
4975             {
4976                 CRL_DIST_POINT_NAME *name = pvStructInfo;
4977
4978                 *pcbStructInfo = bytesNeeded;
4979                 if (dataLen)
4980                 {
4981                     name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4982                     ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
4983                      pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4984                      &name->u.FullName.cAltEntry, name->u.FullName.rgAltEntry,
4985                      &nameLen, NULL);
4986                 }
4987                 else
4988                     name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4989             }
4990         }
4991     }
4992     else
4993     {
4994         SetLastError(CRYPT_E_ASN1_BADTAG);
4995         ret = FALSE;
4996     }
4997     return ret;
4998 }
4999
5000 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5001  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5002 {
5003     struct AsnDecodeSequenceItem items[] = {
5004      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5005        DistPointName), CRYPT_AsnDecodeDistPointName,
5006        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5007        DistPointName.u.FullName.rgAltEntry), 0 },
5008      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5009        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5010        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5011      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5012        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5013        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5014     };
5015     CRL_DIST_POINT *point = pvStructInfo;
5016     BOOL ret;
5017
5018     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5019      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5020      pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5021     return ret;
5022 }
5023
5024 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5025  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5026  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5027 {
5028     BOOL ret;
5029
5030     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5031      pDecodePara, pvStructInfo, *pcbStructInfo);
5032
5033     __TRY
5034     {
5035         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5036          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5037          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5038
5039         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5040          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
5041     }
5042     __EXCEPT_PAGE_FAULT
5043     {
5044         SetLastError(STATUS_ACCESS_VIOLATION);
5045         ret = FALSE;
5046     }
5047     __ENDTRY
5048     return ret;
5049 }
5050
5051 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5052  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5053  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5054 {
5055     BOOL ret;
5056
5057     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5058      pDecodePara, pvStructInfo, *pcbStructInfo);
5059
5060     __TRY
5061     {
5062         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5063          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5064
5065         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5066          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
5067     }
5068     __EXCEPT_PAGE_FAULT
5069     {
5070         SetLastError(STATUS_ACCESS_VIOLATION);
5071         ret = FALSE;
5072     }
5073     __ENDTRY
5074     return ret;
5075 }
5076
5077 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5078  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5079  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5080 {
5081     BOOL ret;
5082
5083     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5084      pDecodePara, pvStructInfo, *pcbStructInfo);
5085
5086     __TRY
5087     {
5088         struct AsnDecodeSequenceItem items[] = {
5089          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5090            DistPointName), CRYPT_AsnDecodeDistPointName,
5091            sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5092            offsetof(CRL_ISSUING_DIST_POINT,
5093            DistPointName.u.FullName.rgAltEntry), 0 },
5094          { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5095            fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5096            FALSE, 0 },
5097          { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5098            fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5099            FALSE, 0 },
5100          { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5101            OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5102            sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5103            OnlySomeReasonFlags.pbData), 0 },
5104          { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5105            fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5106         };
5107
5108         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5109          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5110          pcbStructInfo, NULL, NULL);
5111     }
5112     __EXCEPT_PAGE_FAULT
5113     {
5114         SetLastError(STATUS_ACCESS_VIOLATION);
5115         ret = FALSE;
5116     }
5117     __ENDTRY
5118     return ret;
5119 }
5120
5121 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5122  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5123  DWORD *pcbDecoded)
5124 {
5125     BOOL ret = FALSE;
5126
5127     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5128      pvStructInfo, *pcbStructInfo, pcbDecoded);
5129
5130     if (!cbEncoded)
5131     {
5132         SetLastError(CRYPT_E_ASN1_EOD);
5133         return FALSE;
5134     }
5135     if (pbEncoded[0] != (ASN_CONTEXT | 1))
5136     {
5137         SetLastError(CRYPT_E_ASN1_BADTAG);
5138         return FALSE;
5139     }
5140     /* The BOOL is implicit:  if the integer is present, then it's TRUE */
5141     ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5142      pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
5143      pcbDecoded);
5144     if (ret && pvStructInfo)
5145         *(BOOL *)pvStructInfo = TRUE;
5146     TRACE("returning %d\n", ret);
5147     return ret;
5148 }
5149
5150 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5151  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5152  DWORD *pcbDecoded)
5153 {
5154     BOOL ret;
5155     struct AsnDecodeSequenceItem items[] = {
5156      { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5157        CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5158        offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5159      { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5160        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5161      { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5162        CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
5163        0 },
5164     };
5165     CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5166
5167     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5168      pvStructInfo, *pcbStructInfo, pcbDecoded);
5169
5170     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5171      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5172      pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5173     if (pcbDecoded)
5174     {
5175         TRACE("%d\n", *pcbDecoded);
5176         if (*pcbDecoded < cbEncoded)
5177             TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5178              *(pbEncoded + *pcbDecoded + 1));
5179     }
5180     TRACE("returning %d\n", ret);
5181     return ret;
5182 }
5183
5184 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5185  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5186  DWORD *pcbDecoded)
5187 {
5188     BOOL ret = TRUE;
5189     struct AsnArrayDescriptor arrayDesc = { 0,
5190      CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5191      offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5192     DWORD bytesNeeded;
5193
5194     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5195      pvStructInfo, *pcbStructInfo, pcbDecoded);
5196
5197     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5198      NULL, NULL, &bytesNeeded, pcbDecoded)))
5199     {
5200         bytesNeeded += MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO,
5201          cPermittedSubtree, cExcludedSubtree);
5202         if (!pvStructInfo)
5203             *pcbStructInfo = bytesNeeded;
5204         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5205          pcbStructInfo, bytesNeeded)))
5206         {
5207             CERT_NAME_CONSTRAINTS_INFO *info = (CERT_NAME_CONSTRAINTS_INFO *)
5208              ((BYTE *)pvStructInfo -
5209              offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree));
5210
5211             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5212              &info->cPermittedSubtree, info->rgPermittedSubtree, &bytesNeeded,
5213              pcbDecoded);
5214         }
5215     }
5216     return ret;
5217 }
5218
5219 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5220  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5221  DWORD *pcbDecoded)
5222 {
5223     BOOL ret = TRUE;
5224     struct AsnArrayDescriptor arrayDesc = { 0,
5225      CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5226      offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5227     DWORD bytesNeeded;
5228
5229     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5230      pvStructInfo, *pcbStructInfo, pcbDecoded);
5231
5232     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5233      NULL, NULL, &bytesNeeded, pcbDecoded)))
5234     {
5235         bytesNeeded += FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO,
5236          cExcludedSubtree);
5237         if (!pvStructInfo)
5238             *pcbStructInfo = bytesNeeded;
5239         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5240          pcbStructInfo, bytesNeeded)))
5241         {
5242             CERT_NAME_CONSTRAINTS_INFO *info = (CERT_NAME_CONSTRAINTS_INFO *)
5243              ((BYTE *)pvStructInfo -
5244              offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree));
5245
5246             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5247              &info->cExcludedSubtree, info->rgExcludedSubtree, &bytesNeeded,
5248              pcbDecoded);
5249         }
5250     }
5251     return ret;
5252 }
5253
5254 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5255  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5256  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5257 {
5258     BOOL ret = FALSE;
5259
5260     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5261      pDecodePara, pvStructInfo, *pcbStructInfo);
5262
5263     __TRY
5264     {
5265         struct AsnDecodeSequenceItem items[] = {
5266          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5267            offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5268            CRYPT_AsnDecodePermittedSubtree,
5269            MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5270            cExcludedSubtree), TRUE, TRUE,
5271            offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5272          { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5273            offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5274            CRYPT_AsnDecodeExcludedSubtree,
5275            FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5276            TRUE, TRUE,
5277            offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5278         };
5279
5280         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5281          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5282          pcbStructInfo, NULL, NULL);
5283     }
5284     __EXCEPT_PAGE_FAULT
5285     {
5286         SetLastError(STATUS_ACCESS_VIOLATION);
5287     }
5288     __ENDTRY
5289     return ret;
5290 }
5291
5292 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5293  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5294  DWORD *pcbDecoded)
5295 {
5296     BOOL ret;
5297     struct AsnDecodeSequenceItem items[] = {
5298      { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5299        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5300        Issuer.pbData) },
5301      { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5302        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5303        TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5304     };
5305     CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5306
5307     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5308      pvStructInfo, *pcbStructInfo, pcbDecoded);
5309
5310     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5311      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5312      pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5313     if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5314     {
5315         SetLastError(CRYPT_E_ASN1_CORRUPT);
5316         ret = FALSE;
5317     }
5318     TRACE("returning %d\n", ret);
5319     return ret;
5320 }
5321
5322 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5323  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5324  DWORD *pcbDecoded)
5325 {
5326     CMSG_SIGNER_INFO *info = pvStructInfo;
5327     struct AsnDecodeSequenceItem items[] = {
5328      { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5329        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5330      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5331        CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5332        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5333      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5334        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5335        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5336      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5337        offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5338        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5339        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5340      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5341        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5342        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5343        HashEncryptionAlgorithm.pszObjId), 0 },
5344      { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5345        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5346        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5347      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5348        offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5349        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5350        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5351     };
5352     BOOL ret;
5353
5354     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5355      pvStructInfo, *pcbStructInfo);
5356
5357     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5358      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5359      pcbDecoded, info ? info->Issuer.pbData : NULL);
5360     return ret;
5361 }
5362
5363 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5364  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5365  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5366 {
5367     BOOL ret = FALSE;
5368
5369     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5370      pDecodePara, pvStructInfo, *pcbStructInfo);
5371
5372     __TRY
5373     {
5374         ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5375          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5376         if (ret && pvStructInfo)
5377         {
5378             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5379              pcbStructInfo, *pcbStructInfo);
5380             if (ret)
5381             {
5382                 CMSG_SIGNER_INFO *info;
5383
5384                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5385                     pvStructInfo = *(BYTE **)pvStructInfo;
5386                 info = pvStructInfo;
5387                 info->Issuer.pbData = ((BYTE *)info +
5388                  sizeof(CMSG_SIGNER_INFO));
5389                 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5390                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5391                  pcbStructInfo, NULL);
5392             }
5393         }
5394     }
5395     __EXCEPT_PAGE_FAULT
5396     {
5397         SetLastError(STATUS_ACCESS_VIOLATION);
5398     }
5399     __ENDTRY
5400     TRACE("returning %d\n", ret);
5401     return ret;
5402 }
5403
5404 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5405  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5406  DWORD *pcbDecoded)
5407 {
5408     BOOL ret;
5409     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
5410      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5411     DWORD bytesNeeded;
5412
5413     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5414      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5415
5416     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5417      NULL, NULL, &bytesNeeded, pcbDecoded)))
5418     {
5419         bytesNeeded += MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded);
5420         if (!pvStructInfo)
5421             *pcbStructInfo = bytesNeeded;
5422         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5423          pcbStructInfo, bytesNeeded)))
5424         {
5425             CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5426              ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cCertEncoded));
5427
5428             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5429              &info->cCertEncoded, info->rgCertEncoded, &bytesNeeded,
5430              pcbDecoded);
5431         }
5432     }
5433     return ret;
5434 }
5435
5436 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5437  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5438  DWORD *pcbDecoded)
5439 {
5440     BOOL ret;
5441     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
5442      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5443     DWORD bytesNeeded;
5444
5445     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5446      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5447
5448     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5449      NULL, NULL, &bytesNeeded, pcbDecoded)))
5450     {
5451         bytesNeeded += MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content);
5452         if (!pvStructInfo)
5453             *pcbStructInfo = bytesNeeded;
5454         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5455          pcbStructInfo, bytesNeeded)))
5456         {
5457             CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5458              ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cCrlEncoded));
5459
5460             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5461              &info->cCrlEncoded, info->rgCrlEncoded, &bytesNeeded,
5462              pcbDecoded);
5463         }
5464     }
5465     return ret;
5466 }
5467
5468 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5469  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5470  DWORD *pcbDecoded)
5471 {
5472     CERT_ID *id = pvStructInfo;
5473     BOOL ret = FALSE;
5474
5475     if (*pbEncoded == ASN_SEQUENCEOF)
5476     {
5477         ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5478          id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5479         if (ret)
5480         {
5481             if (id)
5482                 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5483             if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5484                 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5485                  sizeof(CERT_ISSUER_SERIAL_NUMBER);
5486             else
5487                 *pcbStructInfo = sizeof(CERT_ID);
5488         }
5489     }
5490     else if (*pbEncoded == (ASN_CONTEXT | 0))
5491     {
5492         ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5493          id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5494         if (ret)
5495         {
5496             if (id)
5497                 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5498             if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5499                 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5500                  sizeof(CRYPT_DATA_BLOB);
5501             else
5502                 *pcbStructInfo = sizeof(CERT_ID);
5503         }
5504     }
5505     else
5506         SetLastError(CRYPT_E_ASN1_BADTAG);
5507     return ret;
5508 }
5509
5510 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5511  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5512  DWORD *pcbDecoded)
5513 {
5514     CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5515     struct AsnDecodeSequenceItem items[] = {
5516      { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5517        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5518      { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5519        CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5520        offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5521      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5522        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5523        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5524      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5525        offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5526        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5527        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5528      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5529        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5530        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5531        HashEncryptionAlgorithm.pszObjId), 0 },
5532      { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5533        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5534        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5535      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5536        offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5537        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5538        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5539     };
5540     BOOL ret;
5541
5542     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5543      pvStructInfo, *pcbStructInfo);
5544
5545     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5546      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5547      pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5548     return ret;
5549 }
5550
5551 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5552  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5553  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5554 {
5555     BOOL ret = FALSE;
5556
5557     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5558      pDecodePara, pvStructInfo, *pcbStructInfo);
5559
5560     __TRY
5561     {
5562         ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5563          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5564         if (ret && pvStructInfo)
5565         {
5566             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5567              pcbStructInfo, *pcbStructInfo);
5568             if (ret)
5569             {
5570                 CMSG_CMS_SIGNER_INFO *info;
5571
5572                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5573                     pvStructInfo = *(BYTE **)pvStructInfo;
5574                 info = pvStructInfo;
5575                 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5576                  sizeof(CMSG_CMS_SIGNER_INFO));
5577                 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5578                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5579                  pcbStructInfo, NULL);
5580             }
5581         }
5582     }
5583     __EXCEPT_PAGE_FAULT
5584     {
5585         SetLastError(STATUS_ACCESS_VIOLATION);
5586     }
5587     __ENDTRY
5588     TRACE("returning %d\n", ret);
5589     return ret;
5590 }
5591
5592 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5593  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5594 {
5595     BOOL ret;
5596     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5597      CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5598      offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5599     DWORD bytesNeeded;
5600
5601     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5602      pvStructInfo, *pcbStructInfo, pcbDecoded);
5603
5604     if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5605      NULL, NULL, &bytesNeeded, pcbDecoded)))
5606     {
5607         bytesNeeded += FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo);
5608         if (!pvStructInfo)
5609             *pcbStructInfo = bytesNeeded;
5610         else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5611          pcbStructInfo, bytesNeeded)))
5612         {
5613             CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5614              ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cSignerInfo));
5615
5616             ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5617              &info->cSignerInfo, info->rgSignerInfo, &bytesNeeded,
5618              pcbDecoded);
5619         }
5620     }
5621     return ret;
5622 }
5623
5624 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5625  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5626  CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5627 {
5628     BOOL ret = FALSE;
5629     struct AsnDecodeSequenceItem items[] = {
5630      { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5631        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5632      /* Placeholder for the hash algorithms - redundant with those in the
5633       * signers, so just ignore them.
5634       */
5635      { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5636      { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5637        CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5638        FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5639      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5640        offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5641        MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5642        offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5643      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5644        offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5645        MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5646        offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5647      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5648        CRYPT_DecodeSignerArray,
5649        FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5650        offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5651     };
5652
5653     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5654      pDecodePara, signedInfo, *pcbSignedInfo);
5655
5656     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5657      pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5658      NULL, NULL);
5659     TRACE("returning %d\n", ret);
5660     return ret;
5661 }
5662
5663 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5664  LPCSTR lpszStructType)
5665 {
5666     CryptDecodeObjectExFunc decodeFunc = NULL;
5667
5668     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5669      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5670     {
5671         SetLastError(ERROR_FILE_NOT_FOUND);
5672         return NULL;
5673     }
5674     if (!HIWORD(lpszStructType))
5675     {
5676         switch (LOWORD(lpszStructType))
5677         {
5678         case LOWORD(X509_CERT):
5679             decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5680             break;
5681         case LOWORD(X509_CERT_TO_BE_SIGNED):
5682             decodeFunc = CRYPT_AsnDecodeCert;
5683             break;
5684         case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5685             decodeFunc = CRYPT_AsnDecodeCRL;
5686             break;
5687         case LOWORD(X509_EXTENSIONS):
5688             decodeFunc = CRYPT_AsnDecodeExtensions;
5689             break;
5690         case LOWORD(X509_NAME_VALUE):
5691             decodeFunc = CRYPT_AsnDecodeNameValue;
5692             break;
5693         case LOWORD(X509_NAME):
5694             decodeFunc = CRYPT_AsnDecodeName;
5695             break;
5696         case LOWORD(X509_PUBLIC_KEY_INFO):
5697             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5698             break;
5699         case LOWORD(X509_AUTHORITY_KEY_ID):
5700             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5701             break;
5702         case LOWORD(X509_ALTERNATE_NAME):
5703             decodeFunc = CRYPT_AsnDecodeAltName;
5704             break;
5705         case LOWORD(X509_BASIC_CONSTRAINTS):
5706             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5707             break;
5708         case LOWORD(X509_BASIC_CONSTRAINTS2):
5709             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5710             break;
5711         case LOWORD(X509_CERT_POLICIES):
5712             decodeFunc = CRYPT_AsnDecodeCertPolicies;
5713             break;
5714         case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5715             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5716             break;
5717         case LOWORD(X509_UNICODE_NAME):
5718             decodeFunc = CRYPT_AsnDecodeUnicodeName;
5719             break;
5720         case LOWORD(PKCS_ATTRIBUTE):
5721             decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5722             break;
5723         case LOWORD(X509_UNICODE_NAME_VALUE):
5724             decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5725             break;
5726         case LOWORD(X509_OCTET_STRING):
5727             decodeFunc = CRYPT_AsnDecodeOctets;
5728             break;
5729         case LOWORD(X509_BITS):
5730         case LOWORD(X509_KEY_USAGE):
5731             decodeFunc = CRYPT_AsnDecodeBits;
5732             break;
5733         case LOWORD(X509_INTEGER):
5734             decodeFunc = CRYPT_AsnDecodeInt;
5735             break;
5736         case LOWORD(X509_MULTI_BYTE_INTEGER):
5737             decodeFunc = CRYPT_AsnDecodeInteger;
5738             break;
5739         case LOWORD(X509_MULTI_BYTE_UINT):
5740             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5741             break;
5742         case LOWORD(X509_ENUMERATED):
5743             decodeFunc = CRYPT_AsnDecodeEnumerated;
5744             break;
5745         case LOWORD(X509_CHOICE_OF_TIME):
5746             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5747             break;
5748         case LOWORD(X509_AUTHORITY_KEY_ID2):
5749             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5750             break;
5751         case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5752             decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5753             break;
5754         case LOWORD(PKCS_CONTENT_INFO):
5755             decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5756             break;
5757         case LOWORD(X509_SEQUENCE_OF_ANY):
5758             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5759             break;
5760         case LOWORD(PKCS_UTC_TIME):
5761             decodeFunc = CRYPT_AsnDecodeUtcTime;
5762             break;
5763         case LOWORD(X509_CRL_DIST_POINTS):
5764             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5765             break;
5766         case LOWORD(X509_ENHANCED_KEY_USAGE):
5767             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5768             break;
5769         case LOWORD(PKCS_CTL):
5770             decodeFunc = CRYPT_AsnDecodeCTL;
5771             break;
5772         case LOWORD(PKCS_SMIME_CAPABILITIES):
5773             decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5774             break;
5775         case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5776             decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5777             break;
5778         case LOWORD(PKCS_ATTRIBUTES):
5779             decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5780             break;
5781         case LOWORD(X509_ISSUING_DIST_POINT):
5782             decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5783             break;
5784         case LOWORD(X509_NAME_CONSTRAINTS):
5785             decodeFunc = CRYPT_AsnDecodeNameConstraints;
5786             break;
5787         case LOWORD(PKCS7_SIGNER_INFO):
5788             decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5789             break;
5790         case LOWORD(CMS_SIGNER_INFO):
5791             decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5792             break;
5793         }
5794     }
5795     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5796         decodeFunc = CRYPT_AsnDecodeExtensions;
5797     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5798         decodeFunc = CRYPT_AsnDecodeUtcTime;
5799     else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5800         decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5801     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5802         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5803     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5804         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5805     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5806         decodeFunc = CRYPT_AsnDecodeEnumerated;
5807     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5808         decodeFunc = CRYPT_AsnDecodeBits;
5809     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5810         decodeFunc = CRYPT_AsnDecodeOctets;
5811     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5812         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5813     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5814         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5815     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5816         decodeFunc = CRYPT_AsnDecodeAltName;
5817     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5818         decodeFunc = CRYPT_AsnDecodeAltName;
5819     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5820         decodeFunc = CRYPT_AsnDecodeAltName;
5821     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5822         decodeFunc = CRYPT_AsnDecodeAltName;
5823     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5824         decodeFunc = CRYPT_AsnDecodeAltName;
5825     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5826         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5827     else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5828         decodeFunc = CRYPT_AsnDecodeCertPolicies;
5829     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5830         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5831     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5832         decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5833     else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5834         decodeFunc = CRYPT_AsnDecodeNameConstraints;
5835     else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5836         decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5837     else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5838         decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5839     else if (!strcmp(lpszStructType, szOID_CTL))
5840         decodeFunc = CRYPT_AsnDecodeCTL;
5841     return decodeFunc;
5842 }
5843
5844 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5845  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5846 {
5847     static HCRYPTOIDFUNCSET set = NULL;
5848     CryptDecodeObjectFunc decodeFunc = NULL;
5849
5850     if (!set)
5851         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5852     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5853      (void **)&decodeFunc, hFunc);
5854     return decodeFunc;
5855 }
5856
5857 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5858  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5859 {
5860     static HCRYPTOIDFUNCSET set = NULL;
5861     CryptDecodeObjectExFunc decodeFunc = NULL;
5862
5863     if (!set)
5864         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5865     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5866      (void **)&decodeFunc, hFunc);
5867     return decodeFunc;
5868 }
5869
5870 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5871  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5872  DWORD *pcbStructInfo)
5873 {
5874     BOOL ret = FALSE;
5875     CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5876     CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5877     HCRYPTOIDFUNCADDR hFunc = NULL;
5878
5879     TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5880      debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5881      pvStructInfo, pcbStructInfo);
5882
5883     if (!pvStructInfo && !pcbStructInfo)
5884     {
5885         SetLastError(ERROR_INVALID_PARAMETER);
5886         return FALSE;
5887     }
5888     if (cbEncoded > MAX_ENCODED_LEN)
5889     {
5890         SetLastError(CRYPT_E_ASN1_LARGE);
5891         return FALSE;
5892     }
5893
5894     if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5895      lpszStructType)))
5896     {
5897         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5898          debugstr_a(lpszStructType));
5899         pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5900          lpszStructType, &hFunc);
5901         if (!pCryptDecodeObject)
5902             pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5903              lpszStructType, &hFunc);
5904     }
5905     if (pCryptDecodeObject)
5906         ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5907          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5908     else if (pCryptDecodeObjectEx)
5909         ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5910          pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5911          pvStructInfo, pcbStructInfo);
5912     if (hFunc)
5913         CryptFreeOIDFunctionAddress(hFunc, 0);
5914     TRACE_(crypt)("returning %d\n", ret);
5915     return ret;
5916 }
5917
5918 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5919  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5920  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5921 {
5922     BOOL ret = FALSE;
5923     CryptDecodeObjectExFunc decodeFunc;
5924     HCRYPTOIDFUNCADDR hFunc = NULL;
5925
5926     TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5927      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5928      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5929
5930     if (!pvStructInfo && !pcbStructInfo)
5931     {
5932         SetLastError(ERROR_INVALID_PARAMETER);
5933         return FALSE;
5934     }
5935     if (cbEncoded > MAX_ENCODED_LEN)
5936     {
5937         SetLastError(CRYPT_E_ASN1_LARGE);
5938         return FALSE;
5939     }
5940
5941     SetLastError(NOERROR);
5942     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5943         *(BYTE **)pvStructInfo = NULL;
5944     decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5945     if (!decodeFunc)
5946     {
5947         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5948          debugstr_a(lpszStructType));
5949         decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5950          &hFunc);
5951     }
5952     if (decodeFunc)
5953         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5954          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5955     else
5956     {
5957         CryptDecodeObjectFunc pCryptDecodeObject =
5958          CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5959
5960         /* Try CryptDecodeObject function.  Don't call CryptDecodeObject
5961          * directly, as that could cause an infinite loop.
5962          */
5963         if (pCryptDecodeObject)
5964         {
5965             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5966             {
5967                 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5968                  pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5969                 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5970                  pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5971                     ret = pCryptDecodeObject(dwCertEncodingType,
5972                      lpszStructType, pbEncoded, cbEncoded, dwFlags,
5973                      *(BYTE **)pvStructInfo, pcbStructInfo);
5974             }
5975             else
5976                 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5977                  pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5978         }
5979     }
5980     if (hFunc)
5981         CryptFreeOIDFunctionAddress(hFunc, 0);
5982     TRACE_(crypt)("returning %d\n", ret);
5983     return ret;
5984 }
5985
5986 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
5987 {
5988     BOOL ret;
5989
5990     TRACE_(crypt)("(%p)\n", pPFX);
5991
5992     /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
5993      * version integer of length 1 (3 encoded byes) and at least one other
5994      * datum (two encoded bytes), plus at least two bytes for the outer
5995      * sequence.  Thus, even an empty PFX blob is at least 7 bytes in length.
5996      */
5997     if (pPFX->cbData < 7)
5998         ret = FALSE;
5999     else if (pPFX->pbData[0] == ASN_SEQUENCE)
6000     {
6001         DWORD len;
6002
6003         if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
6004         {
6005             BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
6006
6007             /* Need at least three bytes for the integer version */
6008             if (pPFX->cbData < 1 + lenLen + 3)
6009                 ret = FALSE;
6010             else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
6011              pPFX->pbData[1 + lenLen + 1] != 1 ||          /* Definite length */
6012              pPFX->pbData[1 + lenLen + 2] != 3)            /* PFX version */
6013                 ret = FALSE;
6014         }
6015     }
6016     else
6017         ret = FALSE;
6018     return ret;
6019 }
6020
6021 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
6022  DWORD dwFlags)
6023 {
6024     FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
6025     return NULL;
6026 }