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