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