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