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