crypt32: Get rid of bogus check and improve traces for unexpected alt name entry...
[wine] / dlls / crypt32 / decode.c
1 /*
2  * Copyright 2005 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 is
21  * undocumented, 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:
31  * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
32  */
33
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #define NONAMELESSUNION
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "winnls.h"
45 #include "snmp.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
49
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
52
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK  0x1f
55
56 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
57
58 struct GenericArray
59 {
60     DWORD cItems;
61     BYTE *rgItems;
62 };
63
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65  DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67  DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
68
69 /* Prototypes for built-in decoders.  They follow the Ex style prototypes.
70  * The dwCertEncodingType and lpszStructType are ignored by the built-in
71  * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72  * since it must call functions in external DLLs that follow these signatures.
73  */
74 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
75  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
76  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
77 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
78  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
79  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81  * time, doesn't do memory allocation, and doesn't do exception handling.
82  * (This isn't intended to be the externally-called one.)
83  */
84 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
85  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 /* Assumes algo->Parameters.pbData is set ahead of time.  Internal func. */
88 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
89  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
90  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* Internal function */
92 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
93  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
94  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
97  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
98  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100  * member has been initialized, doesn't do exception handling, and doesn't do
101  * memory allocation.
102  */
103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
104  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
105  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
106 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
107  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
108  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
109 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
110  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113  * member has been initialized, doesn't do exception handling, and doesn't do
114  * memory allocation.  Also doesn't check tag, assumes the caller has checked
115  * it.
116  */
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned.  */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124  void *pvStructInfo, DWORD *pcbStructInfo);
125
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128  DWORD *pcbStructInfo)
129 {
130     static HCRYPTOIDFUNCSET set = NULL;
131     BOOL ret = FALSE;
132     CryptDecodeObjectFunc pCryptDecodeObject;
133     HCRYPTOIDFUNCADDR hFunc;
134
135     TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
136      debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137      pvStructInfo, pcbStructInfo);
138
139     if (!pvStructInfo && !pcbStructInfo)
140     {
141         SetLastError(ERROR_INVALID_PARAMETER);
142         return FALSE;
143     }
144
145     /* Try registered DLL first.. */
146     if (!set)
147         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149      (void **)&pCryptDecodeObject, &hFunc);
150     if (pCryptDecodeObject)
151     {
152         ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154         CryptFreeOIDFunctionAddress(hFunc, 0);
155     }
156     else
157     {
158         /* If not, use CryptDecodeObjectEx */
159         ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160          cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
161     }
162     return ret;
163 }
164
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
167
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169  * where pbEncoded[0] is the tag.  If the data are too short to contain a
170  * length or if the length is too large for cbEncoded, sets an appropriate
171  * error code and returns FALSE.
172  */
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
174  DWORD *len)
175 {
176     BOOL ret;
177
178     if (cbEncoded <= 1)
179     {
180         SetLastError(CRYPT_E_ASN1_CORRUPT);
181         ret = FALSE;
182     }
183     else if (pbEncoded[1] <= 0x7f)
184     {
185         if (pbEncoded[1] + 1 > cbEncoded)
186         {
187             SetLastError(CRYPT_E_ASN1_EOD);
188             ret = FALSE;
189         }
190         else
191         {
192             *len = pbEncoded[1];
193             ret = TRUE;
194         }
195     }
196     else if (pbEncoded[1] == 0x80)
197     {
198         FIXME("unimplemented for indefinite-length encoding\n");
199         SetLastError(CRYPT_E_ASN1_CORRUPT);
200         ret = FALSE;
201     }
202     else
203     {
204         BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
205
206         if (lenLen > sizeof(DWORD) + 1)
207         {
208             SetLastError(CRYPT_E_ASN1_LARGE);
209             ret = FALSE;
210         }
211         else if (lenLen + 2 > cbEncoded)
212         {
213             SetLastError(CRYPT_E_ASN1_CORRUPT);
214             ret = FALSE;
215         }
216         else
217         {
218             DWORD out = 0;
219
220             pbEncoded += 2;
221             while (--lenLen)
222             {
223                 out <<= 8;
224                 out |= *pbEncoded++;
225             }
226             if (out + lenLen + 1 > cbEncoded)
227             {
228                 SetLastError(CRYPT_E_ASN1_EOD);
229                 ret = FALSE;
230             }
231             else
232             {
233                 *len = out;
234                 ret = TRUE;
235             }
236         }
237     }
238     return ret;
239 }
240
241 /* Helper function to check *pcbStructInfo, set it to the required size, and
242  * optionally to allocate memory.  Assumes pvStructInfo is not NULL.
243  * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
244  * pointer to the newly allocated memory.
245  */
246 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
247  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
248  DWORD bytesNeeded)
249 {
250     BOOL ret = TRUE;
251
252     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
253     {
254         if (pDecodePara && pDecodePara->pfnAlloc)
255             *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
256         else
257             *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
258         if (!*(BYTE **)pvStructInfo)
259             ret = FALSE;
260         else
261             *pcbStructInfo = bytesNeeded;
262     }
263     else if (*pcbStructInfo < bytesNeeded)
264     {
265         *pcbStructInfo = bytesNeeded;
266         SetLastError(ERROR_MORE_DATA);
267         ret = FALSE;
268     }
269     return ret;
270 }
271
272 /* tag:
273  *     The expected tag of the item.  If tag is 0, decodeFunc is called
274  *     regardless of the tag value seen.
275  * offset:
276  *     A sequence is decoded into a struct.  The offset member is the
277  *     offset of this item within that struct.
278  * decodeFunc:
279  *     The decoder function to use.  If this is NULL, then the member isn't
280  *     decoded, but minSize space is reserved for it.
281  * minSize:
282  *     The minimum amount of space occupied after decoding.  You must set this.
283  * optional:
284  *     If true, and the tag doesn't match the expected tag for this item,
285  *     or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286  *     filled with 0 for this member.
287  * hasPointer, pointerOffset:
288  *     If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289  *     the offset within the struct of the data pointer (or to the
290  *     first data pointer, if more than one exist).
291  * size:
292  *     Used by CRYPT_AsnDecodeSequence, not for your use.
293  */
294 struct AsnDecodeSequenceItem
295 {
296     BYTE                    tag;
297     DWORD                   offset;
298     CryptDecodeObjectExFunc decodeFunc;
299     DWORD                   minSize;
300     BOOL                    optional;
301     BOOL                    hasPointer;
302     DWORD                   pointerOffset;
303     DWORD                   size;
304 };
305
306 /* Decodes the items in a sequence, where the items are described in items,
307  * the encoded data are in pbEncoded with length cbEncoded.  Decodes into
308  * pvStructInfo.  nextData is a pointer to the memory location at which the
309  * first decoded item with a dynamic pointer should point.
310  * Upon decoding, *cbDecoded is the total number of bytes decoded.
311  */
312 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
313  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
314  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
315  DWORD *cbDecoded)
316 {
317     BOOL ret;
318     DWORD i, decoded = 0;
319     const BYTE *ptr = pbEncoded;
320
321     TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
322      cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
323
324     for (i = 0, ret = TRUE; ret && i < cItem; i++)
325     {
326         if (cbEncoded - (ptr - pbEncoded) != 0)
327         {
328             DWORD nextItemLen;
329
330             if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
331              &nextItemLen)))
332             {
333                 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
334
335                 if (ptr[0] == items[i].tag || !items[i].tag)
336                 {
337                     if (nextData && pvStructInfo && items[i].hasPointer)
338                     {
339                         TRACE("Setting next pointer to %p\n",
340                          nextData);
341                         *(BYTE **)((BYTE *)pvStructInfo +
342                          items[i].pointerOffset) = nextData;
343                     }
344                     if (items[i].decodeFunc)
345                     {
346                         if (pvStructInfo)
347                             TRACE("decoding item %d\n", i);
348                         else
349                             TRACE("sizing item %d\n", i);
350                         ret = items[i].decodeFunc(dwCertEncodingType,
351                          NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
352                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
353                          pvStructInfo ?  (BYTE *)pvStructInfo + items[i].offset
354                          : NULL, &items[i].size);
355                         if (ret)
356                         {
357                             /* Account for alignment padding */
358                             if (items[i].size % sizeof(DWORD))
359                                 items[i].size += sizeof(DWORD) -
360                                  items[i].size % sizeof(DWORD);
361                             TRACE("item %d size: %d\n", i, items[i].size);
362                             if (nextData && items[i].hasPointer &&
363                              items[i].size > items[i].minSize)
364                                 nextData += items[i].size - items[i].minSize;
365                             ptr += 1 + nextItemLenBytes + nextItemLen;
366                             decoded += 1 + nextItemLenBytes + nextItemLen;
367                             TRACE("item %d: decoded %d bytes\n", i,
368                              1 + nextItemLenBytes + nextItemLen);
369                         }
370                         else if (items[i].optional &&
371                          GetLastError() == CRYPT_E_ASN1_BADTAG)
372                         {
373                             TRACE("skipping optional item %d\n", i);
374                             items[i].size = items[i].minSize;
375                             SetLastError(NOERROR);
376                             ret = TRUE;
377                         }
378                         else
379                             TRACE("item %d failed: %08x\n", i,
380                              GetLastError());
381                     }
382                     else
383                     {
384                         TRACE("item %d: decoded %d bytes\n", i,
385                          1 + nextItemLenBytes + nextItemLen);
386                         ptr += 1 + nextItemLenBytes + nextItemLen;
387                         decoded += 1 + nextItemLenBytes + nextItemLen;
388                         items[i].size = items[i].minSize;
389                     }
390                 }
391                 else if (items[i].optional)
392                 {
393                     TRACE("skipping optional item %d\n", i);
394                     items[i].size = items[i].minSize;
395                 }
396                 else
397                 {
398                     TRACE("item %d: tag %02x doesn't match expected %02x\n",
399                      i, ptr[0], items[i].tag);
400                     SetLastError(CRYPT_E_ASN1_BADTAG);
401                     ret = FALSE;
402                 }
403             }
404         }
405         else if (items[i].optional)
406         {
407             TRACE("missing optional item %d, skipping\n", i);
408             items[i].size = items[i].minSize;
409         }
410         else
411         {
412             TRACE("not enough bytes for item %d, failing\n", i);
413             SetLastError(CRYPT_E_ASN1_CORRUPT);
414             ret = FALSE;
415         }
416     }
417     if (ret)
418         *cbDecoded = decoded;
419     TRACE("returning %d\n", ret);
420     return ret;
421 }
422
423 /* This decodes an arbitrary sequence into a contiguous block of memory
424  * (basically, a struct.)  Each element being decoded is described by a struct
425  * AsnDecodeSequenceItem, see above.
426  * startingPointer is an optional pointer to the first place where dynamic
427  * data will be stored.  If you know the starting offset, you may pass it
428  * here.  Otherwise, pass NULL, and one will be inferred from the items.
429  * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
430  */
431 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
432  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
433  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
434  void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
435 {
436     BOOL ret;
437
438     TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
439      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
440      startingPointer);
441
442     if (pbEncoded[0] == ASN_SEQUENCE)
443     {
444         DWORD dataLen;
445
446         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
447         {
448             DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
449             const BYTE *ptr = pbEncoded + 1 + lenBytes;
450
451             cbEncoded -= 1 + lenBytes;
452             if (cbEncoded < dataLen)
453             {
454                 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
455                  cbEncoded);
456                 SetLastError(CRYPT_E_ASN1_CORRUPT);
457                 ret = FALSE;
458             }
459             else
460                 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
461                  cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
462             if (ret && cbDecoded != dataLen)
463             {
464                 TRACE("expected %d decoded, got %d, failing\n", dataLen,
465                  cbDecoded);
466                 SetLastError(CRYPT_E_ASN1_CORRUPT);
467                 ret = FALSE;
468             }
469             if (ret)
470             {
471                 DWORD i, bytesNeeded = 0, structSize = 0;
472
473                 for (i = 0; i < cItem; i++)
474                 {
475                     bytesNeeded += items[i].size;
476                     structSize += items[i].minSize;
477                 }
478                 if (!pvStructInfo)
479                     *pcbStructInfo = bytesNeeded;
480                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
481                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
482                 {
483                     BYTE *nextData;
484
485                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
486                         pvStructInfo = *(BYTE **)pvStructInfo;
487                     if (startingPointer)
488                         nextData = (BYTE *)startingPointer;
489                     else
490                         nextData = (BYTE *)pvStructInfo + structSize;
491                     memset(pvStructInfo, 0, structSize);
492                     ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
493                      ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
494                      &cbDecoded);
495                 }
496             }
497         }
498     }
499     else
500     {
501         SetLastError(CRYPT_E_ASN1_BADTAG);
502         ret = FALSE;
503     }
504     TRACE("returning %d (%08x)\n", ret, GetLastError());
505     return ret;
506 }
507
508 /* tag:
509  *     The expected tag of the entire encoded array (usually a variant
510  *     of ASN_SETOF or ASN_SEQUENCEOF.)  If tag is 0, decodeFunc is called
511  *     regardless of the tag seen.
512  * decodeFunc:
513  *     used to decode each item in the array
514  * itemSize:
515  *      is the minimum size of each decoded item
516  * hasPointer:
517  *      indicates whether each item has a dynamic pointer
518  * pointerOffset:
519  *     indicates the offset within itemSize at which the pointer exists
520  */
521 struct AsnArrayDescriptor
522 {
523     BYTE                    tag;
524     CryptDecodeObjectExFunc decodeFunc;
525     DWORD                   itemSize;
526     BOOL                    hasPointer;
527     DWORD                   pointerOffset;
528 };
529
530 struct AsnArrayItemSize
531 {
532     DWORD encodedLen;
533     DWORD size;
534 };
535
536 /* Decodes an array of like types into a struct GenericArray.
537  * The layout and decoding of the array are described by a struct
538  * AsnArrayDescriptor.
539  */
540 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
541  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
542  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
543  void *startingPointer)
544 {
545     BOOL ret = TRUE;
546
547     TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
548      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
549      startingPointer);
550
551     if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
552     {
553         DWORD dataLen;
554
555         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
556         {
557             DWORD bytesNeeded, cItems = 0;
558             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
559             /* There can be arbitrarily many items, but there is often only one.
560              */
561             struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
562
563             bytesNeeded = sizeof(struct GenericArray);
564             if (dataLen)
565             {
566                 const BYTE *ptr;
567
568                 for (ptr = pbEncoded + 1 + lenBytes; ret &&
569                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
570                 {
571                     DWORD itemLenBytes, itemDataLen, size = 0;
572
573                     itemLenBytes = GET_LEN_BYTES(ptr[1]);
574                     /* Each item decoded may not tolerate extraneous bytes, so
575                      * get the length of the next element and pass it directly.
576                      */
577                     ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
578                      &itemDataLen);
579                     if (ret)
580                         ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
581                          1 + itemLenBytes + itemDataLen,
582                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
583                          &size);
584                     if (ret)
585                     {
586                         DWORD nextLen;
587
588                         cItems++;
589                         if (itemSizes != &itemSize)
590                             itemSizes = CryptMemRealloc(itemSizes,
591                              cItems * sizeof(struct AsnArrayItemSize));
592                         else
593                         {
594                             itemSizes =
595                              CryptMemAlloc(
596                              cItems * sizeof(struct AsnArrayItemSize));
597                             if (itemSizes)
598                                 memcpy(itemSizes, &itemSize, sizeof(itemSize));
599                         }
600                         if (itemSizes)
601                         {
602                             itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
603                              + itemDataLen;
604                             itemSizes[cItems - 1].size = size;
605                             bytesNeeded += size;
606                             ret = CRYPT_GetLen(ptr,
607                              cbEncoded - (ptr - pbEncoded), &nextLen);
608                             if (ret)
609                                 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
610                         }
611                         else
612                             ret = FALSE;
613                     }
614                 }
615             }
616             if (ret)
617             {
618                 if (!pvStructInfo)
619                     *pcbStructInfo = bytesNeeded;
620                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
621                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
622                 {
623                     DWORD i;
624                     BYTE *nextData;
625                     const BYTE *ptr;
626                     struct GenericArray *array;
627
628                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
629                         pvStructInfo = *(BYTE **)pvStructInfo;
630                     array = (struct GenericArray *)pvStructInfo;
631                     array->cItems = cItems;
632                     if (startingPointer)
633                         array->rgItems = startingPointer;
634                     else
635                         array->rgItems = (BYTE *)array +
636                          sizeof(struct GenericArray);
637                     nextData = (BYTE *)array->rgItems +
638                      array->cItems * arrayDesc->itemSize;
639                     for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
640                      i < cItems && ptr - pbEncoded - 1 - lenBytes <
641                      dataLen; i++)
642                     {
643                         if (arrayDesc->hasPointer)
644                             *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
645                              + arrayDesc->pointerOffset) = nextData;
646                         ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
647                          itemSizes[i].encodedLen,
648                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
649                          array->rgItems + i * arrayDesc->itemSize,
650                          &itemSizes[i].size);
651                         if (ret)
652                         {
653                             DWORD nextLen;
654
655                             nextData += itemSizes[i].size - arrayDesc->itemSize;
656                             ret = CRYPT_GetLen(ptr,
657                              cbEncoded - (ptr - pbEncoded), &nextLen);
658                             if (ret)
659                                 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
660                         }
661                     }
662                 }
663             }
664             if (itemSizes != &itemSize)
665                 CryptMemFree(itemSizes);
666         }
667     }
668     else
669     {
670         SetLastError(CRYPT_E_ASN1_BADTAG);
671         ret = FALSE;
672     }
673     return ret;
674 }
675
676 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
677  * pvStructInfo.  The BLOB must be non-empty, otherwise the last error is set
678  * to CRYPT_E_ASN1_CORRUPT.
679  * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
680  * set!
681  */
682 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
683  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
684  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
685 {
686     BOOL ret;
687     DWORD dataLen;
688
689     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
690     {
691         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
692         DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
693        
694         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
695             bytesNeeded += 1 + lenBytes + dataLen;
696
697         if (!pvStructInfo)
698             *pcbStructInfo = bytesNeeded;
699         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, 
700          pvStructInfo, pcbStructInfo, bytesNeeded)))
701         {
702             CRYPT_DER_BLOB *blob;
703
704             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
705                 pvStructInfo = *(BYTE **)pvStructInfo;
706             blob = (CRYPT_DER_BLOB *)pvStructInfo;
707             blob->cbData = 1 + lenBytes + dataLen;
708             if (blob->cbData)
709             {
710                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
711                     blob->pbData = (BYTE *)pbEncoded;
712                 else
713                 {
714                     assert(blob->pbData);
715                     memcpy(blob->pbData, pbEncoded, blob->cbData);
716                 }
717             }
718             else
719             {
720                 SetLastError(CRYPT_E_ASN1_CORRUPT);
721                 ret = FALSE;
722             }
723         }
724     }
725     return ret;
726 }
727
728 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
729 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
730  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
731  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
732 {
733     BOOL ret;
734
735     TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
736      pDecodePara, pvStructInfo, *pcbStructInfo);
737
738     /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
739      * place.
740      */
741     ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
742      pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
743      pvStructInfo, pcbStructInfo);
744     if (ret && pvStructInfo)
745     {
746         CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
747
748         if (blob->cbData)
749         {
750             DWORD i;
751             BYTE temp;
752
753             for (i = 0; i < blob->cbData / 2; i++)
754             {
755                 temp = blob->pbData[i];
756                 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
757                 blob->pbData[blob->cbData - i - 1] = temp;
758             }
759         }
760     }
761     TRACE("returning %d (%08x)\n", ret, GetLastError());
762     return ret;
763 }
764
765 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
766  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
767  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
768 {
769     BOOL ret = TRUE;
770
771     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
772      pDecodePara, pvStructInfo, *pcbStructInfo);
773
774     __TRY
775     {
776         struct AsnDecodeSequenceItem items[] = {
777          { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
778            CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
779            offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
780          { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
781            SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
782            sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
783            offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
784          { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
785            CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
786            offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
787         };
788
789         if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
790             items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
791         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
792          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
793          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
794     }
795     __EXCEPT_PAGE_FAULT
796     {
797         SetLastError(STATUS_ACCESS_VIOLATION);
798         ret = FALSE;
799     }
800     __ENDTRY
801
802     TRACE("Returning %d (%08x)\n", ret, GetLastError());
803     return ret;
804 }
805
806 /* Internal function */
807 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
808  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
809  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
810 {
811     BOOL ret;
812     DWORD dataLen;
813
814     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
815     {
816         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
817
818         ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
819          pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
820          pvStructInfo, pcbStructInfo);
821     }
822     return ret;
823 }
824
825 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
826  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
827  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
828 {
829     BOOL ret;
830
831     struct AsnDecodeSequenceItem items[] = {
832      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
833        CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
834      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
835        CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
836     };
837
838     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
839      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
840      pDecodePara, pvStructInfo, pcbStructInfo, NULL);
841     return ret;
842 }
843
844 /* Internal function */
845 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
846  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
847  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
848 {
849     BOOL ret;
850     DWORD dataLen;
851
852     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
853     {
854         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
855
856         ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
857          X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
858          pDecodePara, pvStructInfo, pcbStructInfo);
859     }
860     return ret;
861 }
862
863 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
864  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
865  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
866 {
867     BOOL ret = TRUE;
868     struct AsnDecodeSequenceItem items[] = {
869      { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
870        CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
871      { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
872        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
873        TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
874      { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
875        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
876        FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
877      { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
878        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
879        Issuer.pbData) },
880      { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
881        CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
882        FALSE, 0 },
883      { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
884        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
885        Subject.pbData) },
886      { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
887        CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
888        FALSE, TRUE, offsetof(CERT_INFO,
889        SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
890      { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
891        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
892        offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
893      { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
894        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
895        offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
896      { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
897        CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
898        offsetof(CERT_INFO, rgExtension), 0 },
899     };
900
901     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
902      pDecodePara, pvStructInfo, *pcbStructInfo);
903
904     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
905      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
906      pDecodePara, pvStructInfo, pcbStructInfo, NULL);
907     if (ret && pvStructInfo)
908     {
909         CERT_INFO *info;
910
911         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
912             info = *(CERT_INFO **)pvStructInfo;
913         else
914             info = (CERT_INFO *)pvStructInfo;
915         if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
916          !info->Subject.cbData)
917         {
918             SetLastError(CRYPT_E_ASN1_CORRUPT);
919             /* Don't need to deallocate, because it should have failed on the
920              * first pass (and no memory was allocated.)
921              */
922             ret = FALSE;
923         }
924     }
925
926     TRACE("Returning %d (%08x)\n", ret, GetLastError());
927     return ret;
928 }
929
930 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
931  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
932  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
933 {
934     BOOL ret = TRUE;
935
936     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
937      pDecodePara, pvStructInfo, *pcbStructInfo);
938
939     __TRY
940     {
941         PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
942         DWORD size = 0;
943
944         /* First try to decode it as a signed cert. */
945         ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
946          pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
947          (BYTE *)&signedCert, &size);
948         if (ret)
949         {
950             size = 0;
951             ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
952              X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
953              signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
954              pcbStructInfo);
955             LocalFree(signedCert);
956         }
957         /* Failing that, try it as an unsigned cert */
958         if (!ret)
959         {
960             size = 0;
961             ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
962              X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
963              pDecodePara, pvStructInfo, pcbStructInfo);
964         }
965     }
966     __EXCEPT_PAGE_FAULT
967     {
968         SetLastError(STATUS_ACCESS_VIOLATION);
969         ret = FALSE;
970     }
971     __ENDTRY
972
973     TRACE("Returning %d (%08x)\n", ret, GetLastError());
974     return ret;
975 }
976
977 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
978  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
979  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
980 {
981     BOOL ret;
982     struct AsnDecodeSequenceItem items[] = {
983      { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
984        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
985        offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
986      { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
987        sizeof(FILETIME), FALSE, FALSE, 0 },
988      { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
989        CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
990        offsetof(CRL_ENTRY, rgExtension), 0 },
991     };
992     PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
993
994     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
995      *pcbStructInfo);
996
997     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
998      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
999      NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
1000     return ret;
1001 }
1002
1003 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1004  * been set prior to calling.
1005  */
1006 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
1007  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1008  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1009 {
1010     BOOL ret;
1011     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1012      CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1013      offsetof(CRL_ENTRY, SerialNumber.pbData) };
1014     struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1015
1016     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1017      pDecodePara, pvStructInfo, *pcbStructInfo);
1018
1019     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1020      pDecodePara, pvStructInfo, pcbStructInfo,
1021      entries ? entries->rgItems : NULL);
1022     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1023     return ret;
1024 }
1025
1026 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1027  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1028  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1029 {
1030     struct AsnDecodeSequenceItem items[] = {
1031      { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1032        CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1033      { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1034        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1035        FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1036      { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1037        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1038        Issuer.pbData) },
1039      { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1040        sizeof(FILETIME), FALSE, FALSE, 0 },
1041      { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1042        sizeof(FILETIME), TRUE, FALSE, 0 },
1043      { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1044        CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1045        offsetof(CRL_INFO, rgCRLEntry), 0 },
1046      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1047        CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1048        offsetof(CRL_INFO, rgExtension), 0 },
1049     };
1050     BOOL ret = TRUE;
1051
1052     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1053      pDecodePara, pvStructInfo, *pcbStructInfo);
1054
1055     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1056      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1057      pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1058
1059     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1060     return ret;
1061 }
1062
1063 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1064  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1065  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1066 {
1067     BOOL ret = TRUE;
1068
1069     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1070      pDecodePara, pvStructInfo, *pcbStructInfo);
1071
1072     __TRY
1073     {
1074         PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1075         DWORD size = 0;
1076
1077         /* First try to decode it as a signed crl. */
1078         ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1079          pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1080          (BYTE *)&signedCrl, &size);
1081         if (ret)
1082         {
1083             size = 0;
1084             ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1085              X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1086              signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1087              pvStructInfo, pcbStructInfo);
1088             LocalFree(signedCrl);
1089         }
1090         /* Failing that, try it as an unsigned crl */
1091         if (!ret)
1092         {
1093             size = 0;
1094             ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1095              X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1096              dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1097         }
1098     }
1099     __EXCEPT_PAGE_FAULT
1100     {
1101         SetLastError(STATUS_ACCESS_VIOLATION);
1102         ret = FALSE;
1103     }
1104     __ENDTRY
1105
1106     TRACE("Returning %d (%08x)\n", ret, GetLastError());
1107     return ret;
1108 }
1109
1110 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1111  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1112  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1113 {
1114     BOOL ret = TRUE;
1115
1116     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1117      pDecodePara, pvStructInfo, *pcbStructInfo);
1118
1119     if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1120     {
1121         DWORD dataLen;
1122
1123         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1124         {
1125             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1126             DWORD bytesNeeded = sizeof(LPSTR);
1127
1128             if (dataLen)
1129             {
1130                 /* The largest possible string for the first two components
1131                  * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1132                  */
1133                 char firstTwo[6];
1134                 const BYTE *ptr;
1135
1136                 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1137                  pbEncoded[1 + lenBytes] / 40,
1138                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1139                  * 40);
1140                 bytesNeeded += strlen(firstTwo) + 1;
1141                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1142                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
1143                 {
1144                     /* large enough for ".4000000" */
1145                     char str[9];
1146                     int val = 0;
1147
1148                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1149                      (*ptr & 0x80))
1150                     {
1151                         val <<= 7;
1152                         val |= *ptr & 0x7f;
1153                         ptr++;
1154                     }
1155                     if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1156                      (*ptr & 0x80))
1157                     {
1158                         SetLastError(CRYPT_E_ASN1_CORRUPT);
1159                         ret = FALSE;
1160                     }
1161                     else
1162                     {
1163                         val <<= 7;
1164                         val |= *ptr++;
1165                         snprintf(str, sizeof(str), ".%d", val);
1166                         bytesNeeded += strlen(str);
1167                     }
1168                 }
1169             }
1170             if (!pvStructInfo)
1171                 *pcbStructInfo = bytesNeeded;
1172             else if (*pcbStructInfo < bytesNeeded)
1173             {
1174                 *pcbStructInfo = bytesNeeded;
1175                 SetLastError(ERROR_MORE_DATA);
1176                 ret = FALSE;
1177             }
1178             else
1179             {
1180                 if (dataLen)
1181                 {
1182                     const BYTE *ptr;
1183                     LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1184
1185                     *pszObjId = 0;
1186                     sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1187                      pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1188                      40) * 40);
1189                     pszObjId += strlen(pszObjId);
1190                     for (ptr = pbEncoded + 2 + lenBytes; ret &&
1191                      ptr - pbEncoded - 1 - lenBytes < dataLen; )
1192                     {
1193                         int val = 0;
1194
1195                         while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1196                          (*ptr & 0x80))
1197                         {
1198                             val <<= 7;
1199                             val |= *ptr & 0x7f;
1200                             ptr++;
1201                         }
1202                         val <<= 7;
1203                         val |= *ptr++;
1204                         sprintf(pszObjId, ".%d", val);
1205                         pszObjId += strlen(pszObjId);
1206                     }
1207                 }
1208                 else
1209                     *(LPSTR *)pvStructInfo = NULL;
1210                 *pcbStructInfo = bytesNeeded;
1211             }
1212         }
1213     }
1214     return ret;
1215 }
1216
1217 /* Warning:  assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1218  * ahead of time!
1219  */
1220 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1221  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1222  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1223 {
1224     struct AsnDecodeSequenceItem items[] = {
1225      { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1226        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1227        offsetof(CERT_EXTENSION, pszObjId), 0 },
1228      { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1229        sizeof(BOOL), TRUE, FALSE, 0, 0 },
1230      { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1231        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1232        offsetof(CERT_EXTENSION, Value.pbData) },
1233     };
1234     BOOL ret = TRUE;
1235     PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1236
1237     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1238      *pcbStructInfo);
1239
1240     if (ext)
1241         TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1242     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1243      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1244      ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1245     if (ext)
1246         TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1247          debugstr_a(ext->pszObjId));
1248     TRACE("returning %d (%08x)\n", ret, GetLastError());
1249     return ret;
1250 }
1251
1252 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1253  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1254  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1255 {
1256     BOOL ret = TRUE;
1257     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1258      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1259      offsetof(CERT_EXTENSION, pszObjId) };
1260     PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1261
1262     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1263      pDecodePara, pvStructInfo, *pcbStructInfo);
1264
1265     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1266      pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1267     return ret;
1268 }
1269
1270 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1271  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1272  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1273 {
1274     BOOL ret = TRUE;
1275
1276     __TRY
1277     {
1278         ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1279          lpszStructType, pbEncoded, cbEncoded,
1280          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1281         if (ret && pvStructInfo)
1282         {
1283             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1284              pcbStructInfo, *pcbStructInfo);
1285             if (ret)
1286             {
1287                 CERT_EXTENSIONS *exts;
1288
1289                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1290                     pvStructInfo = *(BYTE **)pvStructInfo;
1291                 exts = (CERT_EXTENSIONS *)pvStructInfo;
1292                 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1293                  sizeof(CERT_EXTENSIONS));
1294                 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1295                  lpszStructType, pbEncoded, cbEncoded,
1296                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1297                  pcbStructInfo);
1298             }
1299         }
1300     }
1301     __EXCEPT_PAGE_FAULT
1302     {
1303         SetLastError(STATUS_ACCESS_VIOLATION);
1304         ret = FALSE;
1305     }
1306     __ENDTRY
1307     return ret;
1308 }
1309
1310 /* Warning: this assumes the address of value->Value.pbData is already set, in
1311  * order to avoid overwriting memory.  (In some cases, it may change it, if it
1312  * doesn't copy anything to memory.)  Be sure to set it correctly!
1313  */
1314 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1315  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1316  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1317 {
1318     BOOL ret = TRUE;
1319     DWORD dataLen;
1320     CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1321
1322     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1323     {
1324         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1325         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1326
1327         switch (pbEncoded[0])
1328         {
1329         case ASN_OCTETSTRING:
1330             valueType = CERT_RDN_OCTET_STRING;
1331             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1332                 bytesNeeded += dataLen;
1333             break;
1334         case ASN_NUMERICSTRING:
1335             valueType = CERT_RDN_NUMERIC_STRING;
1336             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1337                 bytesNeeded += dataLen;
1338             break;
1339         case ASN_PRINTABLESTRING:
1340             valueType = CERT_RDN_PRINTABLE_STRING;
1341             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1342                 bytesNeeded += dataLen;
1343             break;
1344         case ASN_IA5STRING:
1345             valueType = CERT_RDN_IA5_STRING;
1346             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1347                 bytesNeeded += dataLen;
1348             break;
1349         case ASN_T61STRING:
1350             valueType = CERT_RDN_T61_STRING;
1351             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1352                 bytesNeeded += dataLen;
1353             break;
1354         case ASN_VIDEOTEXSTRING:
1355             valueType = CERT_RDN_VIDEOTEX_STRING;
1356             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1357                 bytesNeeded += dataLen;
1358             break;
1359         case ASN_GRAPHICSTRING:
1360             valueType = CERT_RDN_GRAPHIC_STRING;
1361             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1362                 bytesNeeded += dataLen;
1363             break;
1364         case ASN_VISIBLESTRING:
1365             valueType = CERT_RDN_VISIBLE_STRING;
1366             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1367                 bytesNeeded += dataLen;
1368             break;
1369         case ASN_GENERALSTRING:
1370             valueType = CERT_RDN_GENERAL_STRING;
1371             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1372                 bytesNeeded += dataLen;
1373             break;
1374         case ASN_UNIVERSALSTRING:
1375             FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1376             SetLastError(CRYPT_E_ASN1_BADTAG);
1377             return FALSE;
1378         case ASN_BMPSTRING:
1379             valueType = CERT_RDN_BMP_STRING;
1380             bytesNeeded += dataLen;
1381             break;
1382         case ASN_UTF8STRING:
1383             valueType = CERT_RDN_UTF8_STRING;
1384             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1385              (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1386             break;
1387         default:
1388             SetLastError(CRYPT_E_ASN1_BADTAG);
1389             return FALSE;
1390         }
1391
1392         if (!value)
1393             *pcbStructInfo = bytesNeeded;
1394         else if (*pcbStructInfo < bytesNeeded)
1395         {
1396             *pcbStructInfo = bytesNeeded;
1397             SetLastError(ERROR_MORE_DATA);
1398             ret = FALSE;
1399         }
1400         else
1401         {
1402             *pcbStructInfo = bytesNeeded;
1403             value->dwValueType = valueType;
1404             if (dataLen)
1405             {
1406                 DWORD i;
1407
1408                 assert(value->Value.pbData);
1409                 switch (pbEncoded[0])
1410                 {
1411                 case ASN_OCTETSTRING:
1412                 case ASN_NUMERICSTRING:
1413                 case ASN_PRINTABLESTRING:
1414                 case ASN_IA5STRING:
1415                 case ASN_T61STRING:
1416                 case ASN_VIDEOTEXSTRING:
1417                 case ASN_GRAPHICSTRING:
1418                 case ASN_VISIBLESTRING:
1419                 case ASN_GENERALSTRING:
1420                     value->Value.cbData = dataLen;
1421                     if (dataLen)
1422                     {
1423                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1424                             memcpy(value->Value.pbData,
1425                              pbEncoded + 1 + lenBytes, dataLen);
1426                         else
1427                             value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1428                              lenBytes;
1429                     }
1430                     break;
1431                 case ASN_BMPSTRING:
1432                 {
1433                     LPWSTR str = (LPWSTR)value->Value.pbData;
1434
1435                     value->Value.cbData = dataLen;
1436                     for (i = 0; i < dataLen / 2; i++)
1437                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1438                          pbEncoded[1 + lenBytes + 2 * i + 1];
1439                     break;
1440                 }
1441                 case ASN_UTF8STRING:
1442                 {
1443                     LPWSTR str = (LPWSTR)value->Value.pbData;
1444
1445                     value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1446                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, 
1447                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1448                     break;
1449                 }
1450                 }
1451             }
1452             else
1453             {
1454                 value->Value.cbData = 0;
1455                 value->Value.pbData = NULL;
1456             }
1457         }
1458     }
1459     return ret;
1460 }
1461
1462 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1463  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1464  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1465 {
1466     BOOL ret = TRUE;
1467
1468     __TRY
1469     {
1470         ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1471          lpszStructType, pbEncoded, cbEncoded,
1472          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1473         if (ret && pvStructInfo)
1474         {
1475             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1476              pcbStructInfo, *pcbStructInfo);
1477             if (ret)
1478             {
1479                 CERT_NAME_VALUE *value;
1480
1481                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1482                     pvStructInfo = *(BYTE **)pvStructInfo;
1483                 value = (CERT_NAME_VALUE *)pvStructInfo;
1484                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1485                 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1486                  lpszStructType, pbEncoded, cbEncoded,
1487                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1488                  pcbStructInfo);
1489             }
1490         }
1491     }
1492     __EXCEPT_PAGE_FAULT
1493     {
1494         SetLastError(STATUS_ACCESS_VIOLATION);
1495         ret = FALSE;
1496     }
1497     __ENDTRY
1498     return ret;
1499 }
1500
1501 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1502  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1503  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1504  void *pvStructInfo, DWORD *pcbStructInfo)
1505 {
1506     BOOL ret = TRUE;
1507     DWORD dataLen;
1508     CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1509
1510     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1511     {
1512         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1513         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1514
1515         switch (pbEncoded[0])
1516         {
1517         case ASN_NUMERICSTRING:
1518             valueType = CERT_RDN_NUMERIC_STRING;
1519             bytesNeeded += dataLen * 2;
1520             break;
1521         case ASN_PRINTABLESTRING:
1522             valueType = CERT_RDN_PRINTABLE_STRING;
1523             bytesNeeded += dataLen * 2;
1524             break;
1525         case ASN_IA5STRING:
1526             valueType = CERT_RDN_IA5_STRING;
1527             bytesNeeded += dataLen * 2;
1528             break;
1529         case ASN_T61STRING:
1530             valueType = CERT_RDN_T61_STRING;
1531             bytesNeeded += dataLen * 2;
1532             break;
1533         case ASN_VIDEOTEXSTRING:
1534             valueType = CERT_RDN_VIDEOTEX_STRING;
1535             bytesNeeded += dataLen * 2;
1536             break;
1537         case ASN_GRAPHICSTRING:
1538             valueType = CERT_RDN_GRAPHIC_STRING;
1539             bytesNeeded += dataLen * 2;
1540             break;
1541         case ASN_VISIBLESTRING:
1542             valueType = CERT_RDN_VISIBLE_STRING;
1543             bytesNeeded += dataLen * 2;
1544             break;
1545         case ASN_GENERALSTRING:
1546             valueType = CERT_RDN_GENERAL_STRING;
1547             bytesNeeded += dataLen * 2;
1548             break;
1549         case ASN_UNIVERSALSTRING:
1550             valueType = CERT_RDN_UNIVERSAL_STRING;
1551             bytesNeeded += dataLen / 2;
1552             break;
1553         case ASN_BMPSTRING:
1554             valueType = CERT_RDN_BMP_STRING;
1555             bytesNeeded += dataLen;
1556             break;
1557         case ASN_UTF8STRING:
1558             valueType = CERT_RDN_UTF8_STRING;
1559             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1560              (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1561             break;
1562         default:
1563             SetLastError(CRYPT_E_ASN1_BADTAG);
1564             return FALSE;
1565         }
1566
1567         if (!value)
1568             *pcbStructInfo = bytesNeeded;
1569         else if (*pcbStructInfo < bytesNeeded)
1570         {
1571             *pcbStructInfo = bytesNeeded;
1572             SetLastError(ERROR_MORE_DATA);
1573             ret = FALSE;
1574         }
1575         else
1576         {
1577             *pcbStructInfo = bytesNeeded;
1578             value->dwValueType = valueType;
1579             if (dataLen)
1580             {
1581                 DWORD i;
1582                 LPWSTR str = (LPWSTR)value->Value.pbData;
1583
1584                 assert(value->Value.pbData);
1585                 switch (pbEncoded[0])
1586                 {
1587                 case ASN_NUMERICSTRING:
1588                 case ASN_PRINTABLESTRING:
1589                 case ASN_IA5STRING:
1590                 case ASN_T61STRING:
1591                 case ASN_VIDEOTEXSTRING:
1592                 case ASN_GRAPHICSTRING:
1593                 case ASN_VISIBLESTRING:
1594                 case ASN_GENERALSTRING:
1595                     value->Value.cbData = dataLen * 2;
1596                     for (i = 0; i < dataLen; i++)
1597                         str[i] = pbEncoded[1 + lenBytes + i];
1598                     break;
1599                 case ASN_UNIVERSALSTRING:
1600                     value->Value.cbData = dataLen / 2;
1601                     for (i = 0; i < dataLen / 4; i++)
1602                         str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1603                          | pbEncoded[1 + lenBytes + 2 * i + 3];
1604                     break;
1605                 case ASN_BMPSTRING:
1606                     value->Value.cbData = dataLen;
1607                     for (i = 0; i < dataLen / 2; i++)
1608                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1609                          pbEncoded[1 + lenBytes + 2 * i + 1];
1610                     break;
1611                 case ASN_UTF8STRING:
1612                     value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1613                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1614                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1615                     break;
1616                 }
1617             }
1618             else
1619             {
1620                 value->Value.cbData = 0;
1621                 value->Value.pbData = NULL;
1622             }
1623         }
1624     }
1625     return ret;
1626 }
1627
1628 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1629  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1630  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1631 {
1632     BOOL ret = TRUE;
1633
1634     __TRY
1635     {
1636         ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1637          lpszStructType, pbEncoded, cbEncoded,
1638          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1639         if (ret && pvStructInfo)
1640         {
1641             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1642              pcbStructInfo, *pcbStructInfo);
1643             if (ret)
1644             {
1645                 CERT_NAME_VALUE *value;
1646
1647                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1648                     pvStructInfo = *(BYTE **)pvStructInfo;
1649                 value = (CERT_NAME_VALUE *)pvStructInfo;
1650                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1651                 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1652                  dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1653                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1654                  pcbStructInfo);
1655             }
1656         }
1657     }
1658     __EXCEPT_PAGE_FAULT
1659     {
1660         SetLastError(STATUS_ACCESS_VIOLATION);
1661         ret = FALSE;
1662     }
1663     __ENDTRY
1664     return ret;
1665 }
1666
1667 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1668  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1669  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1670 {
1671     BOOL ret;
1672     struct AsnDecodeSequenceItem items[] = {
1673      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1674        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1675        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1676      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1677        CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1678        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1679     };
1680     CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1681
1682     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1683      pvStructInfo, *pcbStructInfo);
1684
1685     if (attr)
1686         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1687     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1688      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1689      attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1690     if (attr)
1691     {
1692         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1693          debugstr_a(attr->pszObjId));
1694         TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1695     }
1696     TRACE("returning %d (%08x)\n", ret, GetLastError());
1697     return ret;
1698 }
1699
1700 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1701  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1702  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1703 {
1704     BOOL ret = TRUE;
1705     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1706      CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1707      offsetof(CERT_RDN_ATTR, pszObjId) };
1708     PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1709
1710     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1711      pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1712     return ret;
1713 }
1714
1715 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1716  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1717  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1718 {
1719     BOOL ret = TRUE;
1720
1721     __TRY
1722     {
1723         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1724          CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1725          offsetof(CERT_RDN, rgRDNAttr) };
1726
1727         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1728          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1729     }
1730     __EXCEPT_PAGE_FAULT
1731     {
1732         SetLastError(STATUS_ACCESS_VIOLATION);
1733         ret = FALSE;
1734     }
1735     __ENDTRY
1736     return ret;
1737 }
1738
1739 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1740  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1741  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1742 {
1743     BOOL ret;
1744     struct AsnDecodeSequenceItem items[] = {
1745      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1746        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1747        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1748      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1749        CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1750        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1751     };
1752     CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1753
1754     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1755      pvStructInfo, *pcbStructInfo);
1756
1757     if (attr)
1758         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1759     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1760      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1761      attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1762     if (attr)
1763     {
1764         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1765          debugstr_a(attr->pszObjId));
1766         TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1767     }
1768     TRACE("returning %d (%08x)\n", ret, GetLastError());
1769     return ret;
1770 }
1771
1772 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1773  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1774  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1775 {
1776     BOOL ret = TRUE;
1777     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1778      CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1779      offsetof(CERT_RDN_ATTR, pszObjId) };
1780     PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1781
1782     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1783      pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1784     return ret;
1785 }
1786
1787 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1788  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1789  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1790 {
1791     BOOL ret = TRUE;
1792
1793     __TRY
1794     {
1795         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1796          CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1797          offsetof(CERT_RDN, rgRDNAttr) };
1798
1799         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1800          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1801     }
1802     __EXCEPT_PAGE_FAULT
1803     {
1804         SetLastError(STATUS_ACCESS_VIOLATION);
1805         ret = FALSE;
1806     }
1807     __ENDTRY
1808     return ret;
1809 }
1810
1811 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1812  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1813  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1814 {
1815     BOOL ret = TRUE;
1816     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1817
1818     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1819      pDecodePara, pvStructInfo, *pcbStructInfo);
1820
1821     if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1822         bytesNeeded += cbEncoded;
1823     if (!pvStructInfo)
1824         *pcbStructInfo = bytesNeeded;
1825     else if (*pcbStructInfo < bytesNeeded)
1826     {
1827         SetLastError(ERROR_MORE_DATA);
1828         *pcbStructInfo = bytesNeeded;
1829         ret = FALSE;
1830     }
1831     else
1832     {
1833         PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1834
1835         *pcbStructInfo = bytesNeeded;
1836         blob->cbData = cbEncoded;
1837         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1838             blob->pbData = (LPBYTE)pbEncoded;
1839         else
1840         {
1841             assert(blob->pbData);
1842             memcpy(blob->pbData, pbEncoded, blob->cbData);
1843         }
1844     }
1845     return ret;
1846 }
1847
1848 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1849  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1850  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1851 {
1852     BOOL ret;
1853     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1854      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1855     struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1856
1857     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1858      pDecodePara, pvStructInfo, *pcbStructInfo);
1859
1860     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1861      pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1862     return ret;
1863 }
1864
1865 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1866  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1867  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1868 {
1869     BOOL ret = FALSE;
1870
1871     __TRY
1872     {
1873         struct AsnDecodeSequenceItem items[] = {
1874          { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1875            CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1876            offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1877          { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1878            CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1879            offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1880         };
1881         PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1882
1883         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1884          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1885          pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1886          NULL);
1887     }
1888     __EXCEPT_PAGE_FAULT
1889     {
1890         SetLastError(STATUS_ACCESS_VIOLATION);
1891     }
1892     __ENDTRY
1893     TRACE("returning %d\n", ret);
1894     return ret;
1895 }
1896
1897 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1898  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1899  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1900  void *pvStructInfo, DWORD *pcbStructInfo)
1901 {
1902     struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodePKCSAttribute,
1903      sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1904     PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1905     BOOL ret;
1906
1907     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1908      pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1909      NULL);
1910     return ret;
1911 }
1912
1913 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1914  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1915  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1916 {
1917     BOOL ret = FALSE;
1918
1919     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1920      pDecodePara, pvStructInfo, *pcbStructInfo);
1921
1922     __TRY
1923     {
1924         DWORD bytesNeeded;
1925
1926         if (!cbEncoded)
1927             SetLastError(CRYPT_E_ASN1_EOD);
1928         else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
1929             SetLastError(CRYPT_E_ASN1_CORRUPT);
1930         else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
1931          dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1932          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1933         {
1934             if (!pvStructInfo)
1935                 *pcbStructInfo = bytesNeeded;
1936             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1937              pvStructInfo, pcbStructInfo, bytesNeeded)))
1938             {
1939                 PCRYPT_ATTRIBUTES attrs;
1940
1941                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1942                     pvStructInfo = *(BYTE **)pvStructInfo;
1943                 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1944                 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1945                  sizeof(CRYPT_ATTRIBUTES));
1946                 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1947                  lpszStructType, pbEncoded, cbEncoded,
1948                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1949                  &bytesNeeded);
1950             }
1951         }
1952     }
1953     __EXCEPT_PAGE_FAULT
1954     {
1955         SetLastError(STATUS_ACCESS_VIOLATION);
1956     }
1957     __ENDTRY
1958     TRACE("returning %d\n", ret);
1959     return ret;
1960 }
1961
1962 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1963  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1964  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1965 {
1966     CRYPT_ALGORITHM_IDENTIFIER *algo =
1967      (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1968     BOOL ret = TRUE;
1969     struct AsnDecodeSequenceItem items[] = {
1970      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1971        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, 
1972        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1973      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1974        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
1975        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1976     };
1977
1978     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1979      pDecodePara, pvStructInfo, *pcbStructInfo);
1980
1981     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1982      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1983      pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1984     if (ret && pvStructInfo)
1985     {
1986         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1987          debugstr_a(algo->pszObjId));
1988     }
1989     return ret;
1990 }
1991
1992 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1993  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1994  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1995 {
1996     BOOL ret = TRUE;
1997     struct AsnDecodeSequenceItem items[] = {
1998      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1999        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2000        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2001        Algorithm.pszObjId) },
2002      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2003        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2004        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2005     };
2006     PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2007
2008     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2009      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2010      pDecodePara, pvStructInfo, pcbStructInfo, info ?
2011      info->Algorithm.Parameters.pbData : NULL);
2012     return ret;
2013 }
2014
2015 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2016  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2017  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2018 {
2019     BOOL ret = TRUE;
2020
2021     __TRY
2022     {
2023         DWORD bytesNeeded;
2024
2025         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2026          lpszStructType, pbEncoded, cbEncoded,
2027          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2028         {
2029             if (!pvStructInfo)
2030                 *pcbStructInfo = bytesNeeded;
2031             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2032              pvStructInfo, pcbStructInfo, bytesNeeded)))
2033             {
2034                 PCERT_PUBLIC_KEY_INFO info;
2035
2036                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2037                     pvStructInfo = *(BYTE **)pvStructInfo;
2038                 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2039                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2040                  sizeof(CERT_PUBLIC_KEY_INFO);
2041                 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2042                  lpszStructType, pbEncoded, cbEncoded,
2043                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2044                  &bytesNeeded);
2045             }
2046         }
2047     }
2048     __EXCEPT_PAGE_FAULT
2049     {
2050         SetLastError(STATUS_ACCESS_VIOLATION);
2051         ret = FALSE;
2052     }
2053     __ENDTRY
2054     return ret;
2055 }
2056
2057 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2058  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2059  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2060 {
2061     BOOL ret;
2062
2063     if (cbEncoded < 3)
2064     {
2065         SetLastError(CRYPT_E_ASN1_CORRUPT);
2066         return FALSE;
2067     }
2068     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2069     {
2070         SetLastError(CRYPT_E_ASN1_CORRUPT);
2071         return FALSE;
2072     }
2073     if (pbEncoded[1] > 1)
2074     {
2075         SetLastError(CRYPT_E_ASN1_CORRUPT);
2076         return FALSE;
2077     }
2078     if (!pvStructInfo)
2079     {
2080         *pcbStructInfo = sizeof(BOOL);
2081         ret = TRUE;
2082     }
2083     else if (*pcbStructInfo < sizeof(BOOL))
2084     {
2085         *pcbStructInfo = sizeof(BOOL);
2086         SetLastError(ERROR_MORE_DATA);
2087         ret = FALSE;
2088     }
2089     else
2090     {
2091         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2092         ret = TRUE;
2093     }
2094     TRACE("returning %d (%08x)\n", ret, GetLastError());
2095     return ret;
2096 }
2097
2098 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2099  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2100  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2101 {
2102     PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2103     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2104     BOOL ret;
2105
2106     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2107      pDecodePara, pvStructInfo, *pcbStructInfo);
2108
2109     if (cbEncoded < 2)
2110     {
2111         SetLastError(CRYPT_E_ASN1_CORRUPT);
2112         return FALSE;
2113     }
2114     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2115     if (1 + lenBytes > cbEncoded)
2116     {
2117         SetLastError(CRYPT_E_ASN1_CORRUPT);
2118         return FALSE;
2119     }
2120     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2121     {
2122         switch (pbEncoded[0] & ASN_TYPE_MASK)
2123         {
2124         case 1: /* rfc822Name */
2125         case 2: /* dNSName */
2126         case 6: /* uniformResourceIdentifier */
2127             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2128             break;
2129         case 7: /* iPAddress */
2130             bytesNeeded += dataLen;
2131             break;
2132         case 8: /* registeredID */
2133             /* FIXME: decode as OID */
2134         case 0: /* otherName */
2135         case 4: /* directoryName */
2136             FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2137             SetLastError(CRYPT_E_ASN1_BADTAG);
2138             ret = FALSE;
2139             break;
2140         case 3: /* x400Address, unimplemented */
2141         case 5: /* ediPartyName, unimplemented */
2142             TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2143             SetLastError(CRYPT_E_ASN1_BADTAG);
2144             ret = FALSE;
2145             break;
2146         default:
2147             TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2148             SetLastError(CRYPT_E_ASN1_CORRUPT);
2149             ret = FALSE;
2150         }
2151         if (ret)
2152         {
2153             if (!entry)
2154                 *pcbStructInfo = bytesNeeded;
2155             else if (*pcbStructInfo < bytesNeeded)
2156             {
2157                 *pcbStructInfo = bytesNeeded;
2158                 SetLastError(ERROR_MORE_DATA);
2159                 ret = FALSE;
2160             }
2161             else
2162             {
2163                 *pcbStructInfo = bytesNeeded;
2164                 /* MS used values one greater than the asn1 ones.. sigh */
2165                 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2166                 switch (pbEncoded[0] & ASN_TYPE_MASK)
2167                 {
2168                 case 1: /* rfc822Name */
2169                 case 2: /* dNSName */
2170                 case 6: /* uniformResourceIdentifier */
2171                 {
2172                     DWORD i;
2173
2174                     for (i = 0; i < dataLen; i++)
2175                         entry->u.pwszURL[i] =
2176                          (WCHAR)pbEncoded[1 + lenBytes + i];
2177                     entry->u.pwszURL[i] = 0;
2178                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2179                      debugstr_w(entry->u.pwszURL));
2180                     break;
2181                 }
2182                 case 7: /* iPAddress */
2183                     /* The next data pointer is in the pwszURL spot, that is,
2184                      * the first 4 bytes.  Need to move it to the next spot.
2185                      */
2186                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2187                     entry->u.IPAddress.cbData = dataLen;
2188                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2189                      dataLen);
2190                     break;
2191                 }
2192             }
2193         }
2194     }
2195     return ret;
2196 }
2197
2198 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2199  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2200  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2201 {
2202     BOOL ret = TRUE;
2203     struct AsnArrayDescriptor arrayDesc = { 0,
2204      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2205      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2206     PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2207
2208     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2209      pDecodePara, pvStructInfo, *pcbStructInfo);
2210
2211     if (info)
2212         TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2213     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2214      pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2215     return ret;
2216 }
2217
2218 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2219  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2220  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2221 {
2222     BOOL ret;
2223
2224     __TRY
2225     {
2226         struct AsnDecodeSequenceItem items[] = {
2227          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2228            CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2229            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2230          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2231            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2232            CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2233            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2234          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2235            CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2236            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2237            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2238         };
2239
2240         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2241          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2242          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2243     }
2244     __EXCEPT_PAGE_FAULT
2245     {
2246         SetLastError(STATUS_ACCESS_VIOLATION);
2247         ret = FALSE;
2248     }
2249     __ENDTRY
2250     return ret;
2251 }
2252
2253 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2254  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2255  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2256 {
2257     BOOL ret;
2258
2259     __TRY
2260     {
2261         struct AsnDecodeSequenceItem items[] = {
2262          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2263            CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2264            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2265          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2266            offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2267            CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2268            TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2269            AuthorityCertIssuer.rgAltEntry), 0 },
2270          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2271            AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2272            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2273            offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2274            AuthorityCertSerialNumber.pbData), 0 },
2275         };
2276
2277         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2278          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2279          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2280     }
2281     __EXCEPT_PAGE_FAULT
2282     {
2283         SetLastError(STATUS_ACCESS_VIOLATION);
2284         ret = FALSE;
2285     }
2286     __ENDTRY
2287     return ret;
2288 }
2289
2290 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2291  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2292  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2293 {
2294     BOOL ret;
2295     DWORD dataLen;
2296
2297     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2298      pDecodePara, pvStructInfo, *pcbStructInfo);
2299
2300     /* The caller has already checked the tag, no need to check it again.
2301      * Check the outer length is valid by calling CRYPT_GetLen:
2302      */
2303     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2304     {
2305         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2306         DWORD innerLen;
2307
2308         pbEncoded += 1 + lenBytes;
2309         /* Check the inner length is valid by calling CRYPT_GetLen again: */
2310         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2311         {
2312             ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2313              pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2314              pcbStructInfo);
2315         }
2316     }
2317     return ret;
2318 }
2319
2320 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2321  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2322  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2323  void *pvStructInfo, DWORD *pcbStructInfo)
2324 {
2325     CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2326     struct AsnDecodeSequenceItem items[] = {
2327      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2328        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2329        offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2330      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2331        offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2332        sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2333        offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2334     };
2335     BOOL ret;
2336
2337     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2338      pDecodePara, pvStructInfo, *pcbStructInfo);
2339
2340     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2341      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2342      pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2343     return ret;
2344 }
2345
2346 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2347  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2348  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2349 {
2350     BOOL ret = FALSE;
2351
2352     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2353      pDecodePara, pvStructInfo, *pcbStructInfo);
2354
2355     __TRY
2356     {
2357         ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2358          lpszStructType, pbEncoded, cbEncoded,
2359          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2360         if (ret && pvStructInfo)
2361         {
2362             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2363              pcbStructInfo, *pcbStructInfo);
2364             if (ret)
2365             {
2366                 CRYPT_CONTENT_INFO *info;
2367
2368                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2369                     pvStructInfo = *(BYTE **)pvStructInfo;
2370                 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2371                 info->pszObjId = (LPSTR)((BYTE *)info +
2372                  sizeof(CRYPT_CONTENT_INFO));
2373                 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2374                  lpszStructType, pbEncoded, cbEncoded,
2375                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2376                  pcbStructInfo);
2377             }
2378         }
2379     }
2380     __EXCEPT_PAGE_FAULT
2381     {
2382         SetLastError(STATUS_ACCESS_VIOLATION);
2383     }
2384     __ENDTRY
2385     return ret;
2386 }
2387
2388 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2389  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2390  CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2391 {
2392     BOOL ret;
2393     struct AsnDecodeSequenceItem items[] = {
2394      { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2395        sizeof(DWORD), FALSE, FALSE, 0, 0 },
2396      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2397        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2398        FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2399        0 },
2400      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2401        CRYPT_AsnDecodePKCSContentInfoInternal,
2402        sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2403        ContentInfo.pszObjId), 0 },
2404      { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2405        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2406        offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2407     };
2408
2409     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2410      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2411      pDecodePara, digestedData, pcbDigestedData, NULL);
2412     return ret;
2413 }
2414
2415 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2416  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2417  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2418 {
2419     BOOL ret = TRUE;
2420
2421     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2422      pDecodePara, pvStructInfo, *pcbStructInfo);
2423
2424     __TRY
2425     {
2426         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2427          CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2428          offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2429
2430         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2431          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2432     }
2433     __EXCEPT_PAGE_FAULT
2434     {
2435         SetLastError(STATUS_ACCESS_VIOLATION);
2436         ret = FALSE;
2437     }
2438     __ENDTRY
2439     return ret;
2440 }
2441
2442 struct PATH_LEN_CONSTRAINT
2443 {
2444     BOOL  fPathLenConstraint;
2445     DWORD dwPathLenConstraint;
2446 };
2447
2448 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2449  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2450  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2451 {
2452     BOOL ret = TRUE;
2453
2454     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2455      pvStructInfo, *pcbStructInfo);
2456
2457     if (cbEncoded)
2458     {
2459         if (pbEncoded[0] == ASN_INTEGER)
2460         {
2461             DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2462
2463             if (!pvStructInfo)
2464                 *pcbStructInfo = bytesNeeded;
2465             else if (*pcbStructInfo < bytesNeeded)
2466             {
2467                 SetLastError(ERROR_MORE_DATA);
2468                 *pcbStructInfo = bytesNeeded;
2469                 ret = FALSE;
2470             }
2471             else
2472             {
2473                 struct PATH_LEN_CONSTRAINT *constraint =
2474                  (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2475                 DWORD size = sizeof(constraint->dwPathLenConstraint);
2476
2477                 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2478                  pbEncoded, cbEncoded, 0, NULL,
2479                  &constraint->dwPathLenConstraint, &size);
2480                 if (ret)
2481                     constraint->fPathLenConstraint = TRUE;
2482                 TRACE("got an int, dwPathLenConstraint is %d\n",
2483                  constraint->dwPathLenConstraint);
2484             }
2485         }
2486         else
2487         {
2488             SetLastError(CRYPT_E_ASN1_CORRUPT);
2489             ret = FALSE;
2490         }
2491     }
2492     TRACE("returning %d (%08x)\n", ret, GetLastError());
2493     return ret;
2494 }
2495
2496 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2497  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2498  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2499 {
2500     BOOL ret;
2501     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2502      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2503      offsetof(CERT_NAME_BLOB, pbData) };
2504     struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2505
2506     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2507      pDecodePara, pvStructInfo, *pcbStructInfo);
2508
2509     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2510      pDecodePara, pvStructInfo, pcbStructInfo,
2511      entries ? entries->rgItems : NULL);
2512     TRACE("Returning %d (%08x)\n", ret, GetLastError());
2513     return ret;
2514 }
2515
2516 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2517  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2518  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2519 {
2520     BOOL ret;
2521
2522     __TRY
2523     {
2524         struct AsnDecodeSequenceItem items[] = {
2525          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2526            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
2527            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2528          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2529            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2530            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2531          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2532            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2533            sizeof(struct GenericArray), TRUE, TRUE,
2534            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2535         };
2536
2537         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2538          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2539          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2540     }
2541     __EXCEPT_PAGE_FAULT
2542     {
2543         SetLastError(STATUS_ACCESS_VIOLATION);
2544         ret = FALSE;
2545     }
2546     __ENDTRY
2547     return ret;
2548 }
2549
2550 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2551  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2552  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2553 {
2554     BOOL ret;
2555
2556     __TRY
2557     {
2558         struct AsnDecodeSequenceItem items[] = {
2559          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2560            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2561          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2562            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2563            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2564         };
2565
2566         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2567          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2568          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2569     }
2570     __EXCEPT_PAGE_FAULT
2571     {
2572         SetLastError(STATUS_ACCESS_VIOLATION);
2573         ret = FALSE;
2574     }
2575     __ENDTRY
2576     return ret;
2577 }
2578
2579 #define RSA1_MAGIC 0x31415352
2580
2581 struct DECODED_RSA_PUB_KEY
2582 {
2583     DWORD              pubexp;
2584     CRYPT_INTEGER_BLOB modulus;
2585 };
2586
2587 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2588  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2589  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2590 {
2591     BOOL ret;
2592
2593     __TRY
2594     {
2595         struct AsnDecodeSequenceItem items[] = {
2596          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2597            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2598            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2599            0 },
2600          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2601            CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2602         };
2603         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2604         DWORD size = 0;
2605
2606         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2607          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2608          CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2609         if (ret)
2610         {
2611             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2612              decodedKey->modulus.cbData;
2613
2614             if (!pvStructInfo)
2615             {
2616                 *pcbStructInfo = bytesNeeded;
2617                 ret = TRUE;
2618             }
2619             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2620              pvStructInfo, pcbStructInfo, bytesNeeded)))
2621             {
2622                 BLOBHEADER *hdr;
2623                 RSAPUBKEY *rsaPubKey;
2624
2625                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2626                     pvStructInfo = *(BYTE **)pvStructInfo;
2627                 hdr = (BLOBHEADER *)pvStructInfo;
2628                 hdr->bType = PUBLICKEYBLOB;
2629                 hdr->bVersion = CUR_BLOB_VERSION;
2630                 hdr->reserved = 0;
2631                 hdr->aiKeyAlg = CALG_RSA_KEYX;
2632                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2633                  sizeof(BLOBHEADER));
2634                 rsaPubKey->magic = RSA1_MAGIC;
2635                 rsaPubKey->pubexp = decodedKey->pubexp;
2636                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2637                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2638                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2639                  decodedKey->modulus.cbData);
2640             }
2641             LocalFree(decodedKey);
2642         }
2643     }
2644     __EXCEPT_PAGE_FAULT
2645     {
2646         SetLastError(STATUS_ACCESS_VIOLATION);
2647         ret = FALSE;
2648     }
2649     __ENDTRY
2650     return ret;
2651 }
2652
2653 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2654  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2655  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2656 {
2657     BOOL ret;
2658     DWORD bytesNeeded, dataLen;
2659
2660     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2661      pDecodePara, pvStructInfo, *pcbStructInfo);
2662
2663     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2664     {
2665         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2666             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2667         else
2668             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2669         if (!pvStructInfo)
2670             *pcbStructInfo = bytesNeeded;
2671         else if (*pcbStructInfo < bytesNeeded)
2672         {
2673             SetLastError(ERROR_MORE_DATA);
2674             *pcbStructInfo = bytesNeeded;
2675             ret = FALSE;
2676         }
2677         else
2678         {
2679             CRYPT_DATA_BLOB *blob;
2680             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2681
2682             blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2683             blob->cbData = dataLen;
2684             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2685                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2686             else
2687             {
2688                 assert(blob->pbData);
2689                 if (blob->cbData)
2690                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2691                      blob->cbData);
2692             }
2693         }
2694     }
2695     return ret;
2696 }
2697
2698 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2699  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2700  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2701 {
2702     BOOL ret;
2703
2704     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2705      pDecodePara, pvStructInfo, *pcbStructInfo);
2706
2707     __TRY
2708     {
2709         DWORD bytesNeeded;
2710
2711         if (!cbEncoded)
2712         {
2713             SetLastError(CRYPT_E_ASN1_CORRUPT);
2714             ret = FALSE;
2715         }
2716         else if (pbEncoded[0] != ASN_OCTETSTRING)
2717         {
2718             SetLastError(CRYPT_E_ASN1_BADTAG);
2719             ret = FALSE;
2720         }
2721         else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2722          lpszStructType, pbEncoded, cbEncoded,
2723          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2724         {
2725             if (!pvStructInfo)
2726                 *pcbStructInfo = bytesNeeded;
2727             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2728              pvStructInfo, pcbStructInfo, bytesNeeded)))
2729             {
2730                 CRYPT_DATA_BLOB *blob;
2731
2732                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2733                     pvStructInfo = *(BYTE **)pvStructInfo;
2734                 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2735                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2736                 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2737                  lpszStructType, pbEncoded, cbEncoded,
2738                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2739                  &bytesNeeded);
2740             }
2741         }
2742     }
2743     __EXCEPT_PAGE_FAULT
2744     {
2745         SetLastError(STATUS_ACCESS_VIOLATION);
2746         ret = FALSE;
2747     }
2748     __ENDTRY
2749     return ret;
2750 }
2751
2752 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2753  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2754  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2755 {
2756     BOOL ret;
2757
2758     TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2759      pDecodePara, pvStructInfo, *pcbStructInfo);
2760
2761     if (pbEncoded[0] == ASN_BITSTRING)
2762     {
2763         DWORD bytesNeeded, dataLen;
2764
2765         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2766         {
2767             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2768                 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2769             else
2770                 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2771             if (!pvStructInfo)
2772                 *pcbStructInfo = bytesNeeded;
2773             else if (*pcbStructInfo < bytesNeeded)
2774             {
2775                 *pcbStructInfo = bytesNeeded;
2776                 SetLastError(ERROR_MORE_DATA);
2777                 ret = FALSE;
2778             }
2779             else
2780             {
2781                 CRYPT_BIT_BLOB *blob;
2782
2783                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2784                 blob->cbData = dataLen - 1;
2785                 blob->cUnusedBits = *(pbEncoded + 1 +
2786                  GET_LEN_BYTES(pbEncoded[1]));
2787                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2788                 {
2789                     blob->pbData = (BYTE *)pbEncoded + 2 +
2790                      GET_LEN_BYTES(pbEncoded[1]);
2791                 }
2792                 else
2793                 {
2794                     assert(blob->pbData);
2795                     if (blob->cbData)
2796                     {
2797                         BYTE mask = 0xff << blob->cUnusedBits;
2798
2799                         memcpy(blob->pbData, pbEncoded + 2 +
2800                          GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2801                         blob->pbData[blob->cbData - 1] &= mask;
2802                     }
2803                 }
2804             }
2805         }
2806     }
2807     else
2808     {
2809         SetLastError(CRYPT_E_ASN1_BADTAG);
2810         ret = FALSE;
2811     }
2812     TRACE("returning %d (%08x)\n", ret, GetLastError());
2813     return ret;
2814 }
2815
2816 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2817  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2818  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2819 {
2820     BOOL ret;
2821
2822     TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2823      pDecodePara, pvStructInfo, pcbStructInfo);
2824
2825     __TRY
2826     {
2827         DWORD bytesNeeded;
2828
2829         if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2830          lpszStructType, pbEncoded, cbEncoded,
2831          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2832         {
2833             if (!pvStructInfo)
2834                 *pcbStructInfo = bytesNeeded;
2835             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2836              pvStructInfo, pcbStructInfo, bytesNeeded)))
2837             {
2838                 CRYPT_BIT_BLOB *blob;
2839
2840                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2841                     pvStructInfo = *(BYTE **)pvStructInfo;
2842                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2843                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2844                 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2845                  lpszStructType, pbEncoded, cbEncoded,
2846                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2847                  &bytesNeeded);
2848             }
2849         }
2850     }
2851     __EXCEPT_PAGE_FAULT
2852     {
2853         SetLastError(STATUS_ACCESS_VIOLATION);
2854         ret = FALSE;
2855     }
2856     __ENDTRY
2857     TRACE("returning %d (%08x)\n", ret, GetLastError());
2858     return ret;
2859 }
2860
2861 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2862  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2863  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2864 {
2865     BOOL ret;
2866
2867     if (!pvStructInfo)
2868     {
2869         *pcbStructInfo = sizeof(int);
2870         return TRUE;
2871     }
2872     __TRY
2873     {
2874         BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2875         CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2876         DWORD size = sizeof(buf);
2877
2878         blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2879         if (pbEncoded[0] != ASN_INTEGER)
2880         {
2881             SetLastError(CRYPT_E_ASN1_BADTAG);
2882             ret = FALSE;
2883         }
2884         else
2885             ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2886              X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2887              &size);
2888         if (ret)
2889         {
2890             if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2891              pvStructInfo, pcbStructInfo, sizeof(int))))
2892             {
2893                 int val, i;
2894
2895                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2896                     pvStructInfo = *(BYTE **)pvStructInfo;
2897                 if (blob->pbData[blob->cbData - 1] & 0x80)
2898                 {
2899                     /* initialize to a negative value to sign-extend */
2900                     val = -1;
2901                 }
2902                 else
2903                     val = 0;
2904                 for (i = 0; i < blob->cbData; i++)
2905                 {
2906                     val <<= 8;
2907                     val |= blob->pbData[blob->cbData - i - 1];
2908                 }
2909                 memcpy(pvStructInfo, &val, sizeof(int));
2910             }
2911         }
2912         else if (GetLastError() == ERROR_MORE_DATA)
2913             SetLastError(CRYPT_E_ASN1_LARGE);
2914     }
2915     __EXCEPT_PAGE_FAULT
2916     {
2917         SetLastError(STATUS_ACCESS_VIOLATION);
2918         ret = FALSE;
2919     }
2920     __ENDTRY
2921     return ret;
2922 }
2923
2924 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2925  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2926  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2927 {
2928     BOOL ret;
2929     DWORD bytesNeeded, dataLen;
2930
2931     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2932     {
2933         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2934
2935         bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2936         if (!pvStructInfo)
2937             *pcbStructInfo = bytesNeeded;
2938         else if (*pcbStructInfo < bytesNeeded)
2939         {
2940             *pcbStructInfo = bytesNeeded;
2941             SetLastError(ERROR_MORE_DATA);
2942             ret = FALSE;
2943         }
2944         else
2945         {
2946             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2947
2948             blob->cbData = dataLen;
2949             assert(blob->pbData);
2950             if (blob->cbData)
2951             {
2952                 DWORD i;
2953
2954                 for (i = 0; i < blob->cbData; i++)
2955                 {
2956                     blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2957                      dataLen - i - 1);
2958                 }
2959             }
2960         }
2961     }
2962     return ret;
2963 }
2964
2965 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2966  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2967  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2968 {
2969     BOOL ret;
2970
2971     __TRY
2972     {
2973         DWORD bytesNeeded;
2974
2975         if (pbEncoded[0] != ASN_INTEGER)
2976         {
2977             SetLastError(CRYPT_E_ASN1_BADTAG);
2978             ret = FALSE;
2979         }
2980         else
2981             ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2982              lpszStructType, pbEncoded, cbEncoded,
2983              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2984         if (ret)
2985         {
2986             if (!pvStructInfo)
2987                 *pcbStructInfo = bytesNeeded;
2988             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2989              pvStructInfo, pcbStructInfo, bytesNeeded)))
2990             {
2991                 CRYPT_INTEGER_BLOB *blob;
2992
2993                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2994                     pvStructInfo = *(BYTE **)pvStructInfo;
2995                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2996                 blob->pbData = (BYTE *)pvStructInfo +
2997                  sizeof(CRYPT_INTEGER_BLOB);
2998                 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2999                  lpszStructType, pbEncoded, cbEncoded,
3000                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3001                  &bytesNeeded);
3002             }
3003         }
3004     }
3005     __EXCEPT_PAGE_FAULT
3006     {
3007         SetLastError(STATUS_ACCESS_VIOLATION);
3008         ret = FALSE;
3009     }
3010     __ENDTRY
3011     return ret;
3012 }
3013
3014 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3015  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3016  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3017  void *pvStructInfo, DWORD *pcbStructInfo)
3018 {
3019     BOOL ret;
3020
3021     if (pbEncoded[0] == ASN_INTEGER)
3022     {
3023         DWORD bytesNeeded, dataLen;
3024
3025         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3026         {
3027             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3028
3029             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3030             if (!pvStructInfo)
3031                 *pcbStructInfo = bytesNeeded;
3032             else if (*pcbStructInfo < bytesNeeded)
3033             {
3034                 *pcbStructInfo = bytesNeeded;
3035                 SetLastError(ERROR_MORE_DATA);
3036                 ret = FALSE;
3037             }
3038             else
3039             {
3040                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3041
3042                 blob->cbData = dataLen;
3043                 assert(blob->pbData);
3044                 /* remove leading zero byte if it exists */
3045                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3046                 {
3047                     blob->cbData--;
3048                     blob->pbData++;
3049                 }
3050                 if (blob->cbData)
3051                 {
3052                     DWORD i;
3053
3054                     for (i = 0; i < blob->cbData; i++)
3055                     {
3056                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3057                          dataLen - i - 1);
3058                     }
3059                 }
3060             }
3061         }
3062     }
3063     else
3064     {
3065         SetLastError(CRYPT_E_ASN1_BADTAG);
3066         ret = FALSE;
3067     }
3068     return ret;
3069 }
3070
3071 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3072  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3073  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3074 {
3075     BOOL ret;
3076
3077     __TRY
3078     {
3079         DWORD bytesNeeded;
3080
3081         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3082          lpszStructType, pbEncoded, cbEncoded,
3083          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3084         {
3085             if (!pvStructInfo)
3086                 *pcbStructInfo = bytesNeeded;
3087             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3088              pvStructInfo, pcbStructInfo, bytesNeeded)))
3089             {
3090                 CRYPT_INTEGER_BLOB *blob;
3091
3092                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3093                     pvStructInfo = *(BYTE **)pvStructInfo;
3094                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3095                 blob->pbData = (BYTE *)pvStructInfo +
3096                  sizeof(CRYPT_INTEGER_BLOB);
3097                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3098                  lpszStructType, pbEncoded, cbEncoded,
3099                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3100                  &bytesNeeded);
3101             }
3102         }
3103     }
3104     __EXCEPT_PAGE_FAULT
3105     {
3106         SetLastError(STATUS_ACCESS_VIOLATION);
3107         ret = FALSE;
3108     }
3109     __ENDTRY
3110     return ret;
3111 }
3112
3113 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3114  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3115  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3116 {
3117     BOOL ret;
3118
3119     if (!pvStructInfo)
3120     {
3121         *pcbStructInfo = sizeof(int);
3122         return TRUE;
3123     }
3124     __TRY
3125     {
3126         if (pbEncoded[0] == ASN_ENUMERATED)
3127         {
3128             unsigned int val = 0, i;
3129
3130             if (cbEncoded <= 1)
3131             {
3132                 SetLastError(CRYPT_E_ASN1_EOD);
3133                 ret = FALSE;
3134             }
3135             else if (pbEncoded[1] == 0)
3136             {
3137                 SetLastError(CRYPT_E_ASN1_CORRUPT);
3138                 ret = FALSE;
3139             }
3140             else
3141             {
3142                 /* A little strange looking, but we have to accept a sign byte:
3143                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
3144                  * assuming a small length is okay here, it has to be in short
3145                  * form.
3146                  */
3147                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3148                 {
3149                     SetLastError(CRYPT_E_ASN1_LARGE);
3150                     return FALSE;
3151                 }
3152                 for (i = 0; i < pbEncoded[1]; i++)
3153                 {
3154                     val <<= 8;
3155                     val |= pbEncoded[2 + i];
3156                 }
3157                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3158                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3159                 {
3160                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3161                         pvStructInfo = *(BYTE **)pvStructInfo;
3162                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
3163                 }
3164             }
3165         }
3166         else
3167         {
3168             SetLastError(CRYPT_E_ASN1_BADTAG);
3169             ret = FALSE;
3170         }
3171     }
3172     __EXCEPT_PAGE_FAULT
3173     {
3174         SetLastError(STATUS_ACCESS_VIOLATION);
3175         ret = FALSE;
3176     }
3177     __ENDTRY
3178     return ret;
3179 }
3180
3181 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3182  * if it fails.
3183  */
3184 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3185  do { \
3186     BYTE i; \
3187  \
3188     (word) = 0; \
3189     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3190     { \
3191         if (!isdigit(*(pbEncoded))) \
3192         { \
3193             SetLastError(CRYPT_E_ASN1_CORRUPT); \
3194             ret = FALSE; \
3195         } \
3196         else \
3197         { \
3198             (word) *= 10; \
3199             (word) += *(pbEncoded)++ - '0'; \
3200         } \
3201     } \
3202  } while (0)
3203
3204 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3205  SYSTEMTIME *sysTime)
3206 {
3207     BOOL ret;
3208
3209     __TRY
3210     {
3211         ret = TRUE;
3212         if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3213         {
3214             WORD hours, minutes = 0;
3215             BYTE sign = *pbEncoded++;
3216
3217             len--;
3218             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3219             if (ret && hours >= 24)
3220             {
3221                 SetLastError(CRYPT_E_ASN1_CORRUPT);
3222                 ret = FALSE;
3223             }
3224             else if (len >= 2)
3225             {
3226                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3227                 if (ret && minutes >= 60)
3228                 {
3229                     SetLastError(CRYPT_E_ASN1_CORRUPT);
3230                     ret = FALSE;
3231                 }
3232             }
3233             if (ret)
3234             {
3235                 if (sign == '+')
3236                 {
3237                     sysTime->wHour += hours;
3238                     sysTime->wMinute += minutes;
3239                 }
3240                 else
3241                 {
3242                     if (hours > sysTime->wHour)
3243                     {
3244                         sysTime->wDay--;
3245                         sysTime->wHour = 24 - (hours - sysTime->wHour);
3246                     }
3247                     else
3248                         sysTime->wHour -= hours;
3249                     if (minutes > sysTime->wMinute)
3250                     {
3251                         sysTime->wHour--;
3252                         sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3253                     }
3254                     else
3255                         sysTime->wMinute -= minutes;
3256                 }
3257             }
3258         }
3259     }
3260     __EXCEPT_PAGE_FAULT
3261     {
3262         SetLastError(STATUS_ACCESS_VIOLATION);
3263         ret = FALSE;
3264     }
3265     __ENDTRY
3266     return ret;
3267 }
3268
3269 #define MIN_ENCODED_TIME_LENGTH 10
3270
3271 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3272  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3273  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3274 {
3275     BOOL ret;
3276
3277     if (!pvStructInfo)
3278     {
3279         *pcbStructInfo = sizeof(FILETIME);
3280         return TRUE;
3281     }
3282     __TRY
3283     {
3284         ret = TRUE;
3285         if (pbEncoded[0] == ASN_UTCTIME)
3286         {
3287             if (cbEncoded <= 1)
3288             {
3289                 SetLastError(CRYPT_E_ASN1_EOD);
3290                 ret = FALSE;
3291             }
3292             else if (pbEncoded[1] > 0x7f)
3293             {
3294                 /* long-form date strings really can't be valid */
3295                 SetLastError(CRYPT_E_ASN1_CORRUPT);
3296                 ret = FALSE;
3297             }
3298             else
3299             {
3300                 SYSTEMTIME sysTime = { 0 };
3301                 BYTE len = pbEncoded[1];
3302
3303                 if (len < MIN_ENCODED_TIME_LENGTH)
3304                 {
3305                     SetLastError(CRYPT_E_ASN1_CORRUPT);
3306                     ret = FALSE;
3307                 }
3308                 else
3309                 {
3310                     pbEncoded += 2;
3311                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3312                     if (sysTime.wYear >= 50)
3313                         sysTime.wYear += 1900;
3314                     else
3315                         sysTime.wYear += 2000;
3316                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3317                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3318                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3319                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3320                     if (ret && len > 0)
3321                     {
3322                         if (len >= 2 && isdigit(*pbEncoded) &&
3323                          isdigit(*(pbEncoded + 1)))
3324                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3325                              sysTime.wSecond);
3326                         else if (isdigit(*pbEncoded))
3327                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3328                              sysTime.wSecond);
3329                         if (ret)
3330                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3331                              &sysTime);
3332                     }
3333                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3334                      pDecodePara, pvStructInfo, pcbStructInfo,
3335                      sizeof(FILETIME))))
3336                     {
3337                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3338                             pvStructInfo = *(BYTE **)pvStructInfo;
3339                         ret = SystemTimeToFileTime(&sysTime,
3340                          (FILETIME *)pvStructInfo);
3341                     }
3342                 }
3343             }
3344         }
3345         else
3346         {
3347             SetLastError(CRYPT_E_ASN1_BADTAG);
3348             ret = FALSE;
3349         }
3350     }
3351     __EXCEPT_PAGE_FAULT
3352     {
3353         SetLastError(STATUS_ACCESS_VIOLATION);
3354         ret = FALSE;
3355     }
3356     __ENDTRY
3357     return ret;
3358 }
3359
3360 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3361  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3362  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3363 {
3364     BOOL ret;
3365
3366     if (!pvStructInfo)
3367     {
3368         *pcbStructInfo = sizeof(FILETIME);
3369         return TRUE;
3370     }
3371     __TRY
3372     {
3373         ret = TRUE;
3374         if (pbEncoded[0] == ASN_GENERALTIME)
3375         {
3376             if (cbEncoded <= 1)
3377             {
3378                 SetLastError(CRYPT_E_ASN1_EOD);
3379                 ret = FALSE;
3380             }
3381             else if (pbEncoded[1] > 0x7f)
3382             {
3383                 /* long-form date strings really can't be valid */
3384                 SetLastError(CRYPT_E_ASN1_CORRUPT);
3385                 ret = FALSE;
3386             }
3387             else
3388             {
3389                 BYTE len = pbEncoded[1];
3390
3391                 if (len < MIN_ENCODED_TIME_LENGTH)
3392                 {
3393                     SetLastError(CRYPT_E_ASN1_CORRUPT);
3394                     ret = FALSE;
3395                 }
3396                 else
3397                 {
3398                     SYSTEMTIME sysTime = { 0 };
3399
3400                     pbEncoded += 2;
3401                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3402                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3403                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3404                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3405                     if (ret && len > 0)
3406                     {
3407                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3408                          sysTime.wMinute);
3409                         if (ret && len > 0)
3410                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3411                              sysTime.wSecond);
3412                         if (ret && len > 0 && (*pbEncoded == '.' ||
3413                          *pbEncoded == ','))
3414                         {
3415                             BYTE digits;
3416
3417                             pbEncoded++;
3418                             len--;
3419                             /* workaround macro weirdness */
3420                             digits = min(len, 3);
3421                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3422                              sysTime.wMilliseconds);
3423                         }
3424                         if (ret)
3425                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3426                              &sysTime);
3427                     }
3428                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3429                      pDecodePara, pvStructInfo, pcbStructInfo,
3430                      sizeof(FILETIME))))
3431                     {
3432                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3433                             pvStructInfo = *(BYTE **)pvStructInfo;
3434                         ret = SystemTimeToFileTime(&sysTime,
3435                          (FILETIME *)pvStructInfo);
3436                     }
3437                 }
3438             }
3439         }
3440         else
3441         {
3442             SetLastError(CRYPT_E_ASN1_BADTAG);
3443             ret = FALSE;
3444         }
3445     }
3446     __EXCEPT_PAGE_FAULT
3447     {
3448         SetLastError(STATUS_ACCESS_VIOLATION);
3449         ret = FALSE;
3450     }
3451     __ENDTRY
3452     return ret;
3453 }
3454
3455 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3456  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3457  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3458 {
3459     BOOL ret;
3460
3461     __TRY
3462     {
3463         if (pbEncoded[0] == ASN_UTCTIME)
3464             ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3465              pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3466              pcbStructInfo);
3467         else if (pbEncoded[0] == ASN_GENERALTIME)
3468             ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3469              lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3470              pvStructInfo, pcbStructInfo);
3471         else
3472         {
3473             SetLastError(CRYPT_E_ASN1_BADTAG);
3474             ret = FALSE;
3475         }
3476     }
3477     __EXCEPT_PAGE_FAULT
3478     {
3479         SetLastError(STATUS_ACCESS_VIOLATION);
3480         ret = FALSE;
3481     }
3482     __ENDTRY
3483     return ret;
3484 }
3485
3486 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3487  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3488  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3489 {
3490     BOOL ret = TRUE;
3491
3492     __TRY
3493     {
3494         if (pbEncoded[0] == ASN_SEQUENCEOF)
3495         {
3496             DWORD bytesNeeded, dataLen, remainingLen, cValue;
3497
3498             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3499             {
3500                 BYTE lenBytes;
3501                 const BYTE *ptr;
3502
3503                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3504                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3505                 cValue = 0;
3506                 ptr = pbEncoded + 1 + lenBytes;
3507                 remainingLen = dataLen;
3508                 while (ret && remainingLen)
3509                 {
3510                     DWORD nextLen;
3511
3512                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3513                     if (ret)
3514                     {
3515                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3516
3517                         remainingLen -= 1 + nextLenBytes + nextLen;
3518                         ptr += 1 + nextLenBytes + nextLen;
3519                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
3520                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3521                             bytesNeeded += 1 + nextLenBytes + nextLen;
3522                         cValue++;
3523                     }
3524                 }
3525                 if (ret)
3526                 {
3527                     CRYPT_SEQUENCE_OF_ANY *seq;
3528                     BYTE *nextPtr;
3529                     DWORD i;
3530
3531                     if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3532                      pvStructInfo, pcbStructInfo, bytesNeeded)))
3533                     {
3534                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3535                             pvStructInfo = *(BYTE **)pvStructInfo;
3536                         seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3537                         seq->cValue = cValue;
3538                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3539                          sizeof(*seq));
3540                         nextPtr = (BYTE *)seq->rgValue +
3541                          cValue * sizeof(CRYPT_DER_BLOB);
3542                         ptr = pbEncoded + 1 + lenBytes;
3543                         remainingLen = dataLen;
3544                         i = 0;
3545                         while (ret && remainingLen)
3546                         {
3547                             DWORD nextLen;
3548
3549                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3550                             if (ret)
3551                             {
3552                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3553
3554                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
3555                                  nextLen;
3556                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3557                                     seq->rgValue[i].pbData = (BYTE *)ptr;
3558                                 else
3559                                 {
3560                                     seq->rgValue[i].pbData = nextPtr;
3561                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
3562                                      nextLen);
3563                                     nextPtr += 1 + nextLenBytes + nextLen;
3564                                 }
3565                                 remainingLen -= 1 + nextLenBytes + nextLen;
3566                                 ptr += 1 + nextLenBytes + nextLen;
3567                                 i++;
3568                             }
3569                         }
3570                     }
3571                 }
3572             }
3573         }
3574         else
3575         {
3576             SetLastError(CRYPT_E_ASN1_BADTAG);
3577             ret = FALSE;
3578         }
3579     }
3580     __EXCEPT_PAGE_FAULT
3581     {
3582         SetLastError(STATUS_ACCESS_VIOLATION);
3583         ret = FALSE;
3584     }
3585     __ENDTRY
3586     return ret;
3587 }
3588
3589 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3590  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3591  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3592 {
3593     BOOL ret;
3594
3595     if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3596     {
3597         DWORD bytesNeeded, dataLen;
3598
3599         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3600         {
3601             struct AsnArrayDescriptor arrayDesc = {
3602              ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3603              sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3604              offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3605             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3606
3607             if (dataLen)
3608             {
3609                 DWORD nameLen;
3610
3611                 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3612                  pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3613                  0, NULL, NULL, &nameLen, NULL);
3614                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3615             }
3616             else
3617                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3618             if (!pvStructInfo)
3619                 *pcbStructInfo = bytesNeeded;
3620             else if (*pcbStructInfo < bytesNeeded)
3621             {
3622                 *pcbStructInfo = bytesNeeded;
3623                 SetLastError(ERROR_MORE_DATA);
3624                 ret = FALSE;
3625             }
3626             else
3627             {
3628                 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3629
3630                 if (dataLen)
3631                 {
3632                     name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3633                     ret = CRYPT_AsnDecodeArray(&arrayDesc,
3634                      pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3635                      0, NULL, &name->u.FullName, pcbStructInfo,
3636                      name->u.FullName.rgAltEntry);
3637                 }
3638                 else
3639                     name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3640             }
3641         }
3642     }
3643     else
3644     {
3645         SetLastError(CRYPT_E_ASN1_BADTAG);
3646         ret = FALSE;
3647     }
3648     return ret;
3649 }
3650
3651 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3652  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3653  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3654 {
3655     struct AsnDecodeSequenceItem items[] = {
3656      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3657        DistPointName), CRYPT_AsnDecodeDistPointName,
3658        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3659        DistPointName.u.FullName.rgAltEntry), 0 },
3660      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3661        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3662        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3663      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3664        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3665        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3666     };
3667     BOOL ret;
3668
3669     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3670      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3671      dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3672     return ret;
3673 }
3674
3675 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3676  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3677  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3678 {
3679     BOOL ret;
3680
3681     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3682      pDecodePara, pvStructInfo, *pcbStructInfo);
3683
3684     __TRY
3685     {
3686         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3687          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3688          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3689
3690         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3691          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3692     }
3693     __EXCEPT_PAGE_FAULT
3694     {
3695         SetLastError(STATUS_ACCESS_VIOLATION);
3696         ret = FALSE;
3697     }
3698     __ENDTRY
3699     return ret;
3700 }
3701
3702 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3703  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3704  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3705 {
3706     BOOL ret;
3707
3708     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3709      pDecodePara, pvStructInfo, *pcbStructInfo);
3710
3711     __TRY
3712     {
3713         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3714          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3715
3716         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3717          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3718     }
3719     __EXCEPT_PAGE_FAULT
3720     {
3721         SetLastError(STATUS_ACCESS_VIOLATION);
3722         ret = FALSE;
3723     }
3724     __ENDTRY
3725     return ret;
3726 }
3727
3728 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3729  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3730  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3731 {
3732     BOOL ret;
3733
3734     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3735      pDecodePara, pvStructInfo, *pcbStructInfo);
3736
3737     __TRY
3738     {
3739         struct AsnDecodeSequenceItem items[] = {
3740          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3741            DistPointName), CRYPT_AsnDecodeDistPointName,
3742            sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3743            offsetof(CRL_ISSUING_DIST_POINT,
3744            DistPointName.u.FullName.rgAltEntry), 0 },
3745          { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3746            fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3747            FALSE, 0 },
3748          { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3749            fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3750            FALSE, 0 },
3751          { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3752            OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3753            sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3754            OnlySomeReasonFlags.pbData), 0 },
3755          { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3756            fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3757         };
3758
3759         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3760          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3761          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3762     }
3763     __EXCEPT_PAGE_FAULT
3764     {
3765         SetLastError(STATUS_ACCESS_VIOLATION);
3766         ret = FALSE;
3767     }
3768     __ENDTRY
3769     return ret;
3770 }
3771
3772 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3773  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3774  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3775 {
3776     BOOL ret;
3777     struct AsnDecodeSequenceItem items[] = {
3778      { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3779        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3780        Issuer.pbData) },
3781      { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3782        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3783        TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3784     };
3785     CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3786      (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3787
3788     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3789      pDecodePara, pvStructInfo, *pcbStructInfo);
3790
3791     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3792      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3793      dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3794      issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3795     if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3796     {
3797         SetLastError(CRYPT_E_ASN1_CORRUPT);
3798         ret = FALSE;
3799     }
3800     TRACE("returning %d\n", ret);
3801     return ret;
3802 }
3803
3804 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfoInternal(
3805  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3806  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3807  void *pvStructInfo, DWORD *pcbStructInfo)
3808 {
3809     CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3810     struct AsnDecodeSequenceItem items[] = {
3811      { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3812        CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3813      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3814        CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3815        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3816      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3817        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3818        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3819      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3820        offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3821        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3822        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3823      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3824        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3825        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3826        HashEncryptionAlgorithm.pszObjId), 0 },
3827      { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3828        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3829        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3830      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3831        offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3832        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3833        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3834     };
3835     BOOL ret;
3836
3837     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3838      pDecodePara, pvStructInfo, *pcbStructInfo);
3839
3840     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3841      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3842      dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3843      info ? info->Issuer.pbData : NULL);
3844     return ret;
3845 }
3846
3847 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3848  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3849  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3850 {
3851     BOOL ret = FALSE;
3852
3853     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3854      pDecodePara, pvStructInfo, *pcbStructInfo);
3855
3856     __TRY
3857     {
3858         ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3859          lpszStructType, pbEncoded, cbEncoded,
3860          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3861         if (ret && pvStructInfo)
3862         {
3863             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3864              pcbStructInfo, *pcbStructInfo);
3865             if (ret)
3866             {
3867                 CMSG_SIGNER_INFO *info;
3868
3869                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3870                     pvStructInfo = *(BYTE **)pvStructInfo;
3871                 info = (CMSG_SIGNER_INFO *)pvStructInfo;
3872                 info->Issuer.pbData = ((BYTE *)info +
3873                  sizeof(CMSG_SIGNER_INFO));
3874                 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3875                  lpszStructType, pbEncoded, cbEncoded,
3876                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3877                  pcbStructInfo);
3878             }
3879         }
3880     }
3881     __EXCEPT_PAGE_FAULT
3882     {
3883         SetLastError(STATUS_ACCESS_VIOLATION);
3884     }
3885     __ENDTRY
3886     TRACE("returning %d\n", ret);
3887     return ret;
3888 }
3889
3890 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
3891  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3892  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3893 {
3894     BOOL ret;
3895     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
3896      CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
3897      offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
3898     struct GenericArray *array = (struct GenericArray *)pvStructInfo;
3899
3900     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3901      pDecodePara, pvStructInfo, *pcbStructInfo);
3902
3903     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3904      pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
3905     return ret;
3906 }
3907
3908 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
3909  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3910  CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
3911 {
3912     BOOL ret = FALSE;
3913     struct AsnDecodeSequenceItem items[] = {
3914      { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
3915        sizeof(DWORD), FALSE, FALSE, 0, 0 },
3916      /* Placeholder for the hash algorithms - redundant with those in the
3917       * signers, so just ignore them.
3918       */
3919      { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
3920      { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
3921        CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
3922        FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
3923      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3924        offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
3925        CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
3926        offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
3927      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3928        offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
3929        sizeof(struct GenericArray), TRUE, TRUE,
3930        offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
3931      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
3932        CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
3933        offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
3934     };
3935
3936     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3937      pDecodePara, signedInfo, *pcbSignedInfo);
3938
3939     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3940      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3941      pDecodePara, signedInfo, pcbSignedInfo, NULL);
3942     TRACE("returning %d\n", ret);
3943     return ret;
3944 }
3945
3946 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3947  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3948  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3949 {
3950     static HCRYPTOIDFUNCSET set = NULL;
3951     BOOL ret = FALSE;
3952     CryptDecodeObjectExFunc decodeFunc = NULL;
3953     HCRYPTOIDFUNCADDR hFunc = NULL;
3954
3955     TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3956      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3957      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3958
3959     if (!pvStructInfo && !pcbStructInfo)
3960     {
3961         SetLastError(ERROR_INVALID_PARAMETER);
3962         return FALSE;
3963     }
3964     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3965      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3966     {
3967         SetLastError(ERROR_FILE_NOT_FOUND);
3968         return FALSE;
3969     }
3970     if (!cbEncoded)
3971     {
3972         SetLastError(CRYPT_E_ASN1_EOD);
3973         return FALSE;
3974     }
3975     if (cbEncoded > MAX_ENCODED_LEN)
3976     {
3977         SetLastError(CRYPT_E_ASN1_LARGE);
3978         return FALSE;
3979     }
3980
3981     SetLastError(NOERROR);
3982     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3983         *(BYTE **)pvStructInfo = NULL;
3984     if (!HIWORD(lpszStructType))
3985     {
3986         switch (LOWORD(lpszStructType))
3987         {
3988         case (WORD)X509_CERT:
3989             decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3990             break;
3991         case (WORD)X509_CERT_TO_BE_SIGNED:
3992             decodeFunc = CRYPT_AsnDecodeCert;
3993             break;
3994         case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3995             decodeFunc = CRYPT_AsnDecodeCRL;
3996             break;
3997         case (WORD)X509_EXTENSIONS:
3998             decodeFunc = CRYPT_AsnDecodeExtensions;
3999             break;
4000         case (WORD)X509_NAME_VALUE:
4001             decodeFunc = CRYPT_AsnDecodeNameValue;
4002             break;
4003         case (WORD)X509_NAME:
4004             decodeFunc = CRYPT_AsnDecodeName;
4005             break;
4006         case (WORD)X509_PUBLIC_KEY_INFO:
4007             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4008             break;
4009         case (WORD)X509_AUTHORITY_KEY_ID:
4010             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4011             break;
4012         case (WORD)X509_ALTERNATE_NAME:
4013             decodeFunc = CRYPT_AsnDecodeAltName;
4014             break;
4015         case (WORD)X509_BASIC_CONSTRAINTS:
4016             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4017             break;
4018         case (WORD)X509_BASIC_CONSTRAINTS2:
4019             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4020             break;
4021         case (WORD)RSA_CSP_PUBLICKEYBLOB:
4022             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4023             break;
4024         case (WORD)X509_UNICODE_NAME:
4025             decodeFunc = CRYPT_AsnDecodeUnicodeName;
4026             break;
4027         case (WORD)PKCS_ATTRIBUTE:
4028             decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4029             break;
4030         case (WORD)X509_UNICODE_NAME_VALUE:
4031             decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4032             break;
4033         case (WORD)X509_OCTET_STRING:
4034             decodeFunc = CRYPT_AsnDecodeOctets;
4035             break;
4036         case (WORD)X509_BITS:
4037         case (WORD)X509_KEY_USAGE:
4038             decodeFunc = CRYPT_AsnDecodeBits;
4039             break;
4040         case (WORD)X509_INTEGER:
4041             decodeFunc = CRYPT_AsnDecodeInt;
4042             break;
4043         case (WORD)X509_MULTI_BYTE_INTEGER:
4044             decodeFunc = CRYPT_AsnDecodeInteger;
4045             break;
4046         case (WORD)X509_MULTI_BYTE_UINT:
4047             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4048             break;
4049         case (WORD)X509_ENUMERATED:
4050             decodeFunc = CRYPT_AsnDecodeEnumerated;
4051             break;
4052         case (WORD)X509_CHOICE_OF_TIME:
4053             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4054             break;
4055         case (WORD)X509_AUTHORITY_KEY_ID2:
4056             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4057             break;
4058         case (WORD)PKCS_CONTENT_INFO:
4059             decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4060             break;
4061         case (WORD)X509_SEQUENCE_OF_ANY:
4062             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4063             break;
4064         case (WORD)PKCS_UTC_TIME:
4065             decodeFunc = CRYPT_AsnDecodeUtcTime;
4066             break;
4067         case (WORD)X509_CRL_DIST_POINTS:
4068             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4069             break;
4070         case (WORD)X509_ENHANCED_KEY_USAGE:
4071             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4072             break;
4073         case (WORD)PKCS_ATTRIBUTES:
4074             decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4075             break;
4076         case (WORD)X509_ISSUING_DIST_POINT:
4077             decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4078             break;
4079         case (WORD)PKCS7_SIGNER_INFO:
4080             decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4081             break;
4082         default:
4083             FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
4084         }
4085     }
4086     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4087         decodeFunc = CRYPT_AsnDecodeExtensions;
4088     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4089         decodeFunc = CRYPT_AsnDecodeUtcTime;
4090     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4091         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4092     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4093         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4094     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4095         decodeFunc = CRYPT_AsnDecodeEnumerated;
4096     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4097         decodeFunc = CRYPT_AsnDecodeBits;
4098     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4099         decodeFunc = CRYPT_AsnDecodeOctets;
4100     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4101         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4102     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4103         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4104     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4105         decodeFunc = CRYPT_AsnDecodeAltName;
4106     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4107         decodeFunc = CRYPT_AsnDecodeAltName;
4108     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4109         decodeFunc = CRYPT_AsnDecodeAltName;
4110     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4111         decodeFunc = CRYPT_AsnDecodeAltName;
4112     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4113         decodeFunc = CRYPT_AsnDecodeAltName;
4114     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4115         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4116     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4117         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4118     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4119         decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4120     else
4121         TRACE("OID %s not found or unimplemented, looking for DLL\n",
4122          debugstr_a(lpszStructType));
4123     if (!decodeFunc)
4124     {
4125         if (!set)
4126             set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4127         CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4128          (void **)&decodeFunc, &hFunc);
4129     }
4130     if (decodeFunc)
4131         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4132          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4133     else
4134         SetLastError(ERROR_FILE_NOT_FOUND);
4135     if (hFunc)
4136         CryptFreeOIDFunctionAddress(hFunc, 0);
4137     return ret;
4138 }