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