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