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