dinput8: DirectInput8Create rewrite.
[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         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1276
1277         switch (pbEncoded[0])
1278         {
1279         case ASN_OCTETSTRING:
1280             valueType = CERT_RDN_OCTET_STRING;
1281             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1282                 bytesNeeded += dataLen;
1283             break;
1284         case ASN_NUMERICSTRING:
1285             valueType = CERT_RDN_NUMERIC_STRING;
1286             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1287                 bytesNeeded += dataLen;
1288             break;
1289         case ASN_PRINTABLESTRING:
1290             valueType = CERT_RDN_PRINTABLE_STRING;
1291             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1292                 bytesNeeded += dataLen;
1293             break;
1294         case ASN_IA5STRING:
1295             valueType = CERT_RDN_IA5_STRING;
1296             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1297                 bytesNeeded += dataLen;
1298             break;
1299         case ASN_T61STRING:
1300             valueType = CERT_RDN_T61_STRING;
1301             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1302                 bytesNeeded += dataLen;
1303             break;
1304         case ASN_VIDEOTEXSTRING:
1305             valueType = CERT_RDN_VIDEOTEX_STRING;
1306             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1307                 bytesNeeded += dataLen;
1308             break;
1309         case ASN_GRAPHICSTRING:
1310             valueType = CERT_RDN_GRAPHIC_STRING;
1311             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1312                 bytesNeeded += dataLen;
1313             break;
1314         case ASN_VISIBLESTRING:
1315             valueType = CERT_RDN_VISIBLE_STRING;
1316             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1317                 bytesNeeded += dataLen;
1318             break;
1319         case ASN_GENERALSTRING:
1320             valueType = CERT_RDN_GENERAL_STRING;
1321             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1322                 bytesNeeded += dataLen;
1323             break;
1324         case ASN_UNIVERSALSTRING:
1325             FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1326             SetLastError(CRYPT_E_ASN1_BADTAG);
1327             ret = FALSE;
1328             break;
1329         case ASN_BMPSTRING:
1330             valueType = CERT_RDN_BMP_STRING;
1331             bytesNeeded += dataLen;
1332             break;
1333         case ASN_UTF8STRING:
1334             valueType = CERT_RDN_UTF8_STRING;
1335             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1336              (LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1337             break;
1338         default:
1339             SetLastError(CRYPT_E_ASN1_BADTAG);
1340             ret = FALSE;
1341         }
1342         if (ret)
1343         {
1344             if (!value)
1345                 *pcbStructInfo = bytesNeeded;
1346             else if (*pcbStructInfo < bytesNeeded)
1347             {
1348                 *pcbStructInfo = bytesNeeded;
1349                 SetLastError(ERROR_MORE_DATA);
1350                 ret = FALSE;
1351             }
1352             else
1353             {
1354                 *pcbStructInfo = bytesNeeded;
1355                 value->dwValueType = valueType;
1356                 if (dataLen)
1357                 {
1358                     DWORD i;
1359
1360                     assert(value->Value.pbData);
1361                     switch (pbEncoded[0])
1362                     {
1363                     case ASN_OCTETSTRING:
1364                     case ASN_NUMERICSTRING:
1365                     case ASN_PRINTABLESTRING:
1366                     case ASN_IA5STRING:
1367                     case ASN_T61STRING:
1368                     case ASN_VIDEOTEXSTRING:
1369                     case ASN_GRAPHICSTRING:
1370                     case ASN_VISIBLESTRING:
1371                     case ASN_GENERALSTRING:
1372                         value->Value.cbData = dataLen;
1373                         if (dataLen)
1374                         {
1375                             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1376                                 memcpy(value->Value.pbData,
1377                                  pbEncoded + 1 + lenBytes, dataLen);
1378                             else
1379                                 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1380                                  lenBytes;
1381                         }
1382                         break;
1383                     case ASN_BMPSTRING:
1384                     {
1385                         LPWSTR str = (LPWSTR)value->Value.pbData;
1386
1387                         value->Value.cbData = dataLen;
1388                         for (i = 0; i < dataLen / 2; i++)
1389                             str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1390                              pbEncoded[1 + lenBytes + 2 * i + 1];
1391                         break;
1392                     }
1393                     case ASN_UTF8STRING:
1394                     {
1395                         LPWSTR str = (LPWSTR)value->Value.pbData;
1396
1397                         value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1398                          (LPSTR)pbEncoded + 1 + lenBytes, dataLen, 
1399                          str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1400                         break;
1401                     }
1402                     }
1403                 }
1404                 else
1405                 {
1406                     value->Value.cbData = 0;
1407                     value->Value.pbData = NULL;
1408                 }
1409             }
1410         }
1411     }
1412     return ret;
1413 }
1414
1415 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1416  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1417  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1418 {
1419     BOOL ret = TRUE;
1420
1421     __TRY
1422     {
1423         ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1424          lpszStructType, pbEncoded, cbEncoded,
1425          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1426         if (ret && pvStructInfo)
1427         {
1428             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1429              pcbStructInfo, *pcbStructInfo);
1430             if (ret)
1431             {
1432                 CERT_NAME_VALUE *value;
1433
1434                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1435                     pvStructInfo = *(BYTE **)pvStructInfo;
1436                 value = (CERT_NAME_VALUE *)pvStructInfo;
1437                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1438                 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1439                  lpszStructType, pbEncoded, cbEncoded,
1440                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1441                  pcbStructInfo);
1442             }
1443         }
1444     }
1445     __EXCEPT_PAGE_FAULT
1446     {
1447         SetLastError(STATUS_ACCESS_VIOLATION);
1448         ret = FALSE;
1449     }
1450     __ENDTRY
1451     return ret;
1452 }
1453
1454 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1455  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1456  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1457  void *pvStructInfo, DWORD *pcbStructInfo)
1458 {
1459     BOOL ret = TRUE;
1460     DWORD dataLen;
1461     CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1462
1463     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1464     {
1465         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1466         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1467
1468         switch (pbEncoded[0])
1469         {
1470         case ASN_NUMERICSTRING:
1471             valueType = CERT_RDN_NUMERIC_STRING;
1472             bytesNeeded += (dataLen + 1) * 2;
1473             break;
1474         case ASN_PRINTABLESTRING:
1475             valueType = CERT_RDN_PRINTABLE_STRING;
1476             bytesNeeded += (dataLen + 1) * 2;
1477             break;
1478         case ASN_IA5STRING:
1479             valueType = CERT_RDN_IA5_STRING;
1480             bytesNeeded += (dataLen + 1) * 2;
1481             break;
1482         case ASN_T61STRING:
1483             valueType = CERT_RDN_T61_STRING;
1484             bytesNeeded += (dataLen + 1) * 2;
1485             break;
1486         case ASN_VIDEOTEXSTRING:
1487             valueType = CERT_RDN_VIDEOTEX_STRING;
1488             bytesNeeded += (dataLen + 1) * 2;
1489             break;
1490         case ASN_GRAPHICSTRING:
1491             valueType = CERT_RDN_GRAPHIC_STRING;
1492             bytesNeeded += (dataLen + 1) * 2;
1493             break;
1494         case ASN_VISIBLESTRING:
1495             valueType = CERT_RDN_VISIBLE_STRING;
1496             bytesNeeded += (dataLen + 1) * 2;
1497             break;
1498         case ASN_GENERALSTRING:
1499             valueType = CERT_RDN_GENERAL_STRING;
1500             bytesNeeded += (dataLen + 1) * 2;
1501             break;
1502         case ASN_UNIVERSALSTRING:
1503             valueType = CERT_RDN_UNIVERSAL_STRING;
1504             bytesNeeded += dataLen / 2 + 2;
1505             break;
1506         case ASN_BMPSTRING:
1507             valueType = CERT_RDN_BMP_STRING;
1508             bytesNeeded += dataLen + 2;
1509             break;
1510         case ASN_UTF8STRING:
1511             valueType = CERT_RDN_UTF8_STRING;
1512             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1513              (LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2 + 2;
1514             break;
1515         default:
1516             SetLastError(CRYPT_E_ASN1_BADTAG);
1517             ret = FALSE;
1518         }
1519         if (ret)
1520         {
1521             if (!value)
1522                 *pcbStructInfo = bytesNeeded;
1523             else if (*pcbStructInfo < bytesNeeded)
1524             {
1525                 *pcbStructInfo = bytesNeeded;
1526                 SetLastError(ERROR_MORE_DATA);
1527                 ret = FALSE;
1528             }
1529             else
1530             {
1531                 *pcbStructInfo = bytesNeeded;
1532                 value->dwValueType = valueType;
1533                 if (dataLen)
1534                 {
1535                     DWORD i;
1536                     LPWSTR str = (LPWSTR)value->Value.pbData;
1537
1538                     assert(value->Value.pbData);
1539                     switch (pbEncoded[0])
1540                     {
1541                     case ASN_NUMERICSTRING:
1542                     case ASN_PRINTABLESTRING:
1543                     case ASN_IA5STRING:
1544                     case ASN_T61STRING:
1545                     case ASN_VIDEOTEXSTRING:
1546                     case ASN_GRAPHICSTRING:
1547                     case ASN_VISIBLESTRING:
1548                     case ASN_GENERALSTRING:
1549                         value->Value.cbData = dataLen * 2 + 2;
1550                         for (i = 0; i < dataLen; i++)
1551                             str[i] = pbEncoded[1 + lenBytes + i];
1552                         str[i] = 0;
1553                         break;
1554                     case ASN_UNIVERSALSTRING:
1555                         value->Value.cbData = dataLen / 2 + 2;
1556                         for (i = 0; i < dataLen / 4; i++)
1557                             str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1558                              | pbEncoded[1 + lenBytes + 2 * i + 3];
1559                         str[i] = 0;
1560                         break;
1561                     case ASN_BMPSTRING:
1562                         value->Value.cbData = dataLen + 2;
1563                         for (i = 0; i < dataLen / 2; i++)
1564                             str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1565                              pbEncoded[1 + lenBytes + 2 * i + 1];
1566                         str[i] = 0;
1567                         break;
1568                     case ASN_UTF8STRING:
1569                         value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1570                          (LPSTR)pbEncoded + 1 + lenBytes, dataLen, 
1571                          str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1572                         str[value->Value.cbData / 2] = 0;
1573                         value->Value.cbData += 2;
1574                         break;
1575                     }
1576                 }
1577                 else
1578                 {
1579                     value->Value.cbData = 0;
1580                     value->Value.pbData = NULL;
1581                 }
1582             }
1583         }
1584     }
1585     return ret;
1586 }
1587
1588 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1589  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1590  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1591 {
1592     BOOL ret = TRUE;
1593
1594     __TRY
1595     {
1596         ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1597          lpszStructType, pbEncoded, cbEncoded,
1598          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1599         if (ret && pvStructInfo)
1600         {
1601             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1602              pcbStructInfo, *pcbStructInfo);
1603             if (ret)
1604             {
1605                 CERT_NAME_VALUE *value;
1606
1607                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1608                     pvStructInfo = *(BYTE **)pvStructInfo;
1609                 value = (CERT_NAME_VALUE *)pvStructInfo;
1610                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1611                 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1612                  dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1613                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1614                  pcbStructInfo);
1615             }
1616         }
1617     }
1618     __EXCEPT_PAGE_FAULT
1619     {
1620         SetLastError(STATUS_ACCESS_VIOLATION);
1621         ret = FALSE;
1622     }
1623     __ENDTRY
1624     return ret;
1625 }
1626
1627 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1628  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1629  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1630 {
1631     BOOL ret;
1632     struct AsnDecodeSequenceItem items[] = {
1633      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1634        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1635        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1636      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1637        CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1638        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1639     };
1640     CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1641
1642     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1643      pvStructInfo, *pcbStructInfo);
1644
1645     if (attr)
1646         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1647     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1648      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1649      attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1650     if (attr)
1651     {
1652         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1653          debugstr_a(attr->pszObjId));
1654         TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1655     }
1656     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1657     return ret;
1658 }
1659
1660 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1661  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1662  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1663 {
1664     BOOL ret = TRUE;
1665     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1666      CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1667      offsetof(CERT_RDN_ATTR, pszObjId) };
1668     PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1669
1670     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1671      pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1672     return ret;
1673 }
1674
1675 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1676  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1677  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1678 {
1679     BOOL ret = TRUE;
1680
1681     __TRY
1682     {
1683         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1684          CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1685          offsetof(CERT_RDN, rgRDNAttr) };
1686
1687         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1688          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1689     }
1690     __EXCEPT_PAGE_FAULT
1691     {
1692         SetLastError(STATUS_ACCESS_VIOLATION);
1693         ret = FALSE;
1694     }
1695     __ENDTRY
1696     return ret;
1697 }
1698
1699 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1700  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1701  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1702 {
1703     BOOL ret = TRUE;
1704     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1705
1706     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1707      pDecodePara, pvStructInfo, *pcbStructInfo);
1708
1709     if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1710         bytesNeeded += cbEncoded;
1711     if (!pvStructInfo)
1712         *pcbStructInfo = bytesNeeded;
1713     else if (*pcbStructInfo < bytesNeeded)
1714     {
1715         SetLastError(ERROR_MORE_DATA);
1716         *pcbStructInfo = bytesNeeded;
1717         ret = FALSE;
1718     }
1719     else
1720     {
1721         PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1722
1723         *pcbStructInfo = bytesNeeded;
1724         blob->cbData = cbEncoded;
1725         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1726             blob->pbData = (LPBYTE)pbEncoded;
1727         else
1728         {
1729             assert(blob->pbData);
1730             memcpy(blob->pbData, pbEncoded, blob->cbData);
1731         }
1732     }
1733     return ret;
1734 }
1735
1736 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1737  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1738  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1739 {
1740     CRYPT_ALGORITHM_IDENTIFIER *algo =
1741      (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1742     BOOL ret = TRUE;
1743     struct AsnDecodeSequenceItem items[] = {
1744      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1745        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, 
1746        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1747      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1748        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
1749        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1750     };
1751
1752     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1753      pDecodePara, pvStructInfo, *pcbStructInfo);
1754
1755     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1756      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1757      pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1758     if (ret && pvStructInfo)
1759     {
1760         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1761          debugstr_a(algo->pszObjId));
1762     }
1763     return ret;
1764 }
1765
1766 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1767  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1768  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1769 {
1770     BOOL ret = TRUE;
1771     struct AsnDecodeSequenceItem items[] = {
1772      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1773        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1774        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1775        Algorithm.pszObjId) },
1776      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1777        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1778        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1779     };
1780     PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1781
1782     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1783      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1784      pDecodePara, pvStructInfo, pcbStructInfo, info ?
1785      info->Algorithm.Parameters.pbData : NULL);
1786     return ret;
1787 }
1788
1789 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1790  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1791  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1792 {
1793     BOOL ret = TRUE;
1794
1795     __TRY
1796     {
1797         DWORD bytesNeeded;
1798
1799         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1800          lpszStructType, pbEncoded, cbEncoded,
1801          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1802         {
1803             if (!pvStructInfo)
1804                 *pcbStructInfo = bytesNeeded;
1805             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1806              pvStructInfo, pcbStructInfo, bytesNeeded)))
1807             {
1808                 PCERT_PUBLIC_KEY_INFO info;
1809
1810                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1811                     pvStructInfo = *(BYTE **)pvStructInfo;
1812                 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1813                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1814                  sizeof(CERT_PUBLIC_KEY_INFO);
1815                 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1816                  lpszStructType, pbEncoded, cbEncoded,
1817                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1818                  &bytesNeeded);
1819             }
1820         }
1821     }
1822     __EXCEPT_PAGE_FAULT
1823     {
1824         SetLastError(STATUS_ACCESS_VIOLATION);
1825         ret = FALSE;
1826     }
1827     __ENDTRY
1828     return ret;
1829 }
1830
1831 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1832  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1833  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1834 {
1835     BOOL ret;
1836
1837     if (cbEncoded < 3)
1838     {
1839         SetLastError(CRYPT_E_ASN1_CORRUPT);
1840         return FALSE;
1841     }
1842     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1843     {
1844         SetLastError(CRYPT_E_ASN1_CORRUPT);
1845         return FALSE;
1846     }
1847     if (pbEncoded[1] > 1)
1848     {
1849         SetLastError(CRYPT_E_ASN1_CORRUPT);
1850         return FALSE;
1851     }
1852     if (!pvStructInfo)
1853     {
1854         *pcbStructInfo = sizeof(BOOL);
1855         ret = TRUE;
1856     }
1857     else if (*pcbStructInfo < sizeof(BOOL))
1858     {
1859         *pcbStructInfo = sizeof(BOOL);
1860         SetLastError(ERROR_MORE_DATA);
1861         ret = FALSE;
1862     }
1863     else
1864     {
1865         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1866         ret = TRUE;
1867     }
1868     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1869     return ret;
1870 }
1871
1872 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1873  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1874  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1875 {
1876     PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1877     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1878     BOOL ret;
1879
1880     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1881      pDecodePara, pvStructInfo, *pcbStructInfo);
1882
1883     if (cbEncoded < 2)
1884     {
1885         SetLastError(CRYPT_E_ASN1_CORRUPT);
1886         return FALSE;
1887     }
1888     if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1889     {
1890         SetLastError(CRYPT_E_ASN1_BADTAG);
1891         return FALSE;
1892     }
1893     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1894     if (1 + lenBytes > cbEncoded)
1895     {
1896         SetLastError(CRYPT_E_ASN1_CORRUPT);
1897         return FALSE;
1898     }
1899     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1900     {
1901         switch (pbEncoded[0] & ASN_TYPE_MASK)
1902         {
1903         case 1: /* rfc822Name */
1904         case 2: /* dNSName */
1905         case 6: /* uniformResourceIdentifier */
1906             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1907             break;
1908         case 7: /* iPAddress */
1909             bytesNeeded += dataLen;
1910             break;
1911         case 8: /* registeredID */
1912             /* FIXME: decode as OID */
1913         case 0: /* otherName */
1914         case 4: /* directoryName */
1915             FIXME("stub\n");
1916             SetLastError(CRYPT_E_ASN1_BADTAG);
1917             ret = FALSE;
1918             break;
1919         case 3: /* x400Address, unimplemented */
1920         case 5: /* ediPartyName, unimplemented */
1921             SetLastError(CRYPT_E_ASN1_BADTAG);
1922             ret = FALSE;
1923             break;
1924         default:
1925             SetLastError(CRYPT_E_ASN1_CORRUPT);
1926             ret = FALSE;
1927         }
1928         if (ret)
1929         {
1930             if (!entry)
1931                 *pcbStructInfo = bytesNeeded;
1932             else if (*pcbStructInfo < bytesNeeded)
1933             {
1934                 *pcbStructInfo = bytesNeeded;
1935                 SetLastError(ERROR_MORE_DATA);
1936                 ret = FALSE;
1937             }
1938             else
1939             {
1940                 *pcbStructInfo = bytesNeeded;
1941                 /* MS used values one greater than the asn1 ones.. sigh */
1942                 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1943                 switch (pbEncoded[0] & ASN_TYPE_MASK)
1944                 {
1945                 case 1: /* rfc822Name */
1946                 case 2: /* dNSName */
1947                 case 6: /* uniformResourceIdentifier */
1948                 {
1949                     DWORD i;
1950
1951                     for (i = 0; i < dataLen; i++)
1952                         entry->u.pwszURL[i] =
1953                          (WCHAR)pbEncoded[1 + lenBytes + i];
1954                     entry->u.pwszURL[i] = 0;
1955                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1956                      debugstr_w(entry->u.pwszURL));
1957                     break;
1958                 }
1959                 case 7: /* iPAddress */
1960                     /* The next data pointer is in the pwszURL spot, that is,
1961                      * the first 4 bytes.  Need to move it to the next spot.
1962                      */
1963                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1964                     entry->u.IPAddress.cbData = dataLen;
1965                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1966                      dataLen);
1967                     break;
1968                 }
1969             }
1970         }
1971     }
1972     return ret;
1973 }
1974
1975 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1976  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1977  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1978 {
1979     BOOL ret = TRUE;
1980     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1981      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1982      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1983     PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1984
1985     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1986      pDecodePara, pvStructInfo, *pcbStructInfo);
1987
1988     if (info)
1989         TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1990     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1991      pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1992     return ret;
1993 }
1994
1995 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1996  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1997  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1998 {
1999     BOOL ret = TRUE;
2000
2001     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2002      pDecodePara, pvStructInfo, *pcbStructInfo);
2003
2004     __TRY
2005     {
2006         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2007          CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2008          offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2009
2010         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2011          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2012     }
2013     __EXCEPT_PAGE_FAULT
2014     {
2015         SetLastError(STATUS_ACCESS_VIOLATION);
2016         ret = FALSE;
2017     }
2018     __ENDTRY
2019     return ret;
2020 }
2021
2022 struct PATH_LEN_CONSTRAINT
2023 {
2024     BOOL  fPathLenConstraint;
2025     DWORD dwPathLenConstraint;
2026 };
2027
2028 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2029  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2030  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2031 {
2032     BOOL ret = TRUE;
2033
2034     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2035      pvStructInfo, *pcbStructInfo);
2036
2037     if (cbEncoded)
2038     {
2039         if (pbEncoded[0] == ASN_INTEGER)
2040         {
2041             DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2042
2043             if (!pvStructInfo)
2044                 *pcbStructInfo = bytesNeeded;
2045             else if (*pcbStructInfo < bytesNeeded)
2046             {
2047                 SetLastError(ERROR_MORE_DATA);
2048                 *pcbStructInfo = bytesNeeded;
2049                 ret = FALSE;
2050             }
2051             else
2052             {
2053                 struct PATH_LEN_CONSTRAINT *constraint =
2054                  (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2055                 DWORD size = sizeof(constraint->dwPathLenConstraint);
2056
2057                 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2058                  pbEncoded, cbEncoded, 0, NULL,
2059                  &constraint->dwPathLenConstraint, &size);
2060                 if (ret)
2061                     constraint->fPathLenConstraint = TRUE;
2062                 TRACE("got an int, dwPathLenConstraint is %ld\n",
2063                  constraint->dwPathLenConstraint);
2064             }
2065         }
2066         else
2067         {
2068             SetLastError(CRYPT_E_ASN1_CORRUPT);
2069             ret = FALSE;
2070         }
2071     }
2072     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2073     return ret;
2074 }
2075
2076 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2077  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2078  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2079 {
2080     BOOL ret;
2081     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2082      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2083      offsetof(CERT_NAME_BLOB, pbData) };
2084     struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2085
2086     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2087      pDecodePara, pvStructInfo, *pcbStructInfo);
2088
2089     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2090      pDecodePara, pvStructInfo, pcbStructInfo,
2091      entries ? entries->rgItems : NULL);
2092     TRACE("Returning %d (%08lx)\n", ret, GetLastError());
2093     return ret;
2094 }
2095
2096 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2097  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2098  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2099 {
2100     BOOL ret;
2101
2102     __TRY
2103     {
2104         struct AsnDecodeSequenceItem items[] = {
2105          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2106            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
2107            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2108          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2109            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2110            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2111          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2112            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2113            sizeof(struct GenericArray), TRUE, TRUE,
2114            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2115         };
2116
2117         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2118          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2119          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2120     }
2121     __EXCEPT_PAGE_FAULT
2122     {
2123         SetLastError(STATUS_ACCESS_VIOLATION);
2124         ret = FALSE;
2125     }
2126     __ENDTRY
2127     return ret;
2128 }
2129
2130 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2131  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2132  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2133 {
2134     BOOL ret;
2135
2136     __TRY
2137     {
2138         struct AsnDecodeSequenceItem items[] = {
2139          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2140            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2141          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2142            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2143            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2144         };
2145
2146         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2147          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2148          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2149     }
2150     __EXCEPT_PAGE_FAULT
2151     {
2152         SetLastError(STATUS_ACCESS_VIOLATION);
2153         ret = FALSE;
2154     }
2155     __ENDTRY
2156     return ret;
2157 }
2158
2159 #define RSA1_MAGIC 0x31415352
2160
2161 struct DECODED_RSA_PUB_KEY
2162 {
2163     DWORD              pubexp;
2164     CRYPT_INTEGER_BLOB modulus;
2165 };
2166
2167 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2168  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2169  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2170 {
2171     BOOL ret;
2172
2173     __TRY
2174     {
2175         struct AsnDecodeSequenceItem items[] = {
2176          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2177            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2178            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2179            0 },
2180          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2181            CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2182         };
2183         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2184         DWORD size = 0;
2185
2186         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2187          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2188          CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2189         if (ret)
2190         {
2191             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2192              decodedKey->modulus.cbData;
2193
2194             if (!pvStructInfo)
2195             {
2196                 *pcbStructInfo = bytesNeeded;
2197                 ret = TRUE;
2198             }
2199             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2200              pvStructInfo, pcbStructInfo, bytesNeeded)))
2201             {
2202                 BLOBHEADER *hdr;
2203                 RSAPUBKEY *rsaPubKey;
2204
2205                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2206                     pvStructInfo = *(BYTE **)pvStructInfo;
2207                 hdr = (BLOBHEADER *)pvStructInfo;
2208                 hdr->bType = PUBLICKEYBLOB;
2209                 hdr->bVersion = CUR_BLOB_VERSION;
2210                 hdr->reserved = 0;
2211                 hdr->aiKeyAlg = CALG_RSA_KEYX;
2212                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2213                  sizeof(BLOBHEADER));
2214                 rsaPubKey->magic = RSA1_MAGIC;
2215                 rsaPubKey->pubexp = decodedKey->pubexp;
2216                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2217                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2218                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2219                  decodedKey->modulus.cbData);
2220             }
2221             LocalFree(decodedKey);
2222         }
2223     }
2224     __EXCEPT_PAGE_FAULT
2225     {
2226         SetLastError(STATUS_ACCESS_VIOLATION);
2227         ret = FALSE;
2228     }
2229     __ENDTRY
2230     return ret;
2231 }
2232
2233 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2234  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2235  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2236 {
2237     BOOL ret;
2238     DWORD bytesNeeded, dataLen;
2239
2240     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2241      pDecodePara, pvStructInfo, *pcbStructInfo);
2242
2243     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2244     {
2245         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2246             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2247         else
2248             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2249         if (!pvStructInfo)
2250             *pcbStructInfo = bytesNeeded;
2251         else if (*pcbStructInfo < bytesNeeded)
2252         {
2253             SetLastError(ERROR_MORE_DATA);
2254             *pcbStructInfo = bytesNeeded;
2255             ret = FALSE;
2256         }
2257         else
2258         {
2259             CRYPT_DATA_BLOB *blob;
2260             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2261
2262             blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2263             blob->cbData = dataLen;
2264             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2265                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2266             else
2267             {
2268                 assert(blob->pbData);
2269                 if (blob->cbData)
2270                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2271                      blob->cbData);
2272             }
2273         }
2274     }
2275     return ret;
2276 }
2277
2278 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2279  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2280  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2281 {
2282     BOOL ret;
2283
2284     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2285      pDecodePara, pvStructInfo, *pcbStructInfo);
2286
2287     __TRY
2288     {
2289         DWORD bytesNeeded;
2290
2291         if (!cbEncoded)
2292         {
2293             SetLastError(CRYPT_E_ASN1_CORRUPT);
2294             ret = FALSE;
2295         }
2296         else if (pbEncoded[0] != ASN_OCTETSTRING)
2297         {
2298             SetLastError(CRYPT_E_ASN1_BADTAG);
2299             ret = FALSE;
2300         }
2301         else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2302          lpszStructType, pbEncoded, cbEncoded,
2303          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2304         {
2305             if (!pvStructInfo)
2306                 *pcbStructInfo = bytesNeeded;
2307             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2308              pvStructInfo, pcbStructInfo, bytesNeeded)))
2309             {
2310                 CRYPT_DATA_BLOB *blob;
2311
2312                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2313                     pvStructInfo = *(BYTE **)pvStructInfo;
2314                 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2315                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2316                 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2317                  lpszStructType, pbEncoded, cbEncoded,
2318                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2319                  &bytesNeeded);
2320             }
2321         }
2322     }
2323     __EXCEPT_PAGE_FAULT
2324     {
2325         SetLastError(STATUS_ACCESS_VIOLATION);
2326         ret = FALSE;
2327     }
2328     __ENDTRY
2329     return ret;
2330 }
2331
2332 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2333  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2334  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2335 {
2336     BOOL ret;
2337
2338     TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2339      pDecodePara, pvStructInfo, *pcbStructInfo);
2340
2341     if (pbEncoded[0] == ASN_BITSTRING)
2342     {
2343         DWORD bytesNeeded, dataLen;
2344
2345         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2346         {
2347             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2348                 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2349             else
2350                 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2351             if (!pvStructInfo)
2352                 *pcbStructInfo = bytesNeeded;
2353             else if (*pcbStructInfo < bytesNeeded)
2354             {
2355                 *pcbStructInfo = bytesNeeded;
2356                 SetLastError(ERROR_MORE_DATA);
2357                 ret = FALSE;
2358             }
2359             else
2360             {
2361                 CRYPT_BIT_BLOB *blob;
2362
2363                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2364                 blob->cbData = dataLen - 1;
2365                 blob->cUnusedBits = *(pbEncoded + 1 +
2366                  GET_LEN_BYTES(pbEncoded[1]));
2367                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2368                 {
2369                     blob->pbData = (BYTE *)pbEncoded + 2 +
2370                      GET_LEN_BYTES(pbEncoded[1]);
2371                 }
2372                 else
2373                 {
2374                     assert(blob->pbData);
2375                     if (blob->cbData)
2376                     {
2377                         BYTE mask = 0xff << blob->cUnusedBits;
2378
2379                         memcpy(blob->pbData, pbEncoded + 2 +
2380                          GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2381                         blob->pbData[blob->cbData - 1] &= mask;
2382                     }
2383                 }
2384             }
2385         }
2386     }
2387     else
2388     {
2389         SetLastError(CRYPT_E_ASN1_BADTAG);
2390         ret = FALSE;
2391     }
2392     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2393     return ret;
2394 }
2395
2396 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2397  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2398  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2399 {
2400     BOOL ret;
2401
2402     TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2403      pDecodePara, pvStructInfo, pcbStructInfo);
2404
2405     __TRY
2406     {
2407         DWORD bytesNeeded;
2408
2409         if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2410          lpszStructType, pbEncoded, cbEncoded,
2411          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2412         {
2413             if (!pvStructInfo)
2414                 *pcbStructInfo = bytesNeeded;
2415             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2416              pvStructInfo, pcbStructInfo, bytesNeeded)))
2417             {
2418                 CRYPT_BIT_BLOB *blob;
2419
2420                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2421                     pvStructInfo = *(BYTE **)pvStructInfo;
2422                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2423                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2424                 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2425                  lpszStructType, pbEncoded, cbEncoded,
2426                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2427                  &bytesNeeded);
2428             }
2429         }
2430     }
2431     __EXCEPT_PAGE_FAULT
2432     {
2433         SetLastError(STATUS_ACCESS_VIOLATION);
2434         ret = FALSE;
2435     }
2436     __ENDTRY
2437     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2438     return ret;
2439 }
2440
2441 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2442  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2443  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2444 {
2445     BOOL ret;
2446
2447     if (!pvStructInfo)
2448     {
2449         *pcbStructInfo = sizeof(int);
2450         return TRUE;
2451     }
2452     __TRY
2453     {
2454         BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2455         CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2456         DWORD size = sizeof(buf);
2457
2458         blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2459         ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2460          X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2461         if (ret)
2462         {
2463             if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2464              pvStructInfo, pcbStructInfo, sizeof(int))))
2465             {
2466                 int val, i;
2467
2468                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2469                     pvStructInfo = *(BYTE **)pvStructInfo;
2470                 if (blob->pbData[blob->cbData - 1] & 0x80)
2471                 {
2472                     /* initialize to a negative value to sign-extend */
2473                     val = -1;
2474                 }
2475                 else
2476                     val = 0;
2477                 for (i = 0; i < blob->cbData; i++)
2478                 {
2479                     val <<= 8;
2480                     val |= blob->pbData[blob->cbData - i - 1];
2481                 }
2482                 memcpy(pvStructInfo, &val, sizeof(int));
2483             }
2484         }
2485         else if (GetLastError() == ERROR_MORE_DATA)
2486             SetLastError(CRYPT_E_ASN1_LARGE);
2487     }
2488     __EXCEPT_PAGE_FAULT
2489     {
2490         SetLastError(STATUS_ACCESS_VIOLATION);
2491         ret = FALSE;
2492     }
2493     __ENDTRY
2494     return ret;
2495 }
2496
2497 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2498  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2499  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2500 {
2501     BOOL ret;
2502
2503     if (pbEncoded[0] == ASN_INTEGER)
2504     {
2505         DWORD bytesNeeded, dataLen;
2506
2507         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2508         {
2509             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2510
2511             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2512             if (!pvStructInfo)
2513                 *pcbStructInfo = bytesNeeded;
2514             else if (*pcbStructInfo < bytesNeeded)
2515             {
2516                 *pcbStructInfo = bytesNeeded;
2517                 SetLastError(ERROR_MORE_DATA);
2518                 ret = FALSE;
2519             }
2520             else
2521             {
2522                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2523
2524                 blob->cbData = dataLen;
2525                 assert(blob->pbData);
2526                 if (blob->cbData)
2527                 {
2528                     DWORD i;
2529
2530                     for (i = 0; i < blob->cbData; i++)
2531                     {
2532                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2533                          dataLen - i - 1);
2534                     }
2535                 }
2536             }
2537         }
2538     }
2539     else
2540     {
2541         SetLastError(CRYPT_E_ASN1_BADTAG);
2542         ret = FALSE;
2543     }
2544     return ret;
2545 }
2546
2547 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2548  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2549  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2550 {
2551     BOOL ret;
2552
2553     __TRY
2554     {
2555         DWORD bytesNeeded;
2556
2557         if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2558          lpszStructType, pbEncoded, cbEncoded,
2559          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2560         {
2561             if (!pvStructInfo)
2562                 *pcbStructInfo = bytesNeeded;
2563             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2564              pvStructInfo, pcbStructInfo, bytesNeeded)))
2565             {
2566                 CRYPT_INTEGER_BLOB *blob;
2567
2568                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2569                     pvStructInfo = *(BYTE **)pvStructInfo;
2570                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2571                 blob->pbData = (BYTE *)pvStructInfo +
2572                  sizeof(CRYPT_INTEGER_BLOB);
2573                 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2574                  lpszStructType, pbEncoded, cbEncoded,
2575                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2576                  &bytesNeeded);
2577             }
2578         }
2579     }
2580     __EXCEPT_PAGE_FAULT
2581     {
2582         SetLastError(STATUS_ACCESS_VIOLATION);
2583         ret = FALSE;
2584     }
2585     __ENDTRY
2586     return ret;
2587 }
2588
2589 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2590  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2591  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2592  void *pvStructInfo, DWORD *pcbStructInfo)
2593 {
2594     BOOL ret;
2595
2596     if (pbEncoded[0] == ASN_INTEGER)
2597     {
2598         DWORD bytesNeeded, dataLen;
2599
2600         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2601         {
2602             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2603
2604             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2605             if (!pvStructInfo)
2606                 *pcbStructInfo = bytesNeeded;
2607             else if (*pcbStructInfo < bytesNeeded)
2608             {
2609                 *pcbStructInfo = bytesNeeded;
2610                 SetLastError(ERROR_MORE_DATA);
2611                 ret = FALSE;
2612             }
2613             else
2614             {
2615                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2616
2617                 blob->cbData = dataLen;
2618                 assert(blob->pbData);
2619                 /* remove leading zero byte if it exists */
2620                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2621                 {
2622                     blob->cbData--;
2623                     blob->pbData++;
2624                 }
2625                 if (blob->cbData)
2626                 {
2627                     DWORD i;
2628
2629                     for (i = 0; i < blob->cbData; i++)
2630                     {
2631                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2632                          dataLen - i - 1);
2633                     }
2634                 }
2635             }
2636         }
2637     }
2638     else
2639     {
2640         SetLastError(CRYPT_E_ASN1_BADTAG);
2641         ret = FALSE;
2642     }
2643     return ret;
2644 }
2645
2646 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2647  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2648  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2649 {
2650     BOOL ret;
2651
2652     __TRY
2653     {
2654         DWORD bytesNeeded;
2655
2656         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2657          lpszStructType, pbEncoded, cbEncoded,
2658          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2659         {
2660             if (!pvStructInfo)
2661                 *pcbStructInfo = bytesNeeded;
2662             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2663              pvStructInfo, pcbStructInfo, bytesNeeded)))
2664             {
2665                 CRYPT_INTEGER_BLOB *blob;
2666
2667                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2668                     pvStructInfo = *(BYTE **)pvStructInfo;
2669                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2670                 blob->pbData = (BYTE *)pvStructInfo +
2671                  sizeof(CRYPT_INTEGER_BLOB);
2672                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2673                  lpszStructType, pbEncoded, cbEncoded,
2674                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2675                  &bytesNeeded);
2676             }
2677         }
2678     }
2679     __EXCEPT_PAGE_FAULT
2680     {
2681         SetLastError(STATUS_ACCESS_VIOLATION);
2682         ret = FALSE;
2683     }
2684     __ENDTRY
2685     return ret;
2686 }
2687
2688 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2689  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2690  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2691 {
2692     BOOL ret;
2693
2694     if (!pvStructInfo)
2695     {
2696         *pcbStructInfo = sizeof(int);
2697         return TRUE;
2698     }
2699     __TRY
2700     {
2701         if (pbEncoded[0] == ASN_ENUMERATED)
2702         {
2703             unsigned int val = 0, i;
2704
2705             if (cbEncoded <= 1)
2706             {
2707                 SetLastError(CRYPT_E_ASN1_EOD);
2708                 ret = FALSE;
2709             }
2710             else if (pbEncoded[1] == 0)
2711             {
2712                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2713                 ret = FALSE;
2714             }
2715             else
2716             {
2717                 /* A little strange looking, but we have to accept a sign byte:
2718                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
2719                  * assuming a small length is okay here, it has to be in short
2720                  * form.
2721                  */
2722                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2723                 {
2724                     SetLastError(CRYPT_E_ASN1_LARGE);
2725                     return FALSE;
2726                 }
2727                 for (i = 0; i < pbEncoded[1]; i++)
2728                 {
2729                     val <<= 8;
2730                     val |= pbEncoded[2 + i];
2731                 }
2732                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2733                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2734                 {
2735                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2736                         pvStructInfo = *(BYTE **)pvStructInfo;
2737                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
2738                 }
2739             }
2740         }
2741         else
2742         {
2743             SetLastError(CRYPT_E_ASN1_BADTAG);
2744             ret = FALSE;
2745         }
2746     }
2747     __EXCEPT_PAGE_FAULT
2748     {
2749         SetLastError(STATUS_ACCESS_VIOLATION);
2750         ret = FALSE;
2751     }
2752     __ENDTRY
2753     return ret;
2754 }
2755
2756 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2757  * if it fails.
2758  */
2759 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2760  do { \
2761     BYTE i; \
2762  \
2763     (word) = 0; \
2764     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2765     { \
2766         if (!isdigit(*(pbEncoded))) \
2767         { \
2768             SetLastError(CRYPT_E_ASN1_CORRUPT); \
2769             ret = FALSE; \
2770         } \
2771         else \
2772         { \
2773             (word) *= 10; \
2774             (word) += *(pbEncoded)++ - '0'; \
2775         } \
2776     } \
2777  } while (0)
2778
2779 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2780  SYSTEMTIME *sysTime)
2781 {
2782     BOOL ret;
2783
2784     __TRY
2785     {
2786         ret = TRUE;
2787         if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2788         {
2789             WORD hours, minutes = 0;
2790             BYTE sign = *pbEncoded++;
2791
2792             len--;
2793             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2794             if (ret && hours >= 24)
2795             {
2796                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2797                 ret = FALSE;
2798             }
2799             else if (len >= 2)
2800             {
2801                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2802                 if (ret && minutes >= 60)
2803                 {
2804                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2805                     ret = FALSE;
2806                 }
2807             }
2808             if (ret)
2809             {
2810                 if (sign == '+')
2811                 {
2812                     sysTime->wHour += hours;
2813                     sysTime->wMinute += minutes;
2814                 }
2815                 else
2816                 {
2817                     if (hours > sysTime->wHour)
2818                     {
2819                         sysTime->wDay--;
2820                         sysTime->wHour = 24 - (hours - sysTime->wHour);
2821                     }
2822                     else
2823                         sysTime->wHour -= hours;
2824                     if (minutes > sysTime->wMinute)
2825                     {
2826                         sysTime->wHour--;
2827                         sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2828                     }
2829                     else
2830                         sysTime->wMinute -= minutes;
2831                 }
2832             }
2833         }
2834     }
2835     __EXCEPT_PAGE_FAULT
2836     {
2837         SetLastError(STATUS_ACCESS_VIOLATION);
2838         ret = FALSE;
2839     }
2840     __ENDTRY
2841     return ret;
2842 }
2843
2844 #define MIN_ENCODED_TIME_LENGTH 10
2845
2846 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2847  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2848  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2849 {
2850     BOOL ret;
2851
2852     if (!pvStructInfo)
2853     {
2854         *pcbStructInfo = sizeof(FILETIME);
2855         return TRUE;
2856     }
2857     __TRY
2858     {
2859         ret = TRUE;
2860         if (pbEncoded[0] == ASN_UTCTIME)
2861         {
2862             if (cbEncoded <= 1)
2863             {
2864                 SetLastError(CRYPT_E_ASN1_EOD);
2865                 ret = FALSE;
2866             }
2867             else if (pbEncoded[1] > 0x7f)
2868             {
2869                 /* long-form date strings really can't be valid */
2870                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2871                 ret = FALSE;
2872             }
2873             else
2874             {
2875                 SYSTEMTIME sysTime = { 0 };
2876                 BYTE len = pbEncoded[1];
2877
2878                 if (len < MIN_ENCODED_TIME_LENGTH)
2879                 {
2880                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2881                     ret = FALSE;
2882                 }
2883                 else
2884                 {
2885                     pbEncoded += 2;
2886                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2887                     if (sysTime.wYear >= 50)
2888                         sysTime.wYear += 1900;
2889                     else
2890                         sysTime.wYear += 2000;
2891                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2892                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2893                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2894                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2895                     if (ret && len > 0)
2896                     {
2897                         if (len >= 2 && isdigit(*pbEncoded) &&
2898                          isdigit(*(pbEncoded + 1)))
2899                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2900                              sysTime.wSecond);
2901                         else if (isdigit(*pbEncoded))
2902                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2903                              sysTime.wSecond);
2904                         if (ret)
2905                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2906                              &sysTime);
2907                     }
2908                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2909                      pDecodePara, pvStructInfo, pcbStructInfo,
2910                      sizeof(FILETIME))))
2911                     {
2912                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2913                             pvStructInfo = *(BYTE **)pvStructInfo;
2914                         ret = SystemTimeToFileTime(&sysTime,
2915                          (FILETIME *)pvStructInfo);
2916                     }
2917                 }
2918             }
2919         }
2920         else
2921         {
2922             SetLastError(CRYPT_E_ASN1_BADTAG);
2923             ret = FALSE;
2924         }
2925     }
2926     __EXCEPT_PAGE_FAULT
2927     {
2928         SetLastError(STATUS_ACCESS_VIOLATION);
2929         ret = FALSE;
2930     }
2931     __ENDTRY
2932     return ret;
2933 }
2934
2935 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2936  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2937  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2938 {
2939     BOOL ret;
2940
2941     if (!pvStructInfo)
2942     {
2943         *pcbStructInfo = sizeof(FILETIME);
2944         return TRUE;
2945     }
2946     __TRY
2947     {
2948         ret = TRUE;
2949         if (pbEncoded[0] == ASN_GENERALTIME)
2950         {
2951             if (cbEncoded <= 1)
2952             {
2953                 SetLastError(CRYPT_E_ASN1_EOD);
2954                 ret = FALSE;
2955             }
2956             else if (pbEncoded[1] > 0x7f)
2957             {
2958                 /* long-form date strings really can't be valid */
2959                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2960                 ret = FALSE;
2961             }
2962             else
2963             {
2964                 BYTE len = pbEncoded[1];
2965
2966                 if (len < MIN_ENCODED_TIME_LENGTH)
2967                 {
2968                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2969                     ret = FALSE;
2970                 }
2971                 else
2972                 {
2973                     SYSTEMTIME sysTime = { 0 };
2974
2975                     pbEncoded += 2;
2976                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2977                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2978                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2979                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2980                     if (ret && len > 0)
2981                     {
2982                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2983                          sysTime.wMinute);
2984                         if (ret && len > 0)
2985                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2986                              sysTime.wSecond);
2987                         if (ret && len > 0 && (*pbEncoded == '.' ||
2988                          *pbEncoded == ','))
2989                         {
2990                             BYTE digits;
2991
2992                             pbEncoded++;
2993                             len--;
2994                             /* workaround macro weirdness */
2995                             digits = min(len, 3);
2996                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2997                              sysTime.wMilliseconds);
2998                         }
2999                         if (ret)
3000                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3001                              &sysTime);
3002                     }
3003                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3004                      pDecodePara, pvStructInfo, pcbStructInfo,
3005                      sizeof(FILETIME))))
3006                     {
3007                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3008                             pvStructInfo = *(BYTE **)pvStructInfo;
3009                         ret = SystemTimeToFileTime(&sysTime,
3010                          (FILETIME *)pvStructInfo);
3011                     }
3012                 }
3013             }
3014         }
3015         else
3016         {
3017             SetLastError(CRYPT_E_ASN1_BADTAG);
3018             ret = FALSE;
3019         }
3020     }
3021     __EXCEPT_PAGE_FAULT
3022     {
3023         SetLastError(STATUS_ACCESS_VIOLATION);
3024         ret = FALSE;
3025     }
3026     __ENDTRY
3027     return ret;
3028 }
3029
3030 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3031  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3032  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3033 {
3034     BOOL ret;
3035
3036     __TRY
3037     {
3038         if (pbEncoded[0] == ASN_UTCTIME)
3039             ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3040              pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3041              pcbStructInfo);
3042         else if (pbEncoded[0] == ASN_GENERALTIME)
3043             ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3044              lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3045              pvStructInfo, pcbStructInfo);
3046         else
3047         {
3048             SetLastError(CRYPT_E_ASN1_BADTAG);
3049             ret = FALSE;
3050         }
3051     }
3052     __EXCEPT_PAGE_FAULT
3053     {
3054         SetLastError(STATUS_ACCESS_VIOLATION);
3055         ret = FALSE;
3056     }
3057     __ENDTRY
3058     return ret;
3059 }
3060
3061 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3062  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3063  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3064 {
3065     BOOL ret = TRUE;
3066
3067     __TRY
3068     {
3069         if (pbEncoded[0] == ASN_SEQUENCEOF)
3070         {
3071             DWORD bytesNeeded, dataLen, remainingLen, cValue;
3072
3073             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3074             {
3075                 BYTE lenBytes;
3076                 const BYTE *ptr;
3077
3078                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3079                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3080                 cValue = 0;
3081                 ptr = pbEncoded + 1 + lenBytes;
3082                 remainingLen = dataLen;
3083                 while (ret && remainingLen)
3084                 {
3085                     DWORD nextLen;
3086
3087                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3088                     if (ret)
3089                     {
3090                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3091
3092                         remainingLen -= 1 + nextLenBytes + nextLen;
3093                         ptr += 1 + nextLenBytes + nextLen;
3094                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
3095                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3096                             bytesNeeded += 1 + nextLenBytes + nextLen;
3097                         cValue++;
3098                     }
3099                 }
3100                 if (ret)
3101                 {
3102                     CRYPT_SEQUENCE_OF_ANY *seq;
3103                     BYTE *nextPtr;
3104                     DWORD i;
3105
3106                     if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3107                      pvStructInfo, pcbStructInfo, bytesNeeded)))
3108                     {
3109                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3110                             pvStructInfo = *(BYTE **)pvStructInfo;
3111                         seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3112                         seq->cValue = cValue;
3113                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3114                          sizeof(*seq));
3115                         nextPtr = (BYTE *)seq->rgValue +
3116                          cValue * sizeof(CRYPT_DER_BLOB);
3117                         ptr = pbEncoded + 1 + lenBytes;
3118                         remainingLen = dataLen;
3119                         i = 0;
3120                         while (ret && remainingLen)
3121                         {
3122                             DWORD nextLen;
3123
3124                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3125                             if (ret)
3126                             {
3127                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3128
3129                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
3130                                  nextLen;
3131                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3132                                     seq->rgValue[i].pbData = (BYTE *)ptr;
3133                                 else
3134                                 {
3135                                     seq->rgValue[i].pbData = nextPtr;
3136                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
3137                                      nextLen);
3138                                     nextPtr += 1 + nextLenBytes + nextLen;
3139                                 }
3140                                 remainingLen -= 1 + nextLenBytes + nextLen;
3141                                 ptr += 1 + nextLenBytes + nextLen;
3142                                 i++;
3143                             }
3144                         }
3145                     }
3146                 }
3147             }
3148         }
3149         else
3150         {
3151             SetLastError(CRYPT_E_ASN1_BADTAG);
3152             ret = FALSE;
3153         }
3154     }
3155     __EXCEPT_PAGE_FAULT
3156     {
3157         SetLastError(STATUS_ACCESS_VIOLATION);
3158         ret = FALSE;
3159     }
3160     __ENDTRY
3161     return ret;
3162 }
3163
3164 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3165  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3166  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3167 {
3168     BOOL ret;
3169
3170     if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3171     {
3172         DWORD bytesNeeded, dataLen;
3173
3174         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3175         {
3176             struct AsnArrayDescriptor arrayDesc = {
3177              ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3178              sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3179              offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3180             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3181
3182             if (dataLen)
3183             {
3184                 DWORD nameLen;
3185
3186                 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3187                  pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3188                  0, NULL, NULL, &nameLen, NULL);
3189                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3190             }
3191             else
3192                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3193             if (!pvStructInfo)
3194                 *pcbStructInfo = bytesNeeded;
3195             else if (*pcbStructInfo < bytesNeeded)
3196             {
3197                 *pcbStructInfo = bytesNeeded;
3198                 SetLastError(ERROR_MORE_DATA);
3199                 ret = FALSE;
3200             }
3201             else
3202             {
3203                 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3204
3205                 if (dataLen)
3206                 {
3207                     name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3208                     ret = CRYPT_AsnDecodeArray(&arrayDesc,
3209                      pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3210                      0, NULL, &name->u.FullName, pcbStructInfo,
3211                      name->u.FullName.rgAltEntry);
3212                 }
3213                 else
3214                     name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3215             }
3216         }
3217     }
3218     else
3219     {
3220         SetLastError(CRYPT_E_ASN1_BADTAG);
3221         ret = FALSE;
3222     }
3223     return ret;
3224 }
3225
3226 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3227  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3228  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3229 {
3230     struct AsnDecodeSequenceItem items[] = {
3231      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3232        DistPointName), CRYPT_AsnDecodeDistPointName,
3233        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3234        DistPointName.u.FullName.rgAltEntry), 0 },
3235      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3236        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3237        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3238      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3239        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3240        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3241     };
3242     BOOL ret;
3243
3244     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3245      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3246      dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3247     return ret;
3248 }
3249
3250 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3251  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3252  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3253 {
3254     BOOL ret;
3255
3256     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3257      pDecodePara, pvStructInfo, *pcbStructInfo);
3258
3259     __TRY
3260     {
3261         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3262          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3263          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3264
3265         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3266          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3267     }
3268     __EXCEPT_PAGE_FAULT
3269     {
3270         SetLastError(STATUS_ACCESS_VIOLATION);
3271         ret = FALSE;
3272     }
3273     __ENDTRY
3274     return ret;
3275 }
3276
3277 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3278  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3279  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3280 {
3281     BOOL ret;
3282
3283     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3284      pDecodePara, pvStructInfo, *pcbStructInfo);
3285
3286     __TRY
3287     {
3288         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3289          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3290
3291         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3292          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3293     }
3294     __EXCEPT_PAGE_FAULT
3295     {
3296         SetLastError(STATUS_ACCESS_VIOLATION);
3297         ret = FALSE;
3298     }
3299     __ENDTRY
3300     return ret;
3301 }
3302
3303 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3304  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3305  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3306 {
3307     BOOL ret;
3308
3309     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3310      pDecodePara, pvStructInfo, *pcbStructInfo);
3311
3312     __TRY
3313     {
3314         struct AsnDecodeSequenceItem items[] = {
3315          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3316            DistPointName), CRYPT_AsnDecodeDistPointName,
3317            sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3318            offsetof(CRL_ISSUING_DIST_POINT,
3319            DistPointName.u.FullName.rgAltEntry), 0 },
3320          { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3321            fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3322            FALSE, 0 },
3323          { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3324            fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3325            FALSE, 0 },
3326          { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3327            OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3328            sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3329            OnlySomeReasonFlags.pbData), 0 },
3330          { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3331            fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3332         };
3333
3334         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3335          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3336          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3337     }
3338     __EXCEPT_PAGE_FAULT
3339     {
3340         SetLastError(STATUS_ACCESS_VIOLATION);
3341         ret = FALSE;
3342     }
3343     __ENDTRY
3344     return ret;
3345 }
3346
3347 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3348  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3349  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3350 {
3351     static HCRYPTOIDFUNCSET set = NULL;
3352     BOOL ret = FALSE;
3353     CryptDecodeObjectExFunc decodeFunc = NULL;
3354     HCRYPTOIDFUNCADDR hFunc = NULL;
3355
3356     TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3357      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3358      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3359
3360     if (!pvStructInfo && !pcbStructInfo)
3361     {
3362         SetLastError(ERROR_INVALID_PARAMETER);
3363         return FALSE;
3364     }
3365     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3366      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3367     {
3368         SetLastError(ERROR_FILE_NOT_FOUND);
3369         return FALSE;
3370     }
3371     if (!cbEncoded)
3372     {
3373         SetLastError(CRYPT_E_ASN1_EOD);
3374         return FALSE;
3375     }
3376     if (cbEncoded > MAX_ENCODED_LEN)
3377     {
3378         SetLastError(CRYPT_E_ASN1_LARGE);
3379         return FALSE;
3380     }
3381
3382     SetLastError(NOERROR);
3383     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3384         *(BYTE **)pvStructInfo = NULL;
3385     if (!HIWORD(lpszStructType))
3386     {
3387         switch (LOWORD(lpszStructType))
3388         {
3389         case (WORD)X509_CERT:
3390             decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3391             break;
3392         case (WORD)X509_CERT_TO_BE_SIGNED:
3393             decodeFunc = CRYPT_AsnDecodeCert;
3394             break;
3395         case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3396             decodeFunc = CRYPT_AsnDecodeCRL;
3397             break;
3398         case (WORD)X509_EXTENSIONS:
3399             decodeFunc = CRYPT_AsnDecodeExtensions;
3400             break;
3401         case (WORD)X509_NAME_VALUE:
3402             decodeFunc = CRYPT_AsnDecodeNameValue;
3403             break;
3404         case (WORD)X509_NAME:
3405             decodeFunc = CRYPT_AsnDecodeName;
3406             break;
3407         case (WORD)X509_PUBLIC_KEY_INFO:
3408             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3409             break;
3410         case (WORD)X509_ALTERNATE_NAME:
3411             decodeFunc = CRYPT_AsnDecodeAltName;
3412             break;
3413         case (WORD)X509_BASIC_CONSTRAINTS:
3414             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3415             break;
3416         case (WORD)X509_BASIC_CONSTRAINTS2:
3417             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3418             break;
3419         case (WORD)RSA_CSP_PUBLICKEYBLOB:
3420             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3421             break;
3422         case (WORD)X509_UNICODE_NAME_VALUE:
3423             decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3424             break;
3425         case (WORD)X509_OCTET_STRING:
3426             decodeFunc = CRYPT_AsnDecodeOctets;
3427             break;
3428         case (WORD)X509_BITS:
3429         case (WORD)X509_KEY_USAGE:
3430             decodeFunc = CRYPT_AsnDecodeBits;
3431             break;
3432         case (WORD)X509_INTEGER:
3433             decodeFunc = CRYPT_AsnDecodeInt;
3434             break;
3435         case (WORD)X509_MULTI_BYTE_INTEGER:
3436             decodeFunc = CRYPT_AsnDecodeInteger;
3437             break;
3438         case (WORD)X509_MULTI_BYTE_UINT:
3439             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3440             break;
3441         case (WORD)X509_ENUMERATED:
3442             decodeFunc = CRYPT_AsnDecodeEnumerated;
3443             break;
3444         case (WORD)X509_CHOICE_OF_TIME:
3445             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3446             break;
3447         case (WORD)X509_SEQUENCE_OF_ANY:
3448             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3449             break;
3450         case (WORD)PKCS_UTC_TIME:
3451             decodeFunc = CRYPT_AsnDecodeUtcTime;
3452             break;
3453         case (WORD)X509_CRL_DIST_POINTS:
3454             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3455             break;
3456         case (WORD)X509_ENHANCED_KEY_USAGE:
3457             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3458             break;
3459         case (WORD)X509_ISSUING_DIST_POINT:
3460             decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3461             break;
3462         default:
3463             FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3464         }
3465     }
3466     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3467         decodeFunc = CRYPT_AsnDecodeExtensions;
3468     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3469         decodeFunc = CRYPT_AsnDecodeUtcTime;
3470     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3471         decodeFunc = CRYPT_AsnDecodeEnumerated;
3472     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3473         decodeFunc = CRYPT_AsnDecodeBits;
3474     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3475         decodeFunc = CRYPT_AsnDecodeOctets;
3476     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3477         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3478     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3479         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3480     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3481         decodeFunc = CRYPT_AsnDecodeAltName;
3482     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3483         decodeFunc = CRYPT_AsnDecodeAltName;
3484     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3485         decodeFunc = CRYPT_AsnDecodeAltName;
3486     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3487         decodeFunc = CRYPT_AsnDecodeAltName;
3488     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3489         decodeFunc = CRYPT_AsnDecodeAltName;
3490     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3491         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3492     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3493         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3494     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3495         decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3496     else
3497         TRACE("OID %s not found or unimplemented, looking for DLL\n",
3498          debugstr_a(lpszStructType));
3499     if (!decodeFunc)
3500     {
3501         if (!set)
3502             set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3503         CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3504          (void **)&decodeFunc, &hFunc);
3505     }
3506     if (decodeFunc)
3507         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3508          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3509     else
3510         SetLastError(ERROR_FILE_NOT_FOUND);
3511     if (hFunc)
3512         CryptFreeOIDFunctionAddress(hFunc, 0);
3513     return ret;
3514 }