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