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