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