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