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