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