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