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