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