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