mshtml: Added beginning OnDataAvailable implementation.
[wine] / dlls / crypt32 / decode.c
1 /*
2  * Copyright 2005 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * This file implements ASN.1 DER decoding of a limited set of types.
19  * It isn't a full ASN.1 implementation.  Microsoft implements BER
20  * encoding of many of the basic types in msasn1.dll, but that interface is
21  * undocumented, so I implement them here.
22  *
23  * References:
24  * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25  * (available online, look for a PDF copy as the HTML versions tend to have
26  * translation errors.)
27  *
28  * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
29  *
30  * MSDN, especially:
31  * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
32  */
33
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #define NONAMELESSUNION
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "excpt.h"
44 #include "wincrypt.h"
45 #include "winreg.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "crypt32_private.h"
50
51 /* This is a bit arbitrary, but to set some limit: */
52 #define MAX_ENCODED_LEN 0x02000000
53
54 #define ASN_FLAGS_MASK 0xe0
55 #define ASN_TYPE_MASK  0x1f
56
57 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
58
59 struct GenericArray
60 {
61     DWORD cItems;
62     BYTE *rgItems;
63 };
64
65 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
66  DWORD, DWORD, void *, DWORD *);
67 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
68  DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69
70 /* Prototypes for built-in decoders.  They follow the Ex style prototypes.
71  * The dwCertEncodingType and lpszStructType are ignored by the built-in
72  * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73  * since it must call functions in external DLLs that follow these signatures.
74  */
75 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
76  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
77  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
78 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
79  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
80  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
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  * (This isn't intended to be the externally-called one.)
84  */
85 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
86  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
87  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
88 /* Assumes algo->Parameters.pbData is set ahead of time.  Internal func. */
89 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
90  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
91  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
92 /* Internal function */
93 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
94  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
95  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
98  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
99  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
100 /* Like CRYPT_AsnDecodeBits, 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.
103  */
104 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
105  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
106  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
107 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
108  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
109  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
110 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
111  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
112  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114  * member has been initialized, doesn't do exception handling, and doesn't do
115  * memory allocation.
116  */
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned.  */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124  void *pvStructInfo, DWORD *pcbStructInfo);
125
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128  DWORD *pcbStructInfo)
129 {
130     static HCRYPTOIDFUNCSET set = NULL;
131     BOOL ret = FALSE;
132     CryptDecodeObjectFunc pCryptDecodeObject;
133     HCRYPTOIDFUNCADDR hFunc;
134
135     TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
136      debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137      pvStructInfo, pcbStructInfo);
138
139     if (!pvStructInfo && !pcbStructInfo)
140     {
141         SetLastError(ERROR_INVALID_PARAMETER);
142         return FALSE;
143     }
144
145     /* Try registered DLL first.. */
146     if (!set)
147         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149      (void **)&pCryptDecodeObject, &hFunc);
150     if (pCryptDecodeObject)
151     {
152         ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154         CryptFreeOIDFunctionAddress(hFunc, 0);
155     }
156     else
157     {
158         /* If not, use CryptDecodeObjectEx */
159         ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160          cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
161     }
162     return ret;
163 }
164
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
167
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169  * where pbEncoded[0] is the tag.  If the data are too short to contain a
170  * length or if the length is too large for cbEncoded, sets an appropriate
171  * error code and returns FALSE.
172  */
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
174  DWORD *len)
175 {
176     BOOL ret;
177
178     if (cbEncoded <= 1)
179     {
180         SetLastError(CRYPT_E_ASN1_CORRUPT);
181         ret = FALSE;
182     }
183     else if (pbEncoded[1] <= 0x7f)
184     {
185         if (pbEncoded[1] + 1 > cbEncoded)
186         {
187             SetLastError(CRYPT_E_ASN1_EOD);
188             ret = FALSE;
189         }
190         else
191         {
192             *len = pbEncoded[1];
193             ret = TRUE;
194         }
195     }
196     else
197     {
198         BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
199
200         if (lenLen > sizeof(DWORD) + 1)
201         {
202             SetLastError(CRYPT_E_ASN1_LARGE);
203             ret = FALSE;
204         }
205         else if (lenLen + 2 > cbEncoded)
206         {
207             SetLastError(CRYPT_E_ASN1_CORRUPT);
208             ret = FALSE;
209         }
210         else
211         {
212             DWORD out = 0;
213
214             pbEncoded += 2;
215             while (--lenLen)
216             {
217                 out <<= 8;
218                 out |= *pbEncoded++;
219             }
220             if (out + lenLen + 1 > cbEncoded)
221             {
222                 SetLastError(CRYPT_E_ASN1_EOD);
223                 ret = FALSE;
224             }
225             else
226             {
227                 *len = out;
228                 ret = TRUE;
229             }
230         }
231     }
232     return ret;
233 }
234
235 /* Helper function to check *pcbStructInfo, set it to the required size, and
236  * optionally to allocate memory.  Assumes pvStructInfo is not NULL.
237  * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
238  * pointer to the newly allocated memory.
239  */
240 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
241  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
242  DWORD bytesNeeded)
243 {
244     BOOL ret = TRUE;
245
246     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
247     {
248         if (pDecodePara && pDecodePara->pfnAlloc)
249             *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
250         else
251             *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
252         if (!*(BYTE **)pvStructInfo)
253             ret = FALSE;
254         else
255             *pcbStructInfo = bytesNeeded;
256     }
257     else if (*pcbStructInfo < bytesNeeded)
258     {
259         *pcbStructInfo = bytesNeeded;
260         SetLastError(ERROR_MORE_DATA);
261         ret = FALSE;
262     }
263     return ret;
264 }
265
266 /* tag:
267  *     The expected tag of the item.  If tag is 0, decodeFunc is called
268  *     regardless of the tag value seen.
269  * offset:
270  *     A sequence is decoded into a struct.  The offset member is the
271  *     offset of this item within that struct.
272  * decodeFunc:
273  *     The decoder function to use.  If this is NULL, then the member isn't
274  *     decoded, but minSize space is reserved for it.
275  * minSize:
276  *     The minimum amount of space occupied after decoding.  You must set this.
277  * optional:
278  *     If true, and the tag doesn't match the expected tag for this item,
279  *     or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
280  *     filled with 0 for this member.
281  * hasPointer, pointerOffset, minSize:
282  *     If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283  *     the offset within the (outer) struct of the data pointer (or to the
284  *     first data pointer, if more than one exist).
285  * size:
286  *     Used by CRYPT_AsnDecodeSequence, not for your use.
287  */
288 struct AsnDecodeSequenceItem
289 {
290     BYTE                    tag;
291     DWORD                   offset;
292     CryptDecodeObjectExFunc decodeFunc;
293     DWORD                   minSize;
294     BOOL                    optional;
295     BOOL                    hasPointer;
296     DWORD                   pointerOffset;
297     DWORD                   size;
298 };
299
300 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
301  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
302  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
303 {
304     BOOL ret;
305     DWORD i;
306     const BYTE *ptr;
307
308     ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
309     for (i = 0, ret = TRUE; ret && i < cItem; i++)
310     {
311         if (cbEncoded - (ptr - pbEncoded) != 0)
312         {
313             DWORD nextItemLen;
314
315             if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
316              &nextItemLen)))
317             {
318                 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
319
320                 if (ptr[0] == items[i].tag || !items[i].tag)
321                 {
322                     if (nextData && pvStructInfo && items[i].hasPointer)
323                     {
324                         TRACE("Setting next pointer to %p\n",
325                          nextData);
326                         *(BYTE **)((BYTE *)pvStructInfo +
327                          items[i].pointerOffset) = nextData;
328                     }
329                     if (items[i].decodeFunc)
330                     {
331                         if (pvStructInfo)
332                             TRACE("decoding item %ld\n", i);
333                         else
334                             TRACE("sizing item %ld\n", i);
335                         ret = items[i].decodeFunc(dwCertEncodingType,
336                          NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
337                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
338                          pvStructInfo ?  (BYTE *)pvStructInfo + items[i].offset
339                          : NULL, &items[i].size);
340                         if (ret)
341                         {
342                             if (nextData && items[i].hasPointer &&
343                              items[i].size > items[i].minSize)
344                             {
345                                 nextData += items[i].size - items[i].minSize;
346                                 /* align nextData to DWORD boundaries */
347                                 if (items[i].size % sizeof(DWORD))
348                                     nextData += sizeof(DWORD) - items[i].size %
349                                      sizeof(DWORD);
350                             }
351                             /* Account for alignment padding */
352                             if (items[i].size % sizeof(DWORD))
353                                 items[i].size += sizeof(DWORD) -
354                                  items[i].size % sizeof(DWORD);
355                             ptr += 1 + nextItemLenBytes + nextItemLen;
356                         }
357                         else if (items[i].optional &&
358                          GetLastError() == CRYPT_E_ASN1_BADTAG)
359                         {
360                             TRACE("skipping optional item %ld\n", i);
361                             items[i].size = items[i].minSize;
362                             SetLastError(NOERROR);
363                             ret = TRUE;
364                         }
365                         else
366                             TRACE("item %ld failed: %08lx\n", i,
367                              GetLastError());
368                     }
369                     else
370                         items[i].size = items[i].minSize;
371                 }
372                 else if (items[i].optional)
373                 {
374                     TRACE("skipping optional item %ld\n", i);
375                     items[i].size = items[i].minSize;
376                 }
377                 else
378                 {
379                     TRACE("tag %02x doesn't match expected %02x\n",
380                      ptr[0], items[i].tag);
381                     SetLastError(CRYPT_E_ASN1_BADTAG);
382                     ret = FALSE;
383                 }
384             }
385         }
386         else if (items[i].optional)
387         {
388             TRACE("missing optional item %ld, skipping\n", i);
389             items[i].size = items[i].minSize;
390         }
391         else
392         {
393             TRACE("not enough bytes for item %ld, failing\n", i);
394             SetLastError(CRYPT_E_ASN1_CORRUPT);
395             ret = FALSE;
396         }
397     }
398     if (cbEncoded - (ptr - pbEncoded) != 0)
399     {
400         TRACE("%ld remaining bytes, failing\n", cbEncoded -
401          (ptr - pbEncoded));
402         SetLastError(CRYPT_E_ASN1_CORRUPT);
403         ret = FALSE;
404     }
405     return ret;
406 }
407
408 /* This decodes an arbitrary sequence into a contiguous block of memory
409  * (basically, a struct.)  Each element being decoded is described by a struct
410  * AsnDecodeSequenceItem, see above.
411  * startingPointer is an optional pointer to the first place where dynamic
412  * data will be stored.  If you know the starting offset, you may pass it
413  * here.  Otherwise, pass NULL, and one will be inferred from the items.
414  * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
415  * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
416  */
417 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
418  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
419  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
420  void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
421 {
422     BOOL ret;
423
424     TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
425      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
426      startingPointer);
427
428     if (pbEncoded[0] == ASN_SEQUENCE)
429     {
430         DWORD dataLen;
431
432         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
433         {
434             DWORD i;
435
436             ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
437              cbEncoded, dwFlags, NULL, NULL);
438             if (ret)
439             {
440                 DWORD bytesNeeded = 0, structSize = 0;
441
442                 for (i = 0; i < cItem; i++)
443                 {
444                     bytesNeeded += items[i].size;
445                     structSize += items[i].minSize;
446                 }
447                 if (!pvStructInfo)
448                     *pcbStructInfo = bytesNeeded;
449                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
450                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
451                 {
452                     BYTE *nextData;
453
454                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
455                         pvStructInfo = *(BYTE **)pvStructInfo;
456                     if (startingPointer)
457                         nextData = (BYTE *)startingPointer;
458                     else
459                         nextData = (BYTE *)pvStructInfo + structSize;
460                     memset(pvStructInfo, 0, structSize);
461                     ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
462                      pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
463                 }
464             }
465         }
466     }
467     else
468     {
469         SetLastError(CRYPT_E_ASN1_BADTAG);
470         ret = FALSE;
471     }
472     TRACE("returning %d (%08lx)\n", ret, GetLastError());
473     return ret;
474 }
475
476 /* tag:
477  *     The expected tag of the entire encoded array (usually a variant
478  *     of ASN_SETOF or ASN_SEQUENCEOF.)
479  * decodeFunc:
480  *     used to decode each item in the array
481  * itemSize:
482  *      is the minimum size of each decoded item
483  * hasPointer:
484  *      indicates whether each item has a dynamic pointer
485  * pointerOffset:
486  *     indicates the offset within itemSize at which the pointer exists
487  */
488 struct AsnArrayDescriptor
489 {
490     BYTE                    tag;
491     CryptDecodeObjectExFunc decodeFunc;
492     DWORD                   itemSize;
493     BOOL                    hasPointer;
494     DWORD                   pointerOffset;
495 };
496
497 struct AsnArrayItemSize
498 {
499     DWORD encodedLen;
500     DWORD size;
501 };
502
503 /* Decodes an array of like types into a struct GenericArray.
504  * The layout and decoding of the array are described by a struct
505  * AsnArrayDescriptor.
506  */
507 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
508  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
509  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
510  void *startingPointer)
511 {
512     BOOL ret = TRUE;
513
514     TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc, pbEncoded,
515      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
516      startingPointer);
517
518     if (pbEncoded[0] == arrayDesc->tag)
519     {
520         DWORD dataLen;
521
522         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
523         {
524             DWORD bytesNeeded, cItems = 0;
525             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
526             /* There can be arbitrarily many items, but there is often only one.
527              */
528             struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
529
530             bytesNeeded = sizeof(struct GenericArray);
531             if (dataLen)
532             {
533                 const BYTE *ptr;
534
535                 for (ptr = pbEncoded + 1 + lenBytes; ret &&
536                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
537                 {
538                     DWORD itemLenBytes, itemDataLen, size;
539
540                     itemLenBytes = GET_LEN_BYTES(ptr[1]);
541                     /* Each item decoded may not tolerate extraneous bytes, so
542                      * get the length of the next element and pass it directly.
543                      */
544                     ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
545                      &itemDataLen);
546                     if (ret)
547                         ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
548                          1 + itemLenBytes + itemDataLen,
549                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
550                          &size);
551                     if (ret)
552                     {
553                         DWORD nextLen;
554
555                         cItems++;
556                         if (itemSizes != &itemSize)
557                             itemSizes = CryptMemRealloc(itemSizes,
558                              cItems * sizeof(struct AsnArrayItemSize));
559                         else
560                         {
561                             itemSizes =
562                              CryptMemAlloc(
563                              cItems * sizeof(struct AsnArrayItemSize));
564                             memcpy(itemSizes, &itemSize, sizeof(itemSize));
565                         }
566                         if (itemSizes)
567                         {
568                             itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
569                              + itemDataLen;
570                             itemSizes[cItems - 1].size = size;
571                             bytesNeeded += size;
572                             ret = CRYPT_GetLen(ptr,
573                              cbEncoded - (ptr - pbEncoded), &nextLen);
574                             if (ret)
575                                 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
576                         }
577                         else
578                             ret = FALSE;
579                     }
580                 }
581             }
582             if (ret)
583             {
584                 if (!pvStructInfo)
585                     *pcbStructInfo = bytesNeeded;
586                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
587                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
588                 {
589                     DWORD i;
590                     BYTE *nextData;
591                     const BYTE *ptr;
592                     struct GenericArray *array;
593
594                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
595                         pvStructInfo = *(BYTE **)pvStructInfo;
596                     array = (struct GenericArray *)pvStructInfo;
597                     array->cItems = cItems;
598                     if (startingPointer)
599                         array->rgItems = startingPointer;
600                     else
601                         array->rgItems = (BYTE *)array +
602                          sizeof(struct GenericArray);
603                     nextData = (BYTE *)array->rgItems +
604                      array->cItems * arrayDesc->itemSize;
605                     for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
606                      i < cItems && ptr - pbEncoded - 1 - lenBytes <
607                      dataLen; i++)
608                     {
609                         if (arrayDesc->hasPointer)
610                             *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
611                              + arrayDesc->pointerOffset) = nextData;
612                         ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
613                          itemSizes[i].encodedLen,
614                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
615                          array->rgItems + i * arrayDesc->itemSize,
616                          &itemSizes[i].size);
617                         if (ret)
618                         {
619                             DWORD nextLen;
620
621                             nextData += itemSizes[i].size - arrayDesc->itemSize;
622                             ret = CRYPT_GetLen(ptr,
623                              cbEncoded - (ptr - pbEncoded), &nextLen);
624                             if (ret)
625                                 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
626                         }
627                     }
628                 }
629             }
630             if (itemSizes != &itemSize)
631                 CryptMemFree(itemSizes);
632         }
633     }
634     else
635     {
636         SetLastError(CRYPT_E_ASN1_BADTAG);
637         ret = FALSE;
638     }
639     return ret;
640 }
641
642 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
643  * pvStructInfo.  The BLOB must be non-empty, otherwise the last error is set
644  * to CRYPT_E_ASN1_CORRUPT.
645  * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
646  * set!
647  */
648 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
649  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
650  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
651 {
652     BOOL ret;
653     DWORD dataLen;
654
655     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
656     {
657         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
658         DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
659        
660         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
661             bytesNeeded += 1 + lenBytes + dataLen;
662
663         if (!pvStructInfo)
664             *pcbStructInfo = bytesNeeded;
665         else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, 
666          pvStructInfo, pcbStructInfo, bytesNeeded)))
667         {
668             CRYPT_DER_BLOB *blob;
669
670             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
671                 pvStructInfo = *(BYTE **)pvStructInfo;
672             blob = (CRYPT_DER_BLOB *)pvStructInfo;
673             blob->cbData = 1 + lenBytes + dataLen;
674             if (blob->cbData)
675             {
676                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
677                     blob->pbData = (BYTE *)pbEncoded;
678                 else
679                 {
680                     assert(blob->pbData);
681                     memcpy(blob->pbData, pbEncoded, blob->cbData);
682                 }
683             }
684             else
685             {
686                 SetLastError(CRYPT_E_ASN1_CORRUPT);
687                 ret = FALSE;
688             }
689         }
690     }
691     return ret;
692 }
693
694 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
695 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
696  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
697  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
698 {
699     BOOL ret;
700
701     TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
702      pDecodePara, pvStructInfo, *pcbStructInfo);
703
704     /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
705      * place.
706      */
707     ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
708      pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
709      pvStructInfo, pcbStructInfo);
710     if (ret && pvStructInfo)
711     {
712         CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
713
714         if (blob->cbData)
715         {
716             DWORD i;
717             BYTE temp;
718
719             for (i = 0; i < blob->cbData / 2; i++)
720             {
721                 temp = blob->pbData[i];
722                 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
723                 blob->pbData[blob->cbData - i - 1] = temp;
724             }
725         }
726     }
727     TRACE("returning %d (%08lx)\n", ret, GetLastError());
728     return ret;
729 }
730
731 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
732  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
733  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
734 {
735     BOOL ret = TRUE;
736
737     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
738      pDecodePara, pvStructInfo, *pcbStructInfo);
739
740     __TRY
741     {
742         struct AsnDecodeSequenceItem items[] = {
743          { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
744            CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
745            offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
746          { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
747            SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
748            sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
749            offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
750          { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
751            CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
752            offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
753         };
754
755         if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
756             items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
757         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
758          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
759          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
760     }
761     __EXCEPT_PAGE_FAULT
762     {
763         SetLastError(STATUS_ACCESS_VIOLATION);
764         ret = FALSE;
765     }
766     __ENDTRY
767     return ret;
768 }
769
770 /* Internal function */
771 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
772  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
773  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
774 {
775     BOOL ret;
776     DWORD dataLen;
777
778     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
779     {
780         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
781
782         ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
783          pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
784          pvStructInfo, pcbStructInfo);
785     }
786     return ret;
787 }
788
789 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
790  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
791  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
792 {
793     BOOL ret;
794
795     struct AsnDecodeSequenceItem items[] = {
796      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
797        CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
798      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
799        CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
800     };
801
802     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
803      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
804      pDecodePara, pvStructInfo, pcbStructInfo, NULL);
805     return ret;
806 }
807
808 /* Internal function */
809 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
810  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
811  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
812 {
813     BOOL ret;
814     DWORD dataLen;
815
816     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
817     {
818         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
819
820         ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
821          X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
822          pDecodePara, pvStructInfo, pcbStructInfo);
823     }
824     return ret;
825 }
826
827 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
828  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
829  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
830 {
831     BOOL ret = TRUE;
832
833     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
834      pDecodePara, pvStructInfo, *pcbStructInfo);
835
836     __TRY
837     {
838         struct AsnDecodeSequenceItem items[] = {
839          { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
840            CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
841          { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
842            CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
843            TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
844          { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
845            CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
846            FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
847          { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
848            sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
849            Issuer.pbData) },
850          { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
851            CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
852            FALSE, 0 },
853          { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
854            sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
855            Subject.pbData) },
856          { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
857            CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
858            FALSE, TRUE, offsetof(CERT_INFO,
859            SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
860          { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
861            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
862            offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
863          { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
864            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
865            offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
866          { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
867            CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
868            offsetof(CERT_INFO, rgExtension), 0 },
869         };
870
871         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
872          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
873          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
874     }
875     __EXCEPT_PAGE_FAULT
876     {
877         SetLastError(STATUS_ACCESS_VIOLATION);
878         ret = FALSE;
879     }
880     __ENDTRY
881     return ret;
882 }
883
884 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
885  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
886  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
887 {
888     BOOL ret;
889     struct AsnDecodeSequenceItem items[] = {
890      { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
891        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
892        offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
893      { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
894        sizeof(FILETIME), FALSE, FALSE, 0 },
895      { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
896        CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
897        offsetof(CRL_ENTRY, rgExtension), 0 },
898     };
899     PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
900
901     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
902      *pcbStructInfo);
903
904     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
905      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
906      NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
907     return ret;
908 }
909
910 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
911  * been set prior to calling.
912  */
913 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
914  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
915  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
916 {
917     BOOL ret;
918     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
919      CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
920      offsetof(CRL_ENTRY, SerialNumber.pbData) };
921     struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
922
923     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
924      pDecodePara, pvStructInfo, *pcbStructInfo);
925
926     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
927      pDecodePara, pvStructInfo, pcbStructInfo,
928      entries ? entries->rgItems : NULL);
929     TRACE("Returning %d (%08lx)\n", ret, GetLastError());
930     return ret;
931 }
932
933 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
934  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
935  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
936 {
937     BOOL ret = TRUE;
938
939     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
940      pDecodePara, pvStructInfo, *pcbStructInfo);
941
942     __TRY
943     {
944         struct AsnDecodeSequenceItem items[] = {
945          { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CRL_INFO, dwVersion),
946            CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
947          { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
948            CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
949            FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
950          { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
951            sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
952            Issuer.pbData) },
953          { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
954            sizeof(FILETIME), FALSE, FALSE, 0 },
955          { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
956            sizeof(FILETIME), TRUE, FALSE, 0 },
957          { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
958            CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
959            offsetof(CRL_INFO, rgCRLEntry), 0 },
960          /* Note that the extensions are ignored by MS, so I'll ignore them too
961           */
962          { 0, offsetof(CRL_INFO, cExtension), NULL,
963            sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
964         };
965
966         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
967          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
968          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
969     }
970     __EXCEPT_PAGE_FAULT
971     {
972         SetLastError(STATUS_ACCESS_VIOLATION);
973         ret = FALSE;
974     }
975     __ENDTRY
976
977     TRACE("Returning %d (%08lx)\n", ret, GetLastError());
978     return ret;
979 }
980
981 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
982  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
983  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
984 {
985     BOOL ret = TRUE;
986
987     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
988      pDecodePara, pvStructInfo, *pcbStructInfo);
989
990     if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
991     {
992         DWORD dataLen;
993
994         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
995         {
996             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
997             DWORD bytesNeeded = sizeof(LPSTR);
998
999             if (dataLen)
1000             {
1001                 /* The largest possible string for the first two components
1002                  * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1003                  */
1004                 char firstTwo[6];
1005                 const BYTE *ptr;
1006
1007                 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1008                  pbEncoded[1 + lenBytes] / 40,
1009                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1010                  * 40);
1011                 bytesNeeded += strlen(firstTwo) + 1;
1012                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1013                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
1014                 {
1015                     /* large enough for ".4000000" */
1016                     char str[9];
1017                     int val = 0;
1018
1019                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1020                      (*ptr & 0x80))
1021                     {
1022                         val <<= 7;
1023                         val |= *ptr & 0x7f;
1024                         ptr++;
1025                     }
1026                     if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1027                      (*ptr & 0x80))
1028                     {
1029                         SetLastError(CRYPT_E_ASN1_CORRUPT);
1030                         ret = FALSE;
1031                     }
1032                     else
1033                     {
1034                         val <<= 7;
1035                         val |= *ptr++;
1036                         snprintf(str, sizeof(str), ".%d", val);
1037                         bytesNeeded += strlen(str);
1038                     }
1039                 }
1040             }
1041             if (!pvStructInfo)
1042                 *pcbStructInfo = bytesNeeded;
1043             else if (*pcbStructInfo < bytesNeeded)
1044             {
1045                 *pcbStructInfo = bytesNeeded;
1046                 SetLastError(ERROR_MORE_DATA);
1047                 ret = FALSE;
1048             }
1049             else
1050             {
1051                 if (dataLen)
1052                 {
1053                     const BYTE *ptr;
1054                     LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1055
1056                     *pszObjId = 0;
1057                     sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1058                      pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1059                      40) * 40);
1060                     pszObjId += strlen(pszObjId);
1061                     for (ptr = pbEncoded + 2 + lenBytes; ret &&
1062                      ptr - pbEncoded - 1 - lenBytes < dataLen; )
1063                     {
1064                         int val = 0;
1065
1066                         while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1067                          (*ptr & 0x80))
1068                         {
1069                             val <<= 7;
1070                             val |= *ptr & 0x7f;
1071                             ptr++;
1072                         }
1073                         val <<= 7;
1074                         val |= *ptr++;
1075                         sprintf(pszObjId, ".%d", val);
1076                         pszObjId += strlen(pszObjId);
1077                     }
1078                 }
1079                 else
1080                     *(LPSTR *)pvStructInfo = NULL;
1081                 *pcbStructInfo = bytesNeeded;
1082             }
1083         }
1084     }
1085     return ret;
1086 }
1087
1088 /* Warning:  assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1089  * ahead of time!
1090  */
1091 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1092  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1093  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1094 {
1095     struct AsnDecodeSequenceItem items[] = {
1096      { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1097        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1098        offsetof(CERT_EXTENSION, pszObjId), 0 },
1099      { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1100        sizeof(BOOL), TRUE, FALSE, 0, 0 },
1101      { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1102        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1103        offsetof(CERT_EXTENSION, Value.pbData) },
1104     };
1105     BOOL ret = TRUE;
1106     PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1107
1108     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1109      *pcbStructInfo);
1110
1111     if (ext)
1112         TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1113     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1114      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1115      ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1116     if (ext)
1117         TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1118          debugstr_a(ext->pszObjId));
1119     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1120     return ret;
1121 }
1122
1123 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1124  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1125  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1126 {
1127     BOOL ret = TRUE;
1128     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1129      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1130      offsetof(CERT_EXTENSION, pszObjId) };
1131     PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1132
1133     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1134      pDecodePara, pvStructInfo, *pcbStructInfo);
1135
1136     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1137      pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1138     return ret;
1139 }
1140
1141 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1142  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1143  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1144 {
1145     BOOL ret = TRUE;
1146
1147     __TRY
1148     {
1149         ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1150          lpszStructType, pbEncoded, cbEncoded,
1151          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1152         if (ret && pvStructInfo)
1153         {
1154             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1155              pcbStructInfo, *pcbStructInfo);
1156             if (ret)
1157             {
1158                 CERT_EXTENSIONS *exts;
1159
1160                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1161                     pvStructInfo = *(BYTE **)pvStructInfo;
1162                 exts = (CERT_EXTENSIONS *)pvStructInfo;
1163                 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1164                  sizeof(CERT_EXTENSIONS));
1165                 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1166                  lpszStructType, pbEncoded, cbEncoded,
1167                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1168                  pcbStructInfo);
1169             }
1170         }
1171     }
1172     __EXCEPT_PAGE_FAULT
1173     {
1174         SetLastError(STATUS_ACCESS_VIOLATION);
1175         ret = FALSE;
1176     }
1177     __ENDTRY
1178     return ret;
1179 }
1180
1181 /* Warning: this assumes the address of value->Value.pbData is already set, in
1182  * order to avoid overwriting memory.  (In some cases, it may change it, if it
1183  * doesn't copy anything to memory.)  Be sure to set it correctly!
1184  */
1185 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1186  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1187  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1188 {
1189     BOOL ret = TRUE;
1190     DWORD dataLen;
1191     CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1192
1193     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1194     {
1195         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1196
1197         switch (pbEncoded[0])
1198         {
1199         case ASN_NUMERICSTRING:
1200         case ASN_PRINTABLESTRING:
1201         case ASN_IA5STRING:
1202             break;
1203         default:
1204             FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
1205             SetLastError(OSS_UNIMPLEMENTED);
1206             ret = FALSE;
1207         }
1208         if (ret)
1209         {
1210             DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
1211
1212             switch (pbEncoded[0])
1213             {
1214             case ASN_NUMERICSTRING:
1215             case ASN_PRINTABLESTRING:
1216             case ASN_IA5STRING:
1217                 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1218                     bytesNeeded += dataLen;
1219                 break;
1220             }
1221             if (!value)
1222                 *pcbStructInfo = bytesNeeded;
1223             else if (*pcbStructInfo < bytesNeeded)
1224             {
1225                 *pcbStructInfo = bytesNeeded;
1226                 SetLastError(ERROR_MORE_DATA);
1227                 ret = FALSE;
1228             }
1229             else
1230             {
1231                 *pcbStructInfo = bytesNeeded;
1232                 switch (pbEncoded[0])
1233                 {
1234                 case ASN_NUMERICSTRING:
1235                     value->dwValueType = CERT_RDN_NUMERIC_STRING;
1236                     break;
1237                 case ASN_PRINTABLESTRING:
1238                     value->dwValueType = CERT_RDN_PRINTABLE_STRING;
1239                     break;
1240                 case ASN_IA5STRING:
1241                     value->dwValueType = CERT_RDN_IA5_STRING;
1242                     break;
1243                 }
1244                 if (dataLen)
1245                 {
1246                     switch (pbEncoded[0])
1247                     {
1248                     case ASN_NUMERICSTRING:
1249                     case ASN_PRINTABLESTRING:
1250                     case ASN_IA5STRING:
1251                         value->Value.cbData = dataLen;
1252                         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1253                             value->Value.pbData = (BYTE *)pbEncoded + 1 +
1254                              lenBytes;
1255                         else
1256                         {
1257                             assert(value->Value.pbData);
1258                             memcpy(value->Value.pbData,
1259                              pbEncoded + 1 + lenBytes, dataLen);
1260                         }
1261                         break;
1262                     }
1263                 }
1264                 else
1265                 {
1266                     value->Value.cbData = 0;
1267                     value->Value.pbData = NULL;
1268                 }
1269             }
1270         }
1271     }
1272     return ret;
1273 }
1274
1275 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1276  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1277  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1278 {
1279     BOOL ret;
1280     struct AsnDecodeSequenceItem items[] = {
1281      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1282        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1283        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1284      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1285        CRYPT_AsnDecodeNameValue, sizeof(CERT_NAME_VALUE),
1286        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1287     };
1288     CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1289
1290     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1291      pvStructInfo, *pcbStructInfo);
1292
1293     if (attr)
1294         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1295     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1296      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1297      attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1298     if (attr)
1299     {
1300         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1301          debugstr_a(attr->pszObjId));
1302         TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1303     }
1304     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1305     return ret;
1306 }
1307
1308 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1309  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1310  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1311 {
1312     BOOL ret = TRUE;
1313     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1314      CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1315      offsetof(CERT_RDN_ATTR, pszObjId) };
1316     PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1317
1318     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1319      pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1320     return ret;
1321 }
1322
1323 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1324  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1325  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1326 {
1327     BOOL ret = TRUE;
1328
1329     __TRY
1330     {
1331         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1332          CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1333          offsetof(CERT_RDN, rgRDNAttr) };
1334
1335         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1336          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1337     }
1338     __EXCEPT_PAGE_FAULT
1339     {
1340         SetLastError(STATUS_ACCESS_VIOLATION);
1341         ret = FALSE;
1342     }
1343     __ENDTRY
1344     return ret;
1345 }
1346
1347 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1348  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1349  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1350 {
1351     BOOL ret = TRUE;
1352     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1353
1354     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1355      pDecodePara, pvStructInfo, *pcbStructInfo);
1356
1357     if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1358         bytesNeeded += cbEncoded;
1359     if (!pvStructInfo)
1360         *pcbStructInfo = bytesNeeded;
1361     else if (*pcbStructInfo < bytesNeeded)
1362     {
1363         SetLastError(ERROR_MORE_DATA);
1364         *pcbStructInfo = bytesNeeded;
1365         ret = FALSE;
1366     }
1367     else
1368     {
1369         PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1370
1371         *pcbStructInfo = bytesNeeded;
1372         blob->cbData = cbEncoded;
1373         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1374             blob->pbData = (LPBYTE)pbEncoded;
1375         else
1376         {
1377             assert(blob->pbData);
1378             memcpy(blob->pbData, pbEncoded, blob->cbData);
1379         }
1380     }
1381     return ret;
1382 }
1383
1384 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1385  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1386  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1387 {
1388     CRYPT_ALGORITHM_IDENTIFIER *algo =
1389      (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1390     BOOL ret = TRUE;
1391     struct AsnDecodeSequenceItem items[] = {
1392      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1393        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, 
1394        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1395      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1396        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
1397        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1398     };
1399
1400     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1401      pDecodePara, pvStructInfo, *pcbStructInfo);
1402
1403     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1404      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1405      pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1406     if (ret && pvStructInfo)
1407     {
1408         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1409          debugstr_a(algo->pszObjId));
1410     }
1411     return ret;
1412 }
1413
1414 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1415  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1416  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1417 {
1418     BOOL ret = TRUE;
1419     struct AsnDecodeSequenceItem items[] = {
1420      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1421        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1422        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1423        Algorithm.pszObjId) },
1424      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1425        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1426        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1427     };
1428     PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1429
1430     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1431      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1432      pDecodePara, pvStructInfo, pcbStructInfo, info ?
1433      info->Algorithm.Parameters.pbData : NULL);
1434     return ret;
1435 }
1436
1437 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1438  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1439  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1440 {
1441     BOOL ret = TRUE;
1442
1443     __TRY
1444     {
1445         DWORD bytesNeeded;
1446
1447         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1448          lpszStructType, pbEncoded, cbEncoded,
1449          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1450         {
1451             if (!pvStructInfo)
1452                 *pcbStructInfo = bytesNeeded;
1453             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1454              pvStructInfo, pcbStructInfo, bytesNeeded)))
1455             {
1456                 PCERT_PUBLIC_KEY_INFO info;
1457
1458                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1459                     pvStructInfo = *(BYTE **)pvStructInfo;
1460                 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1461                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1462                  sizeof(CERT_PUBLIC_KEY_INFO);
1463                 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1464                  lpszStructType, pbEncoded, cbEncoded,
1465                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1466                  &bytesNeeded);
1467             }
1468         }
1469     }
1470     __EXCEPT_PAGE_FAULT
1471     {
1472         SetLastError(STATUS_ACCESS_VIOLATION);
1473         ret = FALSE;
1474     }
1475     __ENDTRY
1476     return ret;
1477 }
1478
1479 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1480  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1481  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1482 {
1483     BOOL ret;
1484
1485     if (cbEncoded < 3)
1486     {
1487         SetLastError(CRYPT_E_ASN1_CORRUPT);
1488         return FALSE;
1489     }
1490     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1491     {
1492         SetLastError(CRYPT_E_ASN1_CORRUPT);
1493         return FALSE;
1494     }
1495     if (pbEncoded[1] > 1)
1496     {
1497         SetLastError(CRYPT_E_ASN1_CORRUPT);
1498         return FALSE;
1499     }
1500     if (!pvStructInfo)
1501     {
1502         *pcbStructInfo = sizeof(BOOL);
1503         ret = TRUE;
1504     }
1505     else if (*pcbStructInfo < sizeof(BOOL))
1506     {
1507         *pcbStructInfo = sizeof(BOOL);
1508         SetLastError(ERROR_MORE_DATA);
1509         ret = FALSE;
1510     }
1511     else
1512     {
1513         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1514         ret = TRUE;
1515     }
1516     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1517     return ret;
1518 }
1519
1520 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1521  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1522  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1523 {
1524     PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1525     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1526     BOOL ret;
1527
1528     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1529      pDecodePara, pvStructInfo, *pcbStructInfo);
1530
1531     if (cbEncoded < 2)
1532     {
1533         SetLastError(CRYPT_E_ASN1_CORRUPT);
1534         return FALSE;
1535     }
1536     if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1537     {
1538         SetLastError(CRYPT_E_ASN1_BADTAG);
1539         return FALSE;
1540     }
1541     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1542     if (1 + lenBytes > cbEncoded)
1543     {
1544         SetLastError(CRYPT_E_ASN1_CORRUPT);
1545         return FALSE;
1546     }
1547     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1548     {
1549         switch (pbEncoded[0] & ASN_TYPE_MASK)
1550         {
1551         case 1: /* rfc822Name */
1552         case 2: /* dNSName */
1553         case 6: /* uniformResourceIdentifier */
1554             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1555             break;
1556         case 7: /* iPAddress */
1557             bytesNeeded += dataLen;
1558             break;
1559         case 8: /* registeredID */
1560             /* FIXME: decode as OID */
1561         case 0: /* otherName */
1562         case 4: /* directoryName */
1563             FIXME("stub\n");
1564             SetLastError(CRYPT_E_ASN1_BADTAG);
1565             ret = FALSE;
1566             break;
1567         case 3: /* x400Address, unimplemented */
1568         case 5: /* ediPartyName, unimplemented */
1569             SetLastError(CRYPT_E_ASN1_BADTAG);
1570             ret = FALSE;
1571             break;
1572         default:
1573             SetLastError(CRYPT_E_ASN1_CORRUPT);
1574             ret = FALSE;
1575         }
1576         if (ret)
1577         {
1578             if (!entry)
1579                 *pcbStructInfo = bytesNeeded;
1580             else if (*pcbStructInfo < bytesNeeded)
1581             {
1582                 *pcbStructInfo = bytesNeeded;
1583                 SetLastError(ERROR_MORE_DATA);
1584                 ret = FALSE;
1585             }
1586             else
1587             {
1588                 *pcbStructInfo = bytesNeeded;
1589                 /* MS used values one greater than the asn1 ones.. sigh */
1590                 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1591                 switch (pbEncoded[0] & ASN_TYPE_MASK)
1592                 {
1593                 case 1: /* rfc822Name */
1594                 case 2: /* dNSName */
1595                 case 6: /* uniformResourceIdentifier */
1596                 {
1597                     DWORD i;
1598
1599                     for (i = 0; i < dataLen; i++)
1600                         entry->u.pwszURL[i] =
1601                          (WCHAR)pbEncoded[1 + lenBytes + i];
1602                     entry->u.pwszURL[i] = 0;
1603                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1604                      debugstr_w(entry->u.pwszURL));
1605                     break;
1606                 }
1607                 case 7: /* iPAddress */
1608                     /* The next data pointer is in the pwszURL spot, that is,
1609                      * the first 4 bytes.  Need to move it to the next spot.
1610                      */
1611                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1612                     entry->u.IPAddress.cbData = dataLen;
1613                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1614                      dataLen);
1615                     break;
1616                 }
1617             }
1618         }
1619     }
1620     return ret;
1621 }
1622
1623 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1624  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1625  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1626 {
1627     BOOL ret = TRUE;
1628     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1629      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1630      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1631     PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1632
1633     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1634      pDecodePara, pvStructInfo, *pcbStructInfo);
1635
1636     if (info)
1637         TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1638     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1639      pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1640     return ret;
1641 }
1642
1643 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1644  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1645  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1646 {
1647     BOOL ret = TRUE;
1648
1649     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1650      pDecodePara, pvStructInfo, *pcbStructInfo);
1651
1652     __TRY
1653     {
1654         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1655          CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1656          offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1657
1658         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1659          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1660     }
1661     __EXCEPT_PAGE_FAULT
1662     {
1663         SetLastError(STATUS_ACCESS_VIOLATION);
1664         ret = FALSE;
1665     }
1666     __ENDTRY
1667     return ret;
1668 }
1669
1670 struct PATH_LEN_CONSTRAINT
1671 {
1672     BOOL  fPathLenConstraint;
1673     DWORD dwPathLenConstraint;
1674 };
1675
1676 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
1677  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1678  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1679 {
1680     BOOL ret = TRUE;
1681
1682     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1683      pvStructInfo, *pcbStructInfo);
1684
1685     if (cbEncoded)
1686     {
1687         if (pbEncoded[0] == ASN_INTEGER)
1688         {
1689             DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
1690
1691             if (!pvStructInfo)
1692                 *pcbStructInfo = bytesNeeded;
1693             else if (*pcbStructInfo < bytesNeeded)
1694             {
1695                 SetLastError(ERROR_MORE_DATA);
1696                 *pcbStructInfo = bytesNeeded;
1697                 ret = FALSE;
1698             }
1699             else
1700             {
1701                 struct PATH_LEN_CONSTRAINT *constraint =
1702                  (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
1703                 DWORD size = sizeof(constraint->dwPathLenConstraint);
1704
1705                 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
1706                  pbEncoded, cbEncoded, 0, NULL,
1707                  &constraint->dwPathLenConstraint, &size);
1708                 if (ret)
1709                     constraint->fPathLenConstraint = TRUE;
1710                 TRACE("got an int, dwPathLenConstraint is %ld\n",
1711                  constraint->dwPathLenConstraint);
1712             }
1713         }
1714         else
1715         {
1716             SetLastError(CRYPT_E_ASN1_CORRUPT);
1717             ret = FALSE;
1718         }
1719     }
1720     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1721     return ret;
1722 }
1723
1724 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
1725  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1726  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1727 {
1728     BOOL ret;
1729     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1730      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
1731      offsetof(CERT_NAME_BLOB, pbData) };
1732     struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1733
1734     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1735      pDecodePara, pvStructInfo, *pcbStructInfo);
1736
1737     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1738      pDecodePara, pvStructInfo, pcbStructInfo,
1739      entries ? entries->rgItems : NULL);
1740     TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1741     return ret;
1742 }
1743
1744 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
1745  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1746  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1747 {
1748     BOOL ret;
1749
1750     __TRY
1751     {
1752         struct AsnDecodeSequenceItem items[] = {
1753          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
1754            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
1755            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
1756          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1757            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1758            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1759          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1760            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
1761            sizeof(struct GenericArray), TRUE, TRUE,
1762            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
1763         };
1764
1765         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1766          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1767          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1768     }
1769     __EXCEPT_PAGE_FAULT
1770     {
1771         SetLastError(STATUS_ACCESS_VIOLATION);
1772         ret = FALSE;
1773     }
1774     __ENDTRY
1775     return ret;
1776 }
1777
1778 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
1779  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1780  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1781 {
1782     BOOL ret;
1783
1784     __TRY
1785     {
1786         struct AsnDecodeSequenceItem items[] = {
1787          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
1788            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
1789          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
1790            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1791            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1792         };
1793
1794         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1795          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1796          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1797     }
1798     __EXCEPT_PAGE_FAULT
1799     {
1800         SetLastError(STATUS_ACCESS_VIOLATION);
1801         ret = FALSE;
1802     }
1803     __ENDTRY
1804     return ret;
1805 }
1806
1807 #define RSA1_MAGIC 0x31415352
1808
1809 struct DECODED_RSA_PUB_KEY
1810 {
1811     DWORD              pubexp;
1812     CRYPT_INTEGER_BLOB modulus;
1813 };
1814
1815 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
1816  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1817  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1818 {
1819     BOOL ret;
1820
1821     __TRY
1822     {
1823         struct AsnDecodeSequenceItem items[] = {
1824          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
1825            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
1826            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
1827            0 },
1828          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
1829            CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
1830         };
1831         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
1832         DWORD size = 0;
1833
1834         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1835          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
1836          CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
1837         if (ret)
1838         {
1839             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1840              decodedKey->modulus.cbData;
1841
1842             if (!pvStructInfo)
1843             {
1844                 *pcbStructInfo = bytesNeeded;
1845                 ret = TRUE;
1846             }
1847             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1848              pvStructInfo, pcbStructInfo, bytesNeeded)))
1849             {
1850                 BLOBHEADER *hdr;
1851                 RSAPUBKEY *rsaPubKey;
1852
1853                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1854                     pvStructInfo = *(BYTE **)pvStructInfo;
1855                 hdr = (BLOBHEADER *)pvStructInfo;
1856                 hdr->bType = PUBLICKEYBLOB;
1857                 hdr->bVersion = CUR_BLOB_VERSION;
1858                 hdr->reserved = 0;
1859                 hdr->aiKeyAlg = CALG_RSA_KEYX;
1860                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
1861                  sizeof(BLOBHEADER));
1862                 rsaPubKey->magic = RSA1_MAGIC;
1863                 rsaPubKey->pubexp = decodedKey->pubexp;
1864                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
1865                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
1866                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
1867                  decodedKey->modulus.cbData);
1868             }
1869             LocalFree(decodedKey);
1870         }
1871     }
1872     __EXCEPT_PAGE_FAULT
1873     {
1874         SetLastError(STATUS_ACCESS_VIOLATION);
1875         ret = FALSE;
1876     }
1877     __ENDTRY
1878     return ret;
1879 }
1880
1881 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
1882  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1883  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1884 {
1885     BOOL ret;
1886     DWORD bytesNeeded, dataLen;
1887
1888     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1889      pDecodePara, pvStructInfo, *pcbStructInfo);
1890
1891     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1892     {
1893         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1894             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1895         else
1896             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1897         if (!pvStructInfo)
1898             *pcbStructInfo = bytesNeeded;
1899         else if (*pcbStructInfo < bytesNeeded)
1900         {
1901             SetLastError(ERROR_MORE_DATA);
1902             *pcbStructInfo = bytesNeeded;
1903             ret = FALSE;
1904         }
1905         else
1906         {
1907             CRYPT_DATA_BLOB *blob;
1908             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1909
1910             blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1911             blob->cbData = dataLen;
1912             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1913                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1914             else
1915             {
1916                 assert(blob->pbData);
1917                 if (blob->cbData)
1918                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1919                      blob->cbData);
1920             }
1921         }
1922     }
1923     return ret;
1924 }
1925
1926 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1927  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1928  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1929 {
1930     BOOL ret;
1931
1932     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1933      pDecodePara, pvStructInfo, *pcbStructInfo);
1934
1935     __TRY
1936     {
1937         DWORD bytesNeeded;
1938
1939         if (!cbEncoded)
1940         {
1941             SetLastError(CRYPT_E_ASN1_CORRUPT);
1942             ret = FALSE;
1943         }
1944         else if (pbEncoded[0] != ASN_OCTETSTRING)
1945         {
1946             SetLastError(CRYPT_E_ASN1_BADTAG);
1947             ret = FALSE;
1948         }
1949         else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
1950          lpszStructType, pbEncoded, cbEncoded,
1951          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1952         {
1953             if (!pvStructInfo)
1954                 *pcbStructInfo = bytesNeeded;
1955             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1956              pvStructInfo, pcbStructInfo, bytesNeeded)))
1957             {
1958                 CRYPT_DATA_BLOB *blob;
1959
1960                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1961                     pvStructInfo = *(BYTE **)pvStructInfo;
1962                 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1963                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
1964                 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
1965                  lpszStructType, pbEncoded, cbEncoded,
1966                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1967                  &bytesNeeded);
1968             }
1969         }
1970     }
1971     __EXCEPT_PAGE_FAULT
1972     {
1973         SetLastError(STATUS_ACCESS_VIOLATION);
1974         ret = FALSE;
1975     }
1976     __ENDTRY
1977     return ret;
1978 }
1979
1980 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1981  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1982  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1983 {
1984     BOOL ret;
1985
1986     TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
1987      pDecodePara, pvStructInfo, *pcbStructInfo);
1988
1989     if (pbEncoded[0] == ASN_BITSTRING)
1990     {
1991         DWORD bytesNeeded, dataLen;
1992
1993         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1994         {
1995             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1996                 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1997             else
1998                 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1999             if (!pvStructInfo)
2000                 *pcbStructInfo = bytesNeeded;
2001             else if (*pcbStructInfo < bytesNeeded)
2002             {
2003                 *pcbStructInfo = bytesNeeded;
2004                 SetLastError(ERROR_MORE_DATA);
2005                 ret = FALSE;
2006             }
2007             else
2008             {
2009                 CRYPT_BIT_BLOB *blob;
2010
2011                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2012                 blob->cbData = dataLen - 1;
2013                 blob->cUnusedBits = *(pbEncoded + 1 +
2014                  GET_LEN_BYTES(pbEncoded[1]));
2015                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2016                 {
2017                     blob->pbData = (BYTE *)pbEncoded + 2 +
2018                      GET_LEN_BYTES(pbEncoded[1]);
2019                 }
2020                 else
2021                 {
2022                     assert(blob->pbData);
2023                     if (blob->cbData)
2024                     {
2025                         BYTE mask = 0xff << blob->cUnusedBits;
2026
2027                         memcpy(blob->pbData, pbEncoded + 2 +
2028                          GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2029                         blob->pbData[blob->cbData - 1] &= mask;
2030                     }
2031                 }
2032             }
2033         }
2034     }
2035     else
2036     {
2037         SetLastError(CRYPT_E_ASN1_BADTAG);
2038         ret = FALSE;
2039     }
2040     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2041     return ret;
2042 }
2043
2044 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2045  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2046  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2047 {
2048     BOOL ret;
2049
2050     TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2051      pDecodePara, pvStructInfo, pcbStructInfo);
2052
2053     __TRY
2054     {
2055         DWORD bytesNeeded;
2056
2057         if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2058          lpszStructType, pbEncoded, cbEncoded,
2059          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2060         {
2061             if (!pvStructInfo)
2062                 *pcbStructInfo = bytesNeeded;
2063             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2064              pvStructInfo, pcbStructInfo, bytesNeeded)))
2065             {
2066                 CRYPT_BIT_BLOB *blob;
2067
2068                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2069                     pvStructInfo = *(BYTE **)pvStructInfo;
2070                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2071                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2072                 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2073                  lpszStructType, pbEncoded, cbEncoded,
2074                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2075                  &bytesNeeded);
2076             }
2077         }
2078     }
2079     __EXCEPT_PAGE_FAULT
2080     {
2081         SetLastError(STATUS_ACCESS_VIOLATION);
2082         ret = FALSE;
2083     }
2084     __ENDTRY
2085     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2086     return ret;
2087 }
2088
2089 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2090  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2091  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2092 {
2093     BOOL ret;
2094
2095     if (!pvStructInfo)
2096     {
2097         *pcbStructInfo = sizeof(int);
2098         return TRUE;
2099     }
2100     __TRY
2101     {
2102         BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2103         CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2104         DWORD size = sizeof(buf);
2105
2106         blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2107         ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2108          X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2109         if (ret)
2110         {
2111             if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2112              pvStructInfo, pcbStructInfo, sizeof(int))))
2113             {
2114                 int val, i;
2115
2116                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2117                     pvStructInfo = *(BYTE **)pvStructInfo;
2118                 if (blob->pbData[blob->cbData - 1] & 0x80)
2119                 {
2120                     /* initialize to a negative value to sign-extend */
2121                     val = -1;
2122                 }
2123                 else
2124                     val = 0;
2125                 for (i = 0; i < blob->cbData; i++)
2126                 {
2127                     val <<= 8;
2128                     val |= blob->pbData[blob->cbData - i - 1];
2129                 }
2130                 memcpy(pvStructInfo, &val, sizeof(int));
2131             }
2132         }
2133         else if (GetLastError() == ERROR_MORE_DATA)
2134             SetLastError(CRYPT_E_ASN1_LARGE);
2135     }
2136     __EXCEPT_PAGE_FAULT
2137     {
2138         SetLastError(STATUS_ACCESS_VIOLATION);
2139         ret = FALSE;
2140     }
2141     __ENDTRY
2142     return ret;
2143 }
2144
2145 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2146  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2147  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2148 {
2149     BOOL ret;
2150
2151     if (pbEncoded[0] == ASN_INTEGER)
2152     {
2153         DWORD bytesNeeded, dataLen;
2154
2155         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2156         {
2157             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2158
2159             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2160             if (!pvStructInfo)
2161                 *pcbStructInfo = bytesNeeded;
2162             else if (*pcbStructInfo < bytesNeeded)
2163             {
2164                 *pcbStructInfo = bytesNeeded;
2165                 SetLastError(ERROR_MORE_DATA);
2166                 ret = FALSE;
2167             }
2168             else
2169             {
2170                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2171
2172                 blob->cbData = dataLen;
2173                 assert(blob->pbData);
2174                 if (blob->cbData)
2175                 {
2176                     DWORD i;
2177
2178                     for (i = 0; i < blob->cbData; i++)
2179                     {
2180                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2181                          dataLen - i - 1);
2182                     }
2183                 }
2184             }
2185         }
2186     }
2187     else
2188     {
2189         SetLastError(CRYPT_E_ASN1_BADTAG);
2190         ret = FALSE;
2191     }
2192     return ret;
2193 }
2194
2195 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2196  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2197  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2198 {
2199     BOOL ret;
2200
2201     __TRY
2202     {
2203         DWORD bytesNeeded;
2204
2205         if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2206          lpszStructType, pbEncoded, cbEncoded,
2207          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2208         {
2209             if (!pvStructInfo)
2210                 *pcbStructInfo = bytesNeeded;
2211             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2212              pvStructInfo, pcbStructInfo, bytesNeeded)))
2213             {
2214                 CRYPT_INTEGER_BLOB *blob;
2215
2216                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2217                     pvStructInfo = *(BYTE **)pvStructInfo;
2218                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2219                 blob->pbData = (BYTE *)pvStructInfo +
2220                  sizeof(CRYPT_INTEGER_BLOB);
2221                 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2222                  lpszStructType, pbEncoded, cbEncoded,
2223                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2224                  &bytesNeeded);
2225             }
2226         }
2227     }
2228     __EXCEPT_PAGE_FAULT
2229     {
2230         SetLastError(STATUS_ACCESS_VIOLATION);
2231         ret = FALSE;
2232     }
2233     __ENDTRY
2234     return ret;
2235 }
2236
2237 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2238  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2239  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2240  void *pvStructInfo, DWORD *pcbStructInfo)
2241 {
2242     BOOL ret;
2243
2244     if (pbEncoded[0] == ASN_INTEGER)
2245     {
2246         DWORD bytesNeeded, dataLen;
2247
2248         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2249         {
2250             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2251
2252             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2253             if (!pvStructInfo)
2254                 *pcbStructInfo = bytesNeeded;
2255             else if (*pcbStructInfo < bytesNeeded)
2256             {
2257                 *pcbStructInfo = bytesNeeded;
2258                 SetLastError(ERROR_MORE_DATA);
2259                 ret = FALSE;
2260             }
2261             else
2262             {
2263                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2264
2265                 blob->cbData = dataLen;
2266                 assert(blob->pbData);
2267                 /* remove leading zero byte if it exists */
2268                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2269                 {
2270                     blob->cbData--;
2271                     blob->pbData++;
2272                 }
2273                 if (blob->cbData)
2274                 {
2275                     DWORD i;
2276
2277                     for (i = 0; i < blob->cbData; i++)
2278                     {
2279                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2280                          dataLen - i - 1);
2281                     }
2282                 }
2283             }
2284         }
2285     }
2286     else
2287     {
2288         SetLastError(CRYPT_E_ASN1_BADTAG);
2289         ret = FALSE;
2290     }
2291     return ret;
2292 }
2293
2294 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2295  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2296  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2297 {
2298     BOOL ret;
2299
2300     __TRY
2301     {
2302         DWORD bytesNeeded;
2303
2304         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2305          lpszStructType, pbEncoded, cbEncoded,
2306          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2307         {
2308             if (!pvStructInfo)
2309                 *pcbStructInfo = bytesNeeded;
2310             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2311              pvStructInfo, pcbStructInfo, bytesNeeded)))
2312             {
2313                 CRYPT_INTEGER_BLOB *blob;
2314
2315                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2316                     pvStructInfo = *(BYTE **)pvStructInfo;
2317                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2318                 blob->pbData = (BYTE *)pvStructInfo +
2319                  sizeof(CRYPT_INTEGER_BLOB);
2320                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2321                  lpszStructType, pbEncoded, cbEncoded,
2322                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2323                  &bytesNeeded);
2324             }
2325         }
2326     }
2327     __EXCEPT_PAGE_FAULT
2328     {
2329         SetLastError(STATUS_ACCESS_VIOLATION);
2330         ret = FALSE;
2331     }
2332     __ENDTRY
2333     return ret;
2334 }
2335
2336 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2337  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2338  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2339 {
2340     BOOL ret;
2341
2342     if (!pvStructInfo)
2343     {
2344         *pcbStructInfo = sizeof(int);
2345         return TRUE;
2346     }
2347     __TRY
2348     {
2349         if (pbEncoded[0] == ASN_ENUMERATED)
2350         {
2351             unsigned int val = 0, i;
2352
2353             if (cbEncoded <= 1)
2354             {
2355                 SetLastError(CRYPT_E_ASN1_EOD);
2356                 ret = FALSE;
2357             }
2358             else if (pbEncoded[1] == 0)
2359             {
2360                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2361                 ret = FALSE;
2362             }
2363             else
2364             {
2365                 /* A little strange looking, but we have to accept a sign byte:
2366                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
2367                  * assuming a small length is okay here, it has to be in short
2368                  * form.
2369                  */
2370                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2371                 {
2372                     SetLastError(CRYPT_E_ASN1_LARGE);
2373                     return FALSE;
2374                 }
2375                 for (i = 0; i < pbEncoded[1]; i++)
2376                 {
2377                     val <<= 8;
2378                     val |= pbEncoded[2 + i];
2379                 }
2380                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2381                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2382                 {
2383                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2384                         pvStructInfo = *(BYTE **)pvStructInfo;
2385                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
2386                 }
2387             }
2388         }
2389         else
2390         {
2391             SetLastError(CRYPT_E_ASN1_BADTAG);
2392             ret = FALSE;
2393         }
2394     }
2395     __EXCEPT_PAGE_FAULT
2396     {
2397         SetLastError(STATUS_ACCESS_VIOLATION);
2398         ret = FALSE;
2399     }
2400     __ENDTRY
2401     return ret;
2402 }
2403
2404 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2405  * if it fails.
2406  */
2407 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2408  do { \
2409     BYTE i; \
2410  \
2411     (word) = 0; \
2412     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2413     { \
2414         if (!isdigit(*(pbEncoded))) \
2415         { \
2416             SetLastError(CRYPT_E_ASN1_CORRUPT); \
2417             ret = FALSE; \
2418         } \
2419         else \
2420         { \
2421             (word) *= 10; \
2422             (word) += *(pbEncoded)++ - '0'; \
2423         } \
2424     } \
2425  } while (0)
2426
2427 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2428  SYSTEMTIME *sysTime)
2429 {
2430     BOOL ret;
2431
2432     __TRY
2433     {
2434         ret = TRUE;
2435         if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2436         {
2437             WORD hours, minutes = 0;
2438             BYTE sign = *pbEncoded++;
2439
2440             len--;
2441             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2442             if (ret && hours >= 24)
2443             {
2444                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2445                 ret = FALSE;
2446             }
2447             else if (len >= 2)
2448             {
2449                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2450                 if (ret && minutes >= 60)
2451                 {
2452                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2453                     ret = FALSE;
2454                 }
2455             }
2456             if (ret)
2457             {
2458                 if (sign == '+')
2459                 {
2460                     sysTime->wHour += hours;
2461                     sysTime->wMinute += minutes;
2462                 }
2463                 else
2464                 {
2465                     if (hours > sysTime->wHour)
2466                     {
2467                         sysTime->wDay--;
2468                         sysTime->wHour = 24 - (hours - sysTime->wHour);
2469                     }
2470                     else
2471                         sysTime->wHour -= hours;
2472                     if (minutes > sysTime->wMinute)
2473                     {
2474                         sysTime->wHour--;
2475                         sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2476                     }
2477                     else
2478                         sysTime->wMinute -= minutes;
2479                 }
2480             }
2481         }
2482     }
2483     __EXCEPT_PAGE_FAULT
2484     {
2485         SetLastError(STATUS_ACCESS_VIOLATION);
2486         ret = FALSE;
2487     }
2488     __ENDTRY
2489     return ret;
2490 }
2491
2492 #define MIN_ENCODED_TIME_LENGTH 10
2493
2494 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2495  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2496  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2497 {
2498     BOOL ret;
2499
2500     if (!pvStructInfo)
2501     {
2502         *pcbStructInfo = sizeof(FILETIME);
2503         return TRUE;
2504     }
2505     __TRY
2506     {
2507         ret = TRUE;
2508         if (pbEncoded[0] == ASN_UTCTIME)
2509         {
2510             if (cbEncoded <= 1)
2511             {
2512                 SetLastError(CRYPT_E_ASN1_EOD);
2513                 ret = FALSE;
2514             }
2515             else if (pbEncoded[1] > 0x7f)
2516             {
2517                 /* long-form date strings really can't be valid */
2518                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2519                 ret = FALSE;
2520             }
2521             else
2522             {
2523                 SYSTEMTIME sysTime = { 0 };
2524                 BYTE len = pbEncoded[1];
2525
2526                 if (len < MIN_ENCODED_TIME_LENGTH)
2527                 {
2528                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2529                     ret = FALSE;
2530                 }
2531                 else
2532                 {
2533                     pbEncoded += 2;
2534                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2535                     if (sysTime.wYear >= 50)
2536                         sysTime.wYear += 1900;
2537                     else
2538                         sysTime.wYear += 2000;
2539                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2540                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2541                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2542                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2543                     if (ret && len > 0)
2544                     {
2545                         if (len >= 2 && isdigit(*pbEncoded) &&
2546                          isdigit(*(pbEncoded + 1)))
2547                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2548                              sysTime.wSecond);
2549                         else if (isdigit(*pbEncoded))
2550                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2551                              sysTime.wSecond);
2552                         if (ret)
2553                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2554                              &sysTime);
2555                     }
2556                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2557                      pDecodePara, pvStructInfo, pcbStructInfo,
2558                      sizeof(FILETIME))))
2559                     {
2560                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2561                             pvStructInfo = *(BYTE **)pvStructInfo;
2562                         ret = SystemTimeToFileTime(&sysTime,
2563                          (FILETIME *)pvStructInfo);
2564                     }
2565                 }
2566             }
2567         }
2568         else
2569         {
2570             SetLastError(CRYPT_E_ASN1_BADTAG);
2571             ret = FALSE;
2572         }
2573     }
2574     __EXCEPT_PAGE_FAULT
2575     {
2576         SetLastError(STATUS_ACCESS_VIOLATION);
2577         ret = FALSE;
2578     }
2579     __ENDTRY
2580     return ret;
2581 }
2582
2583 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2584  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2585  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2586 {
2587     BOOL ret;
2588
2589     if (!pvStructInfo)
2590     {
2591         *pcbStructInfo = sizeof(FILETIME);
2592         return TRUE;
2593     }
2594     __TRY
2595     {
2596         ret = TRUE;
2597         if (pbEncoded[0] == ASN_GENERALTIME)
2598         {
2599             if (cbEncoded <= 1)
2600             {
2601                 SetLastError(CRYPT_E_ASN1_EOD);
2602                 ret = FALSE;
2603             }
2604             else if (pbEncoded[1] > 0x7f)
2605             {
2606                 /* long-form date strings really can't be valid */
2607                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2608                 ret = FALSE;
2609             }
2610             else
2611             {
2612                 BYTE len = pbEncoded[1];
2613
2614                 if (len < MIN_ENCODED_TIME_LENGTH)
2615                 {
2616                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2617                     ret = FALSE;
2618                 }
2619                 else
2620                 {
2621                     SYSTEMTIME sysTime = { 0 };
2622
2623                     pbEncoded += 2;
2624                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2625                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2626                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2627                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2628                     if (ret && len > 0)
2629                     {
2630                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2631                          sysTime.wMinute);
2632                         if (ret && len > 0)
2633                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2634                              sysTime.wSecond);
2635                         if (ret && len > 0 && (*pbEncoded == '.' ||
2636                          *pbEncoded == ','))
2637                         {
2638                             BYTE digits;
2639
2640                             pbEncoded++;
2641                             len--;
2642                             /* workaround macro weirdness */
2643                             digits = min(len, 3);
2644                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2645                              sysTime.wMilliseconds);
2646                         }
2647                         if (ret)
2648                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2649                              &sysTime);
2650                     }
2651                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2652                      pDecodePara, pvStructInfo, pcbStructInfo,
2653                      sizeof(FILETIME))))
2654                     {
2655                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2656                             pvStructInfo = *(BYTE **)pvStructInfo;
2657                         ret = SystemTimeToFileTime(&sysTime,
2658                          (FILETIME *)pvStructInfo);
2659                     }
2660                 }
2661             }
2662         }
2663         else
2664         {
2665             SetLastError(CRYPT_E_ASN1_BADTAG);
2666             ret = FALSE;
2667         }
2668     }
2669     __EXCEPT_PAGE_FAULT
2670     {
2671         SetLastError(STATUS_ACCESS_VIOLATION);
2672         ret = FALSE;
2673     }
2674     __ENDTRY
2675     return ret;
2676 }
2677
2678 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
2679  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2680  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2681 {
2682     BOOL ret;
2683
2684     __TRY
2685     {
2686         if (pbEncoded[0] == ASN_UTCTIME)
2687             ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
2688              pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2689              pcbStructInfo);
2690         else if (pbEncoded[0] == ASN_GENERALTIME)
2691             ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
2692              lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
2693              pvStructInfo, pcbStructInfo);
2694         else
2695         {
2696             SetLastError(CRYPT_E_ASN1_BADTAG);
2697             ret = FALSE;
2698         }
2699     }
2700     __EXCEPT_PAGE_FAULT
2701     {
2702         SetLastError(STATUS_ACCESS_VIOLATION);
2703         ret = FALSE;
2704     }
2705     __ENDTRY
2706     return ret;
2707 }
2708
2709 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
2710  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2711  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2712 {
2713     BOOL ret = TRUE;
2714
2715     __TRY
2716     {
2717         if (pbEncoded[0] == ASN_SEQUENCEOF)
2718         {
2719             DWORD bytesNeeded, dataLen, remainingLen, cValue;
2720
2721             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2722             {
2723                 BYTE lenBytes;
2724                 const BYTE *ptr;
2725
2726                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2727                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
2728                 cValue = 0;
2729                 ptr = pbEncoded + 1 + lenBytes;
2730                 remainingLen = dataLen;
2731                 while (ret && remainingLen)
2732                 {
2733                     DWORD nextLen;
2734
2735                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2736                     if (ret)
2737                     {
2738                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2739
2740                         remainingLen -= 1 + nextLenBytes + nextLen;
2741                         ptr += 1 + nextLenBytes + nextLen;
2742                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
2743                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2744                             bytesNeeded += 1 + nextLenBytes + nextLen;
2745                         cValue++;
2746                     }
2747                 }
2748                 if (ret)
2749                 {
2750                     CRYPT_SEQUENCE_OF_ANY *seq;
2751                     BYTE *nextPtr;
2752                     DWORD i;
2753
2754                     if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2755                      pvStructInfo, pcbStructInfo, bytesNeeded)))
2756                     {
2757                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2758                             pvStructInfo = *(BYTE **)pvStructInfo;
2759                         seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2760                         seq->cValue = cValue;
2761                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
2762                          sizeof(*seq));
2763                         nextPtr = (BYTE *)seq->rgValue +
2764                          cValue * sizeof(CRYPT_DER_BLOB);
2765                         ptr = pbEncoded + 1 + lenBytes;
2766                         remainingLen = dataLen;
2767                         i = 0;
2768                         while (ret && remainingLen)
2769                         {
2770                             DWORD nextLen;
2771
2772                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2773                             if (ret)
2774                             {
2775                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2776
2777                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
2778                                  nextLen;
2779                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2780                                     seq->rgValue[i].pbData = (BYTE *)ptr;
2781                                 else
2782                                 {
2783                                     seq->rgValue[i].pbData = nextPtr;
2784                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
2785                                      nextLen);
2786                                     nextPtr += 1 + nextLenBytes + nextLen;
2787                                 }
2788                                 remainingLen -= 1 + nextLenBytes + nextLen;
2789                                 ptr += 1 + nextLenBytes + nextLen;
2790                                 i++;
2791                             }
2792                         }
2793                     }
2794                 }
2795             }
2796         }
2797         else
2798         {
2799             SetLastError(CRYPT_E_ASN1_BADTAG);
2800             return FALSE;
2801         }
2802     }
2803     __EXCEPT_PAGE_FAULT
2804     {
2805         SetLastError(STATUS_ACCESS_VIOLATION);
2806         ret = FALSE;
2807     }
2808     __ENDTRY
2809     return ret;
2810 }
2811
2812 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
2813  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2814  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2815 {
2816     struct AsnDecodeSequenceItem items[] = {
2817      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
2818        DistPointName), CRYPT_AsnDecodeAltNameInternal,
2819        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
2820        DistPointName.u.FullName.rgAltEntry), 0 },
2821      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
2822        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
2823        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
2824      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
2825        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
2826        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
2827     };
2828     BOOL ret;
2829
2830     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2831      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2832      dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2833     return ret;
2834 }
2835
2836 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
2837  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2838  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2839 {
2840     BOOL ret;
2841
2842     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2843      pDecodePara, pvStructInfo, *pcbStructInfo);
2844
2845     __TRY
2846     {
2847         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2848          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
2849          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
2850
2851         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2852          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2853     }
2854     __EXCEPT_PAGE_FAULT
2855     {
2856         SetLastError(STATUS_ACCESS_VIOLATION);
2857         ret = FALSE;
2858     }
2859     __ENDTRY
2860     return ret;
2861 }
2862
2863 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2864  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2865  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2866 {
2867     BOOL ret;
2868
2869     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2870      pDecodePara, pvStructInfo, *pcbStructInfo);
2871
2872     __TRY
2873     {
2874         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2875          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2876
2877         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2878          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2879     }
2880     __EXCEPT_PAGE_FAULT
2881     {
2882         SetLastError(STATUS_ACCESS_VIOLATION);
2883         ret = FALSE;
2884     }
2885     __ENDTRY
2886     return ret;
2887 }
2888
2889 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2890  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2891  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2892 {
2893     static HCRYPTOIDFUNCSET set = NULL;
2894     BOOL ret = FALSE;
2895     CryptDecodeObjectExFunc decodeFunc = NULL;
2896     HCRYPTOIDFUNCADDR hFunc = NULL;
2897
2898     TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
2899      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
2900      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
2901
2902     if (!pvStructInfo && !pcbStructInfo)
2903     {
2904         SetLastError(ERROR_INVALID_PARAMETER);
2905         return FALSE;
2906     }
2907     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2908      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2909     {
2910         SetLastError(ERROR_FILE_NOT_FOUND);
2911         return FALSE;
2912     }
2913     if (!cbEncoded)
2914     {
2915         SetLastError(CRYPT_E_ASN1_EOD);
2916         return FALSE;
2917     }
2918     if (cbEncoded > MAX_ENCODED_LEN)
2919     {
2920         SetLastError(CRYPT_E_ASN1_LARGE);
2921         return FALSE;
2922     }
2923
2924     SetLastError(NOERROR);
2925     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
2926         *(BYTE **)pvStructInfo = NULL;
2927     if (!HIWORD(lpszStructType))
2928     {
2929         switch (LOWORD(lpszStructType))
2930         {
2931         case (WORD)X509_CERT:
2932             decodeFunc = CRYPT_AsnDecodeCert;
2933             break;
2934         case (WORD)X509_CERT_TO_BE_SIGNED:
2935             decodeFunc = CRYPT_AsnDecodeCertInfo;
2936             break;
2937         case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2938             decodeFunc = CRYPT_AsnDecodeCRLInfo;
2939             break;
2940         case (WORD)X509_EXTENSIONS:
2941             decodeFunc = CRYPT_AsnDecodeExtensions;
2942             break;
2943         case (WORD)X509_NAME:
2944             decodeFunc = CRYPT_AsnDecodeName;
2945             break;
2946         case (WORD)X509_PUBLIC_KEY_INFO:
2947             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
2948             break;
2949         case (WORD)X509_ALTERNATE_NAME:
2950             decodeFunc = CRYPT_AsnDecodeAltName;
2951             break;
2952         case (WORD)X509_BASIC_CONSTRAINTS:
2953             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
2954             break;
2955         case (WORD)X509_BASIC_CONSTRAINTS2:
2956             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
2957             break;
2958         case (WORD)RSA_CSP_PUBLICKEYBLOB:
2959             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
2960             break;
2961         case (WORD)X509_OCTET_STRING:
2962             decodeFunc = CRYPT_AsnDecodeOctets;
2963             break;
2964         case (WORD)X509_BITS:
2965         case (WORD)X509_KEY_USAGE:
2966             decodeFunc = CRYPT_AsnDecodeBits;
2967             break;
2968         case (WORD)X509_INTEGER:
2969             decodeFunc = CRYPT_AsnDecodeInt;
2970             break;
2971         case (WORD)X509_MULTI_BYTE_INTEGER:
2972             decodeFunc = CRYPT_AsnDecodeInteger;
2973             break;
2974         case (WORD)X509_MULTI_BYTE_UINT:
2975             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
2976             break;
2977         case (WORD)X509_ENUMERATED:
2978             decodeFunc = CRYPT_AsnDecodeEnumerated;
2979             break;
2980         case (WORD)X509_CHOICE_OF_TIME:
2981             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
2982             break;
2983         case (WORD)X509_SEQUENCE_OF_ANY:
2984             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
2985             break;
2986         case (WORD)PKCS_UTC_TIME:
2987             decodeFunc = CRYPT_AsnDecodeUtcTime;
2988             break;
2989         case (WORD)X509_CRL_DIST_POINTS:
2990             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
2991             break;
2992         case (WORD)X509_ENHANCED_KEY_USAGE:
2993             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
2994             break;
2995         default:
2996             FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
2997         }
2998     }
2999     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3000         decodeFunc = CRYPT_AsnDecodeExtensions;
3001     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3002         decodeFunc = CRYPT_AsnDecodeUtcTime;
3003     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3004         decodeFunc = CRYPT_AsnDecodeEnumerated;
3005     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3006         decodeFunc = CRYPT_AsnDecodeBits;
3007     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3008         decodeFunc = CRYPT_AsnDecodeOctets;
3009     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3010         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3011     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3012         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3013     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3014         decodeFunc = CRYPT_AsnDecodeAltName;
3015     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3016         decodeFunc = CRYPT_AsnDecodeAltName;
3017     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3018         decodeFunc = CRYPT_AsnDecodeAltName;
3019     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3020         decodeFunc = CRYPT_AsnDecodeAltName;
3021     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3022         decodeFunc = CRYPT_AsnDecodeAltName;
3023     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3024         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3025     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3026         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3027     else
3028         TRACE("OID %s not found or unimplemented, looking for DLL\n",
3029          debugstr_a(lpszStructType));
3030     if (!decodeFunc)
3031     {
3032         if (!set)
3033             set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3034         CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3035          (void **)&decodeFunc, &hFunc);
3036     }
3037     if (decodeFunc)
3038         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3039          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3040     else
3041         SetLastError(ERROR_FILE_NOT_FOUND);
3042     if (hFunc)
3043         CryptFreeOIDFunctionAddress(hFunc, 0);
3044     return ret;
3045 }