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