ntdll: On Solaris, limits.h is required for PATH_MAX.
[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          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
961            CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
962            offsetof(CRL_INFO, rgExtension), 0 },
963         };
964
965         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
966          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
967          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
968     }
969     __EXCEPT_PAGE_FAULT
970     {
971         SetLastError(STATUS_ACCESS_VIOLATION);
972         ret = FALSE;
973     }
974     __ENDTRY
975
976     TRACE("Returning %d (%08lx)\n", ret, GetLastError());
977     return ret;
978 }
979
980 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
981  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
982  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
983 {
984     BOOL ret = TRUE;
985
986     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
987      pDecodePara, pvStructInfo, *pcbStructInfo);
988
989     if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
990     {
991         DWORD dataLen;
992
993         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
994         {
995             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
996             DWORD bytesNeeded = sizeof(LPSTR);
997
998             if (dataLen)
999             {
1000                 /* The largest possible string for the first two components
1001                  * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1002                  */
1003                 char firstTwo[6];
1004                 const BYTE *ptr;
1005
1006                 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1007                  pbEncoded[1 + lenBytes] / 40,
1008                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1009                  * 40);
1010                 bytesNeeded += strlen(firstTwo) + 1;
1011                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1012                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
1013                 {
1014                     /* large enough for ".4000000" */
1015                     char str[9];
1016                     int val = 0;
1017
1018                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1019                      (*ptr & 0x80))
1020                     {
1021                         val <<= 7;
1022                         val |= *ptr & 0x7f;
1023                         ptr++;
1024                     }
1025                     if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1026                      (*ptr & 0x80))
1027                     {
1028                         SetLastError(CRYPT_E_ASN1_CORRUPT);
1029                         ret = FALSE;
1030                     }
1031                     else
1032                     {
1033                         val <<= 7;
1034                         val |= *ptr++;
1035                         snprintf(str, sizeof(str), ".%d", val);
1036                         bytesNeeded += strlen(str);
1037                     }
1038                 }
1039             }
1040             if (!pvStructInfo)
1041                 *pcbStructInfo = bytesNeeded;
1042             else if (*pcbStructInfo < bytesNeeded)
1043             {
1044                 *pcbStructInfo = bytesNeeded;
1045                 SetLastError(ERROR_MORE_DATA);
1046                 ret = FALSE;
1047             }
1048             else
1049             {
1050                 if (dataLen)
1051                 {
1052                     const BYTE *ptr;
1053                     LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1054
1055                     *pszObjId = 0;
1056                     sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1057                      pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1058                      40) * 40);
1059                     pszObjId += strlen(pszObjId);
1060                     for (ptr = pbEncoded + 2 + lenBytes; ret &&
1061                      ptr - pbEncoded - 1 - lenBytes < dataLen; )
1062                     {
1063                         int val = 0;
1064
1065                         while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1066                          (*ptr & 0x80))
1067                         {
1068                             val <<= 7;
1069                             val |= *ptr & 0x7f;
1070                             ptr++;
1071                         }
1072                         val <<= 7;
1073                         val |= *ptr++;
1074                         sprintf(pszObjId, ".%d", val);
1075                         pszObjId += strlen(pszObjId);
1076                     }
1077                 }
1078                 else
1079                     *(LPSTR *)pvStructInfo = NULL;
1080                 *pcbStructInfo = bytesNeeded;
1081             }
1082         }
1083     }
1084     return ret;
1085 }
1086
1087 /* Warning:  assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1088  * ahead of time!
1089  */
1090 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1091  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1092  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1093 {
1094     struct AsnDecodeSequenceItem items[] = {
1095      { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1096        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1097        offsetof(CERT_EXTENSION, pszObjId), 0 },
1098      { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1099        sizeof(BOOL), TRUE, FALSE, 0, 0 },
1100      { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1101        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1102        offsetof(CERT_EXTENSION, Value.pbData) },
1103     };
1104     BOOL ret = TRUE;
1105     PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1106
1107     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1108      *pcbStructInfo);
1109
1110     if (ext)
1111         TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1112     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1113      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1114      ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1115     if (ext)
1116         TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1117          debugstr_a(ext->pszObjId));
1118     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1119     return ret;
1120 }
1121
1122 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1123  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1124  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1125 {
1126     BOOL ret = TRUE;
1127     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1128      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1129      offsetof(CERT_EXTENSION, pszObjId) };
1130     PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1131
1132     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1133      pDecodePara, pvStructInfo, *pcbStructInfo);
1134
1135     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1136      pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1137     return ret;
1138 }
1139
1140 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1141  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1142  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1143 {
1144     BOOL ret = TRUE;
1145
1146     __TRY
1147     {
1148         ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1149          lpszStructType, pbEncoded, cbEncoded,
1150          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1151         if (ret && pvStructInfo)
1152         {
1153             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1154              pcbStructInfo, *pcbStructInfo);
1155             if (ret)
1156             {
1157                 CERT_EXTENSIONS *exts;
1158
1159                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1160                     pvStructInfo = *(BYTE **)pvStructInfo;
1161                 exts = (CERT_EXTENSIONS *)pvStructInfo;
1162                 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1163                  sizeof(CERT_EXTENSIONS));
1164                 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1165                  lpszStructType, pbEncoded, cbEncoded,
1166                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1167                  pcbStructInfo);
1168             }
1169         }
1170     }
1171     __EXCEPT_PAGE_FAULT
1172     {
1173         SetLastError(STATUS_ACCESS_VIOLATION);
1174         ret = FALSE;
1175     }
1176     __ENDTRY
1177     return ret;
1178 }
1179
1180 /* Warning: this assumes the address of value->Value.pbData is already set, in
1181  * order to avoid overwriting memory.  (In some cases, it may change it, if it
1182  * doesn't copy anything to memory.)  Be sure to set it correctly!
1183  */
1184 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1185  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1186  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1187 {
1188     BOOL ret = TRUE;
1189     DWORD dataLen;
1190     CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1191
1192     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1193     {
1194         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1195
1196         switch (pbEncoded[0])
1197         {
1198         case ASN_NUMERICSTRING:
1199         case ASN_PRINTABLESTRING:
1200         case ASN_IA5STRING:
1201         case ASN_T61STRING:
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             case ASN_T61STRING:
1218                 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1219                     bytesNeeded += dataLen;
1220                 break;
1221             }
1222             if (!value)
1223                 *pcbStructInfo = bytesNeeded;
1224             else if (*pcbStructInfo < bytesNeeded)
1225             {
1226                 *pcbStructInfo = bytesNeeded;
1227                 SetLastError(ERROR_MORE_DATA);
1228                 ret = FALSE;
1229             }
1230             else
1231             {
1232                 *pcbStructInfo = bytesNeeded;
1233                 switch (pbEncoded[0])
1234                 {
1235                 case ASN_NUMERICSTRING:
1236                     value->dwValueType = CERT_RDN_NUMERIC_STRING;
1237                     break;
1238                 case ASN_PRINTABLESTRING:
1239                     value->dwValueType = CERT_RDN_PRINTABLE_STRING;
1240                     break;
1241                 case ASN_IA5STRING:
1242                     value->dwValueType = CERT_RDN_IA5_STRING;
1243                     break;
1244                 case ASN_T61STRING:
1245                     value->dwValueType = CERT_RDN_T61_STRING;
1246                     break;
1247                 }
1248                 if (dataLen)
1249                 {
1250                     switch (pbEncoded[0])
1251                     {
1252                     case ASN_NUMERICSTRING:
1253                     case ASN_PRINTABLESTRING:
1254                     case ASN_IA5STRING:
1255                     case ASN_T61STRING:
1256                         value->Value.cbData = dataLen;
1257                         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1258                             value->Value.pbData = (BYTE *)pbEncoded + 1 +
1259                              lenBytes;
1260                         else
1261                         {
1262                             assert(value->Value.pbData);
1263                             memcpy(value->Value.pbData,
1264                              pbEncoded + 1 + lenBytes, dataLen);
1265                         }
1266                         break;
1267                     }
1268                 }
1269                 else
1270                 {
1271                     value->Value.cbData = 0;
1272                     value->Value.pbData = NULL;
1273                 }
1274             }
1275         }
1276     }
1277     return ret;
1278 }
1279
1280 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1281  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1282  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1283 {
1284     BOOL ret = TRUE;
1285
1286     __TRY
1287     {
1288         ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1289          lpszStructType, pbEncoded, cbEncoded,
1290          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1291         if (ret && pvStructInfo)
1292         {
1293             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1294              pcbStructInfo, *pcbStructInfo);
1295             if (ret)
1296             {
1297                 CERT_NAME_VALUE *value;
1298
1299                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1300                     pvStructInfo = *(BYTE **)pvStructInfo;
1301                 value = (CERT_NAME_VALUE *)pvStructInfo;
1302                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1303                 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1304                  lpszStructType, pbEncoded, cbEncoded,
1305                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1306                  pcbStructInfo);
1307             }
1308         }
1309     }
1310     __EXCEPT_PAGE_FAULT
1311     {
1312         SetLastError(STATUS_ACCESS_VIOLATION);
1313         ret = FALSE;
1314     }
1315     __ENDTRY
1316     return ret;
1317 }
1318
1319 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1320  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1321  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1322 {
1323     BOOL ret;
1324     struct AsnDecodeSequenceItem items[] = {
1325      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1326        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1327        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1328      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1329        CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1330        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1331     };
1332     CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1333
1334     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1335      pvStructInfo, *pcbStructInfo);
1336
1337     if (attr)
1338         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1339     ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1340      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1341      attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1342     if (attr)
1343     {
1344         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1345          debugstr_a(attr->pszObjId));
1346         TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1347     }
1348     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1349     return ret;
1350 }
1351
1352 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1353  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1354  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1355 {
1356     BOOL ret = TRUE;
1357     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1358      CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1359      offsetof(CERT_RDN_ATTR, pszObjId) };
1360     PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1361
1362     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1363      pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1364     return ret;
1365 }
1366
1367 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1368  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1369  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1370 {
1371     BOOL ret = TRUE;
1372
1373     __TRY
1374     {
1375         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1376          CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1377          offsetof(CERT_RDN, rgRDNAttr) };
1378
1379         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1380          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1381     }
1382     __EXCEPT_PAGE_FAULT
1383     {
1384         SetLastError(STATUS_ACCESS_VIOLATION);
1385         ret = FALSE;
1386     }
1387     __ENDTRY
1388     return ret;
1389 }
1390
1391 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1392  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1393  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1394 {
1395     BOOL ret = TRUE;
1396     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1397
1398     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1399      pDecodePara, pvStructInfo, *pcbStructInfo);
1400
1401     if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1402         bytesNeeded += cbEncoded;
1403     if (!pvStructInfo)
1404         *pcbStructInfo = bytesNeeded;
1405     else if (*pcbStructInfo < bytesNeeded)
1406     {
1407         SetLastError(ERROR_MORE_DATA);
1408         *pcbStructInfo = bytesNeeded;
1409         ret = FALSE;
1410     }
1411     else
1412     {
1413         PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1414
1415         *pcbStructInfo = bytesNeeded;
1416         blob->cbData = cbEncoded;
1417         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1418             blob->pbData = (LPBYTE)pbEncoded;
1419         else
1420         {
1421             assert(blob->pbData);
1422             memcpy(blob->pbData, pbEncoded, blob->cbData);
1423         }
1424     }
1425     return ret;
1426 }
1427
1428 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1429  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1430  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1431 {
1432     CRYPT_ALGORITHM_IDENTIFIER *algo =
1433      (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1434     BOOL ret = TRUE;
1435     struct AsnDecodeSequenceItem items[] = {
1436      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1437        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE, 
1438        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1439      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1440        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
1441        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1442     };
1443
1444     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1445      pDecodePara, pvStructInfo, *pcbStructInfo);
1446
1447     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1448      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1449      pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1450     if (ret && pvStructInfo)
1451     {
1452         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1453          debugstr_a(algo->pszObjId));
1454     }
1455     return ret;
1456 }
1457
1458 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1459  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1460  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1461 {
1462     BOOL ret = TRUE;
1463     struct AsnDecodeSequenceItem items[] = {
1464      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1465        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1466        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1467        Algorithm.pszObjId) },
1468      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1469        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1470        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1471     };
1472     PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1473
1474     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1475      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1476      pDecodePara, pvStructInfo, pcbStructInfo, info ?
1477      info->Algorithm.Parameters.pbData : NULL);
1478     return ret;
1479 }
1480
1481 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1482  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1483  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1484 {
1485     BOOL ret = TRUE;
1486
1487     __TRY
1488     {
1489         DWORD bytesNeeded;
1490
1491         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1492          lpszStructType, pbEncoded, cbEncoded,
1493          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1494         {
1495             if (!pvStructInfo)
1496                 *pcbStructInfo = bytesNeeded;
1497             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1498              pvStructInfo, pcbStructInfo, bytesNeeded)))
1499             {
1500                 PCERT_PUBLIC_KEY_INFO info;
1501
1502                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1503                     pvStructInfo = *(BYTE **)pvStructInfo;
1504                 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1505                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1506                  sizeof(CERT_PUBLIC_KEY_INFO);
1507                 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1508                  lpszStructType, pbEncoded, cbEncoded,
1509                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1510                  &bytesNeeded);
1511             }
1512         }
1513     }
1514     __EXCEPT_PAGE_FAULT
1515     {
1516         SetLastError(STATUS_ACCESS_VIOLATION);
1517         ret = FALSE;
1518     }
1519     __ENDTRY
1520     return ret;
1521 }
1522
1523 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1524  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1525  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1526 {
1527     BOOL ret;
1528
1529     if (cbEncoded < 3)
1530     {
1531         SetLastError(CRYPT_E_ASN1_CORRUPT);
1532         return FALSE;
1533     }
1534     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1535     {
1536         SetLastError(CRYPT_E_ASN1_CORRUPT);
1537         return FALSE;
1538     }
1539     if (pbEncoded[1] > 1)
1540     {
1541         SetLastError(CRYPT_E_ASN1_CORRUPT);
1542         return FALSE;
1543     }
1544     if (!pvStructInfo)
1545     {
1546         *pcbStructInfo = sizeof(BOOL);
1547         ret = TRUE;
1548     }
1549     else if (*pcbStructInfo < sizeof(BOOL))
1550     {
1551         *pcbStructInfo = sizeof(BOOL);
1552         SetLastError(ERROR_MORE_DATA);
1553         ret = FALSE;
1554     }
1555     else
1556     {
1557         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1558         ret = TRUE;
1559     }
1560     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1561     return ret;
1562 }
1563
1564 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1565  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1566  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1567 {
1568     PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1569     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1570     BOOL ret;
1571
1572     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1573      pDecodePara, pvStructInfo, *pcbStructInfo);
1574
1575     if (cbEncoded < 2)
1576     {
1577         SetLastError(CRYPT_E_ASN1_CORRUPT);
1578         return FALSE;
1579     }
1580     if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1581     {
1582         SetLastError(CRYPT_E_ASN1_BADTAG);
1583         return FALSE;
1584     }
1585     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1586     if (1 + lenBytes > cbEncoded)
1587     {
1588         SetLastError(CRYPT_E_ASN1_CORRUPT);
1589         return FALSE;
1590     }
1591     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1592     {
1593         switch (pbEncoded[0] & ASN_TYPE_MASK)
1594         {
1595         case 1: /* rfc822Name */
1596         case 2: /* dNSName */
1597         case 6: /* uniformResourceIdentifier */
1598             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1599             break;
1600         case 7: /* iPAddress */
1601             bytesNeeded += dataLen;
1602             break;
1603         case 8: /* registeredID */
1604             /* FIXME: decode as OID */
1605         case 0: /* otherName */
1606         case 4: /* directoryName */
1607             FIXME("stub\n");
1608             SetLastError(CRYPT_E_ASN1_BADTAG);
1609             ret = FALSE;
1610             break;
1611         case 3: /* x400Address, unimplemented */
1612         case 5: /* ediPartyName, unimplemented */
1613             SetLastError(CRYPT_E_ASN1_BADTAG);
1614             ret = FALSE;
1615             break;
1616         default:
1617             SetLastError(CRYPT_E_ASN1_CORRUPT);
1618             ret = FALSE;
1619         }
1620         if (ret)
1621         {
1622             if (!entry)
1623                 *pcbStructInfo = bytesNeeded;
1624             else if (*pcbStructInfo < bytesNeeded)
1625             {
1626                 *pcbStructInfo = bytesNeeded;
1627                 SetLastError(ERROR_MORE_DATA);
1628                 ret = FALSE;
1629             }
1630             else
1631             {
1632                 *pcbStructInfo = bytesNeeded;
1633                 /* MS used values one greater than the asn1 ones.. sigh */
1634                 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1635                 switch (pbEncoded[0] & ASN_TYPE_MASK)
1636                 {
1637                 case 1: /* rfc822Name */
1638                 case 2: /* dNSName */
1639                 case 6: /* uniformResourceIdentifier */
1640                 {
1641                     DWORD i;
1642
1643                     for (i = 0; i < dataLen; i++)
1644                         entry->u.pwszURL[i] =
1645                          (WCHAR)pbEncoded[1 + lenBytes + i];
1646                     entry->u.pwszURL[i] = 0;
1647                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1648                      debugstr_w(entry->u.pwszURL));
1649                     break;
1650                 }
1651                 case 7: /* iPAddress */
1652                     /* The next data pointer is in the pwszURL spot, that is,
1653                      * the first 4 bytes.  Need to move it to the next spot.
1654                      */
1655                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1656                     entry->u.IPAddress.cbData = dataLen;
1657                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1658                      dataLen);
1659                     break;
1660                 }
1661             }
1662         }
1663     }
1664     return ret;
1665 }
1666
1667 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1668  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1669  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1670 {
1671     BOOL ret = TRUE;
1672     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1673      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1674      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1675     PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1676
1677     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1678      pDecodePara, pvStructInfo, *pcbStructInfo);
1679
1680     if (info)
1681         TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1682     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1683      pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1684     return ret;
1685 }
1686
1687 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1688  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1689  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1690 {
1691     BOOL ret = TRUE;
1692
1693     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1694      pDecodePara, pvStructInfo, *pcbStructInfo);
1695
1696     __TRY
1697     {
1698         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1699          CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1700          offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1701
1702         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1703          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1704     }
1705     __EXCEPT_PAGE_FAULT
1706     {
1707         SetLastError(STATUS_ACCESS_VIOLATION);
1708         ret = FALSE;
1709     }
1710     __ENDTRY
1711     return ret;
1712 }
1713
1714 struct PATH_LEN_CONSTRAINT
1715 {
1716     BOOL  fPathLenConstraint;
1717     DWORD dwPathLenConstraint;
1718 };
1719
1720 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
1721  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1722  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1723 {
1724     BOOL ret = TRUE;
1725
1726     TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1727      pvStructInfo, *pcbStructInfo);
1728
1729     if (cbEncoded)
1730     {
1731         if (pbEncoded[0] == ASN_INTEGER)
1732         {
1733             DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
1734
1735             if (!pvStructInfo)
1736                 *pcbStructInfo = bytesNeeded;
1737             else if (*pcbStructInfo < bytesNeeded)
1738             {
1739                 SetLastError(ERROR_MORE_DATA);
1740                 *pcbStructInfo = bytesNeeded;
1741                 ret = FALSE;
1742             }
1743             else
1744             {
1745                 struct PATH_LEN_CONSTRAINT *constraint =
1746                  (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
1747                 DWORD size = sizeof(constraint->dwPathLenConstraint);
1748
1749                 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
1750                  pbEncoded, cbEncoded, 0, NULL,
1751                  &constraint->dwPathLenConstraint, &size);
1752                 if (ret)
1753                     constraint->fPathLenConstraint = TRUE;
1754                 TRACE("got an int, dwPathLenConstraint is %ld\n",
1755                  constraint->dwPathLenConstraint);
1756             }
1757         }
1758         else
1759         {
1760             SetLastError(CRYPT_E_ASN1_CORRUPT);
1761             ret = FALSE;
1762         }
1763     }
1764     TRACE("returning %d (%08lx)\n", ret, GetLastError());
1765     return ret;
1766 }
1767
1768 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
1769  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1770  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1771 {
1772     BOOL ret;
1773     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1774      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
1775      offsetof(CERT_NAME_BLOB, pbData) };
1776     struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1777
1778     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1779      pDecodePara, pvStructInfo, *pcbStructInfo);
1780
1781     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1782      pDecodePara, pvStructInfo, pcbStructInfo,
1783      entries ? entries->rgItems : NULL);
1784     TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1785     return ret;
1786 }
1787
1788 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
1789  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1790  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1791 {
1792     BOOL ret;
1793
1794     __TRY
1795     {
1796         struct AsnDecodeSequenceItem items[] = {
1797          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
1798            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
1799            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
1800          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1801            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1802            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1803          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1804            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
1805            sizeof(struct GenericArray), TRUE, TRUE,
1806            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
1807         };
1808
1809         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1810          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1811          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1812     }
1813     __EXCEPT_PAGE_FAULT
1814     {
1815         SetLastError(STATUS_ACCESS_VIOLATION);
1816         ret = FALSE;
1817     }
1818     __ENDTRY
1819     return ret;
1820 }
1821
1822 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
1823  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1824  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1825 {
1826     BOOL ret;
1827
1828     __TRY
1829     {
1830         struct AsnDecodeSequenceItem items[] = {
1831          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
1832            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
1833          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
1834            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1835            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1836         };
1837
1838         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1839          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1840          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1841     }
1842     __EXCEPT_PAGE_FAULT
1843     {
1844         SetLastError(STATUS_ACCESS_VIOLATION);
1845         ret = FALSE;
1846     }
1847     __ENDTRY
1848     return ret;
1849 }
1850
1851 #define RSA1_MAGIC 0x31415352
1852
1853 struct DECODED_RSA_PUB_KEY
1854 {
1855     DWORD              pubexp;
1856     CRYPT_INTEGER_BLOB modulus;
1857 };
1858
1859 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
1860  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1861  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1862 {
1863     BOOL ret;
1864
1865     __TRY
1866     {
1867         struct AsnDecodeSequenceItem items[] = {
1868          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
1869            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
1870            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
1871            0 },
1872          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
1873            CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
1874         };
1875         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
1876         DWORD size = 0;
1877
1878         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1879          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
1880          CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
1881         if (ret)
1882         {
1883             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1884              decodedKey->modulus.cbData;
1885
1886             if (!pvStructInfo)
1887             {
1888                 *pcbStructInfo = bytesNeeded;
1889                 ret = TRUE;
1890             }
1891             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1892              pvStructInfo, pcbStructInfo, bytesNeeded)))
1893             {
1894                 BLOBHEADER *hdr;
1895                 RSAPUBKEY *rsaPubKey;
1896
1897                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1898                     pvStructInfo = *(BYTE **)pvStructInfo;
1899                 hdr = (BLOBHEADER *)pvStructInfo;
1900                 hdr->bType = PUBLICKEYBLOB;
1901                 hdr->bVersion = CUR_BLOB_VERSION;
1902                 hdr->reserved = 0;
1903                 hdr->aiKeyAlg = CALG_RSA_KEYX;
1904                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
1905                  sizeof(BLOBHEADER));
1906                 rsaPubKey->magic = RSA1_MAGIC;
1907                 rsaPubKey->pubexp = decodedKey->pubexp;
1908                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
1909                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
1910                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
1911                  decodedKey->modulus.cbData);
1912             }
1913             LocalFree(decodedKey);
1914         }
1915     }
1916     __EXCEPT_PAGE_FAULT
1917     {
1918         SetLastError(STATUS_ACCESS_VIOLATION);
1919         ret = FALSE;
1920     }
1921     __ENDTRY
1922     return ret;
1923 }
1924
1925 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
1926  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1927  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1928 {
1929     BOOL ret;
1930     DWORD bytesNeeded, dataLen;
1931
1932     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1933      pDecodePara, pvStructInfo, *pcbStructInfo);
1934
1935     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1936     {
1937         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1938             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1939         else
1940             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1941         if (!pvStructInfo)
1942             *pcbStructInfo = bytesNeeded;
1943         else if (*pcbStructInfo < bytesNeeded)
1944         {
1945             SetLastError(ERROR_MORE_DATA);
1946             *pcbStructInfo = bytesNeeded;
1947             ret = FALSE;
1948         }
1949         else
1950         {
1951             CRYPT_DATA_BLOB *blob;
1952             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1953
1954             blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1955             blob->cbData = dataLen;
1956             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1957                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1958             else
1959             {
1960                 assert(blob->pbData);
1961                 if (blob->cbData)
1962                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1963                      blob->cbData);
1964             }
1965         }
1966     }
1967     return ret;
1968 }
1969
1970 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1971  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1972  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1973 {
1974     BOOL ret;
1975
1976     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1977      pDecodePara, pvStructInfo, *pcbStructInfo);
1978
1979     __TRY
1980     {
1981         DWORD bytesNeeded;
1982
1983         if (!cbEncoded)
1984         {
1985             SetLastError(CRYPT_E_ASN1_CORRUPT);
1986             ret = FALSE;
1987         }
1988         else if (pbEncoded[0] != ASN_OCTETSTRING)
1989         {
1990             SetLastError(CRYPT_E_ASN1_BADTAG);
1991             ret = FALSE;
1992         }
1993         else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
1994          lpszStructType, pbEncoded, cbEncoded,
1995          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1996         {
1997             if (!pvStructInfo)
1998                 *pcbStructInfo = bytesNeeded;
1999             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2000              pvStructInfo, pcbStructInfo, bytesNeeded)))
2001             {
2002                 CRYPT_DATA_BLOB *blob;
2003
2004                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2005                     pvStructInfo = *(BYTE **)pvStructInfo;
2006                 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2007                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2008                 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2009                  lpszStructType, pbEncoded, cbEncoded,
2010                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2011                  &bytesNeeded);
2012             }
2013         }
2014     }
2015     __EXCEPT_PAGE_FAULT
2016     {
2017         SetLastError(STATUS_ACCESS_VIOLATION);
2018         ret = FALSE;
2019     }
2020     __ENDTRY
2021     return ret;
2022 }
2023
2024 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2025  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2026  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2027 {
2028     BOOL ret;
2029
2030     TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2031      pDecodePara, pvStructInfo, *pcbStructInfo);
2032
2033     if (pbEncoded[0] == ASN_BITSTRING)
2034     {
2035         DWORD bytesNeeded, dataLen;
2036
2037         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2038         {
2039             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2040                 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2041             else
2042                 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2043             if (!pvStructInfo)
2044                 *pcbStructInfo = bytesNeeded;
2045             else if (*pcbStructInfo < bytesNeeded)
2046             {
2047                 *pcbStructInfo = bytesNeeded;
2048                 SetLastError(ERROR_MORE_DATA);
2049                 ret = FALSE;
2050             }
2051             else
2052             {
2053                 CRYPT_BIT_BLOB *blob;
2054
2055                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2056                 blob->cbData = dataLen - 1;
2057                 blob->cUnusedBits = *(pbEncoded + 1 +
2058                  GET_LEN_BYTES(pbEncoded[1]));
2059                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2060                 {
2061                     blob->pbData = (BYTE *)pbEncoded + 2 +
2062                      GET_LEN_BYTES(pbEncoded[1]);
2063                 }
2064                 else
2065                 {
2066                     assert(blob->pbData);
2067                     if (blob->cbData)
2068                     {
2069                         BYTE mask = 0xff << blob->cUnusedBits;
2070
2071                         memcpy(blob->pbData, pbEncoded + 2 +
2072                          GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2073                         blob->pbData[blob->cbData - 1] &= mask;
2074                     }
2075                 }
2076             }
2077         }
2078     }
2079     else
2080     {
2081         SetLastError(CRYPT_E_ASN1_BADTAG);
2082         ret = FALSE;
2083     }
2084     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2085     return ret;
2086 }
2087
2088 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2089  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2090  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2091 {
2092     BOOL ret;
2093
2094     TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2095      pDecodePara, pvStructInfo, pcbStructInfo);
2096
2097     __TRY
2098     {
2099         DWORD bytesNeeded;
2100
2101         if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2102          lpszStructType, pbEncoded, cbEncoded,
2103          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2104         {
2105             if (!pvStructInfo)
2106                 *pcbStructInfo = bytesNeeded;
2107             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2108              pvStructInfo, pcbStructInfo, bytesNeeded)))
2109             {
2110                 CRYPT_BIT_BLOB *blob;
2111
2112                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2113                     pvStructInfo = *(BYTE **)pvStructInfo;
2114                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2115                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2116                 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2117                  lpszStructType, pbEncoded, cbEncoded,
2118                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2119                  &bytesNeeded);
2120             }
2121         }
2122     }
2123     __EXCEPT_PAGE_FAULT
2124     {
2125         SetLastError(STATUS_ACCESS_VIOLATION);
2126         ret = FALSE;
2127     }
2128     __ENDTRY
2129     TRACE("returning %d (%08lx)\n", ret, GetLastError());
2130     return ret;
2131 }
2132
2133 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2134  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2135  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2136 {
2137     BOOL ret;
2138
2139     if (!pvStructInfo)
2140     {
2141         *pcbStructInfo = sizeof(int);
2142         return TRUE;
2143     }
2144     __TRY
2145     {
2146         BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2147         CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2148         DWORD size = sizeof(buf);
2149
2150         blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2151         ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2152          X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2153         if (ret)
2154         {
2155             if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2156              pvStructInfo, pcbStructInfo, sizeof(int))))
2157             {
2158                 int val, i;
2159
2160                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2161                     pvStructInfo = *(BYTE **)pvStructInfo;
2162                 if (blob->pbData[blob->cbData - 1] & 0x80)
2163                 {
2164                     /* initialize to a negative value to sign-extend */
2165                     val = -1;
2166                 }
2167                 else
2168                     val = 0;
2169                 for (i = 0; i < blob->cbData; i++)
2170                 {
2171                     val <<= 8;
2172                     val |= blob->pbData[blob->cbData - i - 1];
2173                 }
2174                 memcpy(pvStructInfo, &val, sizeof(int));
2175             }
2176         }
2177         else if (GetLastError() == ERROR_MORE_DATA)
2178             SetLastError(CRYPT_E_ASN1_LARGE);
2179     }
2180     __EXCEPT_PAGE_FAULT
2181     {
2182         SetLastError(STATUS_ACCESS_VIOLATION);
2183         ret = FALSE;
2184     }
2185     __ENDTRY
2186     return ret;
2187 }
2188
2189 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2190  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2191  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2192 {
2193     BOOL ret;
2194
2195     if (pbEncoded[0] == ASN_INTEGER)
2196     {
2197         DWORD bytesNeeded, dataLen;
2198
2199         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2200         {
2201             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2202
2203             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2204             if (!pvStructInfo)
2205                 *pcbStructInfo = bytesNeeded;
2206             else if (*pcbStructInfo < bytesNeeded)
2207             {
2208                 *pcbStructInfo = bytesNeeded;
2209                 SetLastError(ERROR_MORE_DATA);
2210                 ret = FALSE;
2211             }
2212             else
2213             {
2214                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2215
2216                 blob->cbData = dataLen;
2217                 assert(blob->pbData);
2218                 if (blob->cbData)
2219                 {
2220                     DWORD i;
2221
2222                     for (i = 0; i < blob->cbData; i++)
2223                     {
2224                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2225                          dataLen - i - 1);
2226                     }
2227                 }
2228             }
2229         }
2230     }
2231     else
2232     {
2233         SetLastError(CRYPT_E_ASN1_BADTAG);
2234         ret = FALSE;
2235     }
2236     return ret;
2237 }
2238
2239 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2240  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2241  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2242 {
2243     BOOL ret;
2244
2245     __TRY
2246     {
2247         DWORD bytesNeeded;
2248
2249         if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2250          lpszStructType, pbEncoded, cbEncoded,
2251          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2252         {
2253             if (!pvStructInfo)
2254                 *pcbStructInfo = bytesNeeded;
2255             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2256              pvStructInfo, pcbStructInfo, bytesNeeded)))
2257             {
2258                 CRYPT_INTEGER_BLOB *blob;
2259
2260                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2261                     pvStructInfo = *(BYTE **)pvStructInfo;
2262                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2263                 blob->pbData = (BYTE *)pvStructInfo +
2264                  sizeof(CRYPT_INTEGER_BLOB);
2265                 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2266                  lpszStructType, pbEncoded, cbEncoded,
2267                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2268                  &bytesNeeded);
2269             }
2270         }
2271     }
2272     __EXCEPT_PAGE_FAULT
2273     {
2274         SetLastError(STATUS_ACCESS_VIOLATION);
2275         ret = FALSE;
2276     }
2277     __ENDTRY
2278     return ret;
2279 }
2280
2281 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2282  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2283  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2284  void *pvStructInfo, DWORD *pcbStructInfo)
2285 {
2286     BOOL ret;
2287
2288     if (pbEncoded[0] == ASN_INTEGER)
2289     {
2290         DWORD bytesNeeded, dataLen;
2291
2292         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2293         {
2294             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2295
2296             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2297             if (!pvStructInfo)
2298                 *pcbStructInfo = bytesNeeded;
2299             else if (*pcbStructInfo < bytesNeeded)
2300             {
2301                 *pcbStructInfo = bytesNeeded;
2302                 SetLastError(ERROR_MORE_DATA);
2303                 ret = FALSE;
2304             }
2305             else
2306             {
2307                 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2308
2309                 blob->cbData = dataLen;
2310                 assert(blob->pbData);
2311                 /* remove leading zero byte if it exists */
2312                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2313                 {
2314                     blob->cbData--;
2315                     blob->pbData++;
2316                 }
2317                 if (blob->cbData)
2318                 {
2319                     DWORD i;
2320
2321                     for (i = 0; i < blob->cbData; i++)
2322                     {
2323                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2324                          dataLen - i - 1);
2325                     }
2326                 }
2327             }
2328         }
2329     }
2330     else
2331     {
2332         SetLastError(CRYPT_E_ASN1_BADTAG);
2333         ret = FALSE;
2334     }
2335     return ret;
2336 }
2337
2338 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2339  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2340  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2341 {
2342     BOOL ret;
2343
2344     __TRY
2345     {
2346         DWORD bytesNeeded;
2347
2348         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2349          lpszStructType, pbEncoded, cbEncoded,
2350          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2351         {
2352             if (!pvStructInfo)
2353                 *pcbStructInfo = bytesNeeded;
2354             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2355              pvStructInfo, pcbStructInfo, bytesNeeded)))
2356             {
2357                 CRYPT_INTEGER_BLOB *blob;
2358
2359                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2360                     pvStructInfo = *(BYTE **)pvStructInfo;
2361                 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2362                 blob->pbData = (BYTE *)pvStructInfo +
2363                  sizeof(CRYPT_INTEGER_BLOB);
2364                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2365                  lpszStructType, pbEncoded, cbEncoded,
2366                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2367                  &bytesNeeded);
2368             }
2369         }
2370     }
2371     __EXCEPT_PAGE_FAULT
2372     {
2373         SetLastError(STATUS_ACCESS_VIOLATION);
2374         ret = FALSE;
2375     }
2376     __ENDTRY
2377     return ret;
2378 }
2379
2380 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2381  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2382  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2383 {
2384     BOOL ret;
2385
2386     if (!pvStructInfo)
2387     {
2388         *pcbStructInfo = sizeof(int);
2389         return TRUE;
2390     }
2391     __TRY
2392     {
2393         if (pbEncoded[0] == ASN_ENUMERATED)
2394         {
2395             unsigned int val = 0, i;
2396
2397             if (cbEncoded <= 1)
2398             {
2399                 SetLastError(CRYPT_E_ASN1_EOD);
2400                 ret = FALSE;
2401             }
2402             else if (pbEncoded[1] == 0)
2403             {
2404                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2405                 ret = FALSE;
2406             }
2407             else
2408             {
2409                 /* A little strange looking, but we have to accept a sign byte:
2410                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
2411                  * assuming a small length is okay here, it has to be in short
2412                  * form.
2413                  */
2414                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2415                 {
2416                     SetLastError(CRYPT_E_ASN1_LARGE);
2417                     return FALSE;
2418                 }
2419                 for (i = 0; i < pbEncoded[1]; i++)
2420                 {
2421                     val <<= 8;
2422                     val |= pbEncoded[2 + i];
2423                 }
2424                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2425                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2426                 {
2427                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2428                         pvStructInfo = *(BYTE **)pvStructInfo;
2429                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
2430                 }
2431             }
2432         }
2433         else
2434         {
2435             SetLastError(CRYPT_E_ASN1_BADTAG);
2436             ret = FALSE;
2437         }
2438     }
2439     __EXCEPT_PAGE_FAULT
2440     {
2441         SetLastError(STATUS_ACCESS_VIOLATION);
2442         ret = FALSE;
2443     }
2444     __ENDTRY
2445     return ret;
2446 }
2447
2448 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2449  * if it fails.
2450  */
2451 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2452  do { \
2453     BYTE i; \
2454  \
2455     (word) = 0; \
2456     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2457     { \
2458         if (!isdigit(*(pbEncoded))) \
2459         { \
2460             SetLastError(CRYPT_E_ASN1_CORRUPT); \
2461             ret = FALSE; \
2462         } \
2463         else \
2464         { \
2465             (word) *= 10; \
2466             (word) += *(pbEncoded)++ - '0'; \
2467         } \
2468     } \
2469  } while (0)
2470
2471 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2472  SYSTEMTIME *sysTime)
2473 {
2474     BOOL ret;
2475
2476     __TRY
2477     {
2478         ret = TRUE;
2479         if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2480         {
2481             WORD hours, minutes = 0;
2482             BYTE sign = *pbEncoded++;
2483
2484             len--;
2485             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2486             if (ret && hours >= 24)
2487             {
2488                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2489                 ret = FALSE;
2490             }
2491             else if (len >= 2)
2492             {
2493                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2494                 if (ret && minutes >= 60)
2495                 {
2496                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2497                     ret = FALSE;
2498                 }
2499             }
2500             if (ret)
2501             {
2502                 if (sign == '+')
2503                 {
2504                     sysTime->wHour += hours;
2505                     sysTime->wMinute += minutes;
2506                 }
2507                 else
2508                 {
2509                     if (hours > sysTime->wHour)
2510                     {
2511                         sysTime->wDay--;
2512                         sysTime->wHour = 24 - (hours - sysTime->wHour);
2513                     }
2514                     else
2515                         sysTime->wHour -= hours;
2516                     if (minutes > sysTime->wMinute)
2517                     {
2518                         sysTime->wHour--;
2519                         sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2520                     }
2521                     else
2522                         sysTime->wMinute -= minutes;
2523                 }
2524             }
2525         }
2526     }
2527     __EXCEPT_PAGE_FAULT
2528     {
2529         SetLastError(STATUS_ACCESS_VIOLATION);
2530         ret = FALSE;
2531     }
2532     __ENDTRY
2533     return ret;
2534 }
2535
2536 #define MIN_ENCODED_TIME_LENGTH 10
2537
2538 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2539  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2540  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2541 {
2542     BOOL ret;
2543
2544     if (!pvStructInfo)
2545     {
2546         *pcbStructInfo = sizeof(FILETIME);
2547         return TRUE;
2548     }
2549     __TRY
2550     {
2551         ret = TRUE;
2552         if (pbEncoded[0] == ASN_UTCTIME)
2553         {
2554             if (cbEncoded <= 1)
2555             {
2556                 SetLastError(CRYPT_E_ASN1_EOD);
2557                 ret = FALSE;
2558             }
2559             else if (pbEncoded[1] > 0x7f)
2560             {
2561                 /* long-form date strings really can't be valid */
2562                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2563                 ret = FALSE;
2564             }
2565             else
2566             {
2567                 SYSTEMTIME sysTime = { 0 };
2568                 BYTE len = pbEncoded[1];
2569
2570                 if (len < MIN_ENCODED_TIME_LENGTH)
2571                 {
2572                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2573                     ret = FALSE;
2574                 }
2575                 else
2576                 {
2577                     pbEncoded += 2;
2578                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2579                     if (sysTime.wYear >= 50)
2580                         sysTime.wYear += 1900;
2581                     else
2582                         sysTime.wYear += 2000;
2583                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2584                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2585                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2586                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2587                     if (ret && len > 0)
2588                     {
2589                         if (len >= 2 && isdigit(*pbEncoded) &&
2590                          isdigit(*(pbEncoded + 1)))
2591                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2592                              sysTime.wSecond);
2593                         else if (isdigit(*pbEncoded))
2594                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2595                              sysTime.wSecond);
2596                         if (ret)
2597                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2598                              &sysTime);
2599                     }
2600                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2601                      pDecodePara, pvStructInfo, pcbStructInfo,
2602                      sizeof(FILETIME))))
2603                     {
2604                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2605                             pvStructInfo = *(BYTE **)pvStructInfo;
2606                         ret = SystemTimeToFileTime(&sysTime,
2607                          (FILETIME *)pvStructInfo);
2608                     }
2609                 }
2610             }
2611         }
2612         else
2613         {
2614             SetLastError(CRYPT_E_ASN1_BADTAG);
2615             ret = FALSE;
2616         }
2617     }
2618     __EXCEPT_PAGE_FAULT
2619     {
2620         SetLastError(STATUS_ACCESS_VIOLATION);
2621         ret = FALSE;
2622     }
2623     __ENDTRY
2624     return ret;
2625 }
2626
2627 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2628  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2629  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2630 {
2631     BOOL ret;
2632
2633     if (!pvStructInfo)
2634     {
2635         *pcbStructInfo = sizeof(FILETIME);
2636         return TRUE;
2637     }
2638     __TRY
2639     {
2640         ret = TRUE;
2641         if (pbEncoded[0] == ASN_GENERALTIME)
2642         {
2643             if (cbEncoded <= 1)
2644             {
2645                 SetLastError(CRYPT_E_ASN1_EOD);
2646                 ret = FALSE;
2647             }
2648             else if (pbEncoded[1] > 0x7f)
2649             {
2650                 /* long-form date strings really can't be valid */
2651                 SetLastError(CRYPT_E_ASN1_CORRUPT);
2652                 ret = FALSE;
2653             }
2654             else
2655             {
2656                 BYTE len = pbEncoded[1];
2657
2658                 if (len < MIN_ENCODED_TIME_LENGTH)
2659                 {
2660                     SetLastError(CRYPT_E_ASN1_CORRUPT);
2661                     ret = FALSE;
2662                 }
2663                 else
2664                 {
2665                     SYSTEMTIME sysTime = { 0 };
2666
2667                     pbEncoded += 2;
2668                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2669                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2670                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2671                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2672                     if (ret && len > 0)
2673                     {
2674                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2675                          sysTime.wMinute);
2676                         if (ret && len > 0)
2677                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2678                              sysTime.wSecond);
2679                         if (ret && len > 0 && (*pbEncoded == '.' ||
2680                          *pbEncoded == ','))
2681                         {
2682                             BYTE digits;
2683
2684                             pbEncoded++;
2685                             len--;
2686                             /* workaround macro weirdness */
2687                             digits = min(len, 3);
2688                             CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2689                              sysTime.wMilliseconds);
2690                         }
2691                         if (ret)
2692                             ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2693                              &sysTime);
2694                     }
2695                     if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2696                      pDecodePara, pvStructInfo, pcbStructInfo,
2697                      sizeof(FILETIME))))
2698                     {
2699                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2700                             pvStructInfo = *(BYTE **)pvStructInfo;
2701                         ret = SystemTimeToFileTime(&sysTime,
2702                          (FILETIME *)pvStructInfo);
2703                     }
2704                 }
2705             }
2706         }
2707         else
2708         {
2709             SetLastError(CRYPT_E_ASN1_BADTAG);
2710             ret = FALSE;
2711         }
2712     }
2713     __EXCEPT_PAGE_FAULT
2714     {
2715         SetLastError(STATUS_ACCESS_VIOLATION);
2716         ret = FALSE;
2717     }
2718     __ENDTRY
2719     return ret;
2720 }
2721
2722 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
2723  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2724  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2725 {
2726     BOOL ret;
2727
2728     __TRY
2729     {
2730         if (pbEncoded[0] == ASN_UTCTIME)
2731             ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
2732              pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2733              pcbStructInfo);
2734         else if (pbEncoded[0] == ASN_GENERALTIME)
2735             ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
2736              lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
2737              pvStructInfo, pcbStructInfo);
2738         else
2739         {
2740             SetLastError(CRYPT_E_ASN1_BADTAG);
2741             ret = FALSE;
2742         }
2743     }
2744     __EXCEPT_PAGE_FAULT
2745     {
2746         SetLastError(STATUS_ACCESS_VIOLATION);
2747         ret = FALSE;
2748     }
2749     __ENDTRY
2750     return ret;
2751 }
2752
2753 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
2754  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2755  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2756 {
2757     BOOL ret = TRUE;
2758
2759     __TRY
2760     {
2761         if (pbEncoded[0] == ASN_SEQUENCEOF)
2762         {
2763             DWORD bytesNeeded, dataLen, remainingLen, cValue;
2764
2765             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2766             {
2767                 BYTE lenBytes;
2768                 const BYTE *ptr;
2769
2770                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2771                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
2772                 cValue = 0;
2773                 ptr = pbEncoded + 1 + lenBytes;
2774                 remainingLen = dataLen;
2775                 while (ret && remainingLen)
2776                 {
2777                     DWORD nextLen;
2778
2779                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2780                     if (ret)
2781                     {
2782                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2783
2784                         remainingLen -= 1 + nextLenBytes + nextLen;
2785                         ptr += 1 + nextLenBytes + nextLen;
2786                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
2787                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2788                             bytesNeeded += 1 + nextLenBytes + nextLen;
2789                         cValue++;
2790                     }
2791                 }
2792                 if (ret)
2793                 {
2794                     CRYPT_SEQUENCE_OF_ANY *seq;
2795                     BYTE *nextPtr;
2796                     DWORD i;
2797
2798                     if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2799                      pvStructInfo, pcbStructInfo, bytesNeeded)))
2800                     {
2801                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2802                             pvStructInfo = *(BYTE **)pvStructInfo;
2803                         seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2804                         seq->cValue = cValue;
2805                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
2806                          sizeof(*seq));
2807                         nextPtr = (BYTE *)seq->rgValue +
2808                          cValue * sizeof(CRYPT_DER_BLOB);
2809                         ptr = pbEncoded + 1 + lenBytes;
2810                         remainingLen = dataLen;
2811                         i = 0;
2812                         while (ret && remainingLen)
2813                         {
2814                             DWORD nextLen;
2815
2816                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2817                             if (ret)
2818                             {
2819                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2820
2821                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
2822                                  nextLen;
2823                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2824                                     seq->rgValue[i].pbData = (BYTE *)ptr;
2825                                 else
2826                                 {
2827                                     seq->rgValue[i].pbData = nextPtr;
2828                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
2829                                      nextLen);
2830                                     nextPtr += 1 + nextLenBytes + nextLen;
2831                                 }
2832                                 remainingLen -= 1 + nextLenBytes + nextLen;
2833                                 ptr += 1 + nextLenBytes + nextLen;
2834                                 i++;
2835                             }
2836                         }
2837                     }
2838                 }
2839             }
2840         }
2841         else
2842         {
2843             SetLastError(CRYPT_E_ASN1_BADTAG);
2844             return FALSE;
2845         }
2846     }
2847     __EXCEPT_PAGE_FAULT
2848     {
2849         SetLastError(STATUS_ACCESS_VIOLATION);
2850         ret = FALSE;
2851     }
2852     __ENDTRY
2853     return ret;
2854 }
2855
2856 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
2857  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2858  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2859 {
2860     struct AsnDecodeSequenceItem items[] = {
2861      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
2862        DistPointName), CRYPT_AsnDecodeAltNameInternal,
2863        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
2864        DistPointName.u.FullName.rgAltEntry), 0 },
2865      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
2866        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
2867        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
2868      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
2869        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
2870        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
2871     };
2872     BOOL ret;
2873
2874     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2875      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2876      dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2877     return ret;
2878 }
2879
2880 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
2881  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2882  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2883 {
2884     BOOL ret;
2885
2886     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2887      pDecodePara, pvStructInfo, *pcbStructInfo);
2888
2889     __TRY
2890     {
2891         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2892          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
2893          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
2894
2895         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2896          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2897     }
2898     __EXCEPT_PAGE_FAULT
2899     {
2900         SetLastError(STATUS_ACCESS_VIOLATION);
2901         ret = FALSE;
2902     }
2903     __ENDTRY
2904     return ret;
2905 }
2906
2907 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2908  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2909  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2910 {
2911     BOOL ret;
2912
2913     TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2914      pDecodePara, pvStructInfo, *pcbStructInfo);
2915
2916     __TRY
2917     {
2918         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2919          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2920
2921         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2922          pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2923     }
2924     __EXCEPT_PAGE_FAULT
2925     {
2926         SetLastError(STATUS_ACCESS_VIOLATION);
2927         ret = FALSE;
2928     }
2929     __ENDTRY
2930     return ret;
2931 }
2932
2933 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2934  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2935  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2936 {
2937     static HCRYPTOIDFUNCSET set = NULL;
2938     BOOL ret = FALSE;
2939     CryptDecodeObjectExFunc decodeFunc = NULL;
2940     HCRYPTOIDFUNCADDR hFunc = NULL;
2941
2942     TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
2943      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
2944      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
2945
2946     if (!pvStructInfo && !pcbStructInfo)
2947     {
2948         SetLastError(ERROR_INVALID_PARAMETER);
2949         return FALSE;
2950     }
2951     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2952      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2953     {
2954         SetLastError(ERROR_FILE_NOT_FOUND);
2955         return FALSE;
2956     }
2957     if (!cbEncoded)
2958     {
2959         SetLastError(CRYPT_E_ASN1_EOD);
2960         return FALSE;
2961     }
2962     if (cbEncoded > MAX_ENCODED_LEN)
2963     {
2964         SetLastError(CRYPT_E_ASN1_LARGE);
2965         return FALSE;
2966     }
2967
2968     SetLastError(NOERROR);
2969     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
2970         *(BYTE **)pvStructInfo = NULL;
2971     if (!HIWORD(lpszStructType))
2972     {
2973         switch (LOWORD(lpszStructType))
2974         {
2975         case (WORD)X509_CERT:
2976             decodeFunc = CRYPT_AsnDecodeCert;
2977             break;
2978         case (WORD)X509_CERT_TO_BE_SIGNED:
2979             decodeFunc = CRYPT_AsnDecodeCertInfo;
2980             break;
2981         case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2982             decodeFunc = CRYPT_AsnDecodeCRLInfo;
2983             break;
2984         case (WORD)X509_EXTENSIONS:
2985             decodeFunc = CRYPT_AsnDecodeExtensions;
2986             break;
2987         case (WORD)X509_NAME_VALUE:
2988             decodeFunc = CRYPT_AsnDecodeNameValue;
2989             break;
2990         case (WORD)X509_NAME:
2991             decodeFunc = CRYPT_AsnDecodeName;
2992             break;
2993         case (WORD)X509_PUBLIC_KEY_INFO:
2994             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
2995             break;
2996         case (WORD)X509_ALTERNATE_NAME:
2997             decodeFunc = CRYPT_AsnDecodeAltName;
2998             break;
2999         case (WORD)X509_BASIC_CONSTRAINTS:
3000             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3001             break;
3002         case (WORD)X509_BASIC_CONSTRAINTS2:
3003             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3004             break;
3005         case (WORD)RSA_CSP_PUBLICKEYBLOB:
3006             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3007             break;
3008         case (WORD)X509_OCTET_STRING:
3009             decodeFunc = CRYPT_AsnDecodeOctets;
3010             break;
3011         case (WORD)X509_BITS:
3012         case (WORD)X509_KEY_USAGE:
3013             decodeFunc = CRYPT_AsnDecodeBits;
3014             break;
3015         case (WORD)X509_INTEGER:
3016             decodeFunc = CRYPT_AsnDecodeInt;
3017             break;
3018         case (WORD)X509_MULTI_BYTE_INTEGER:
3019             decodeFunc = CRYPT_AsnDecodeInteger;
3020             break;
3021         case (WORD)X509_MULTI_BYTE_UINT:
3022             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3023             break;
3024         case (WORD)X509_ENUMERATED:
3025             decodeFunc = CRYPT_AsnDecodeEnumerated;
3026             break;
3027         case (WORD)X509_CHOICE_OF_TIME:
3028             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3029             break;
3030         case (WORD)X509_SEQUENCE_OF_ANY:
3031             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3032             break;
3033         case (WORD)PKCS_UTC_TIME:
3034             decodeFunc = CRYPT_AsnDecodeUtcTime;
3035             break;
3036         case (WORD)X509_CRL_DIST_POINTS:
3037             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3038             break;
3039         case (WORD)X509_ENHANCED_KEY_USAGE:
3040             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3041             break;
3042         default:
3043             FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3044         }
3045     }
3046     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3047         decodeFunc = CRYPT_AsnDecodeExtensions;
3048     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3049         decodeFunc = CRYPT_AsnDecodeUtcTime;
3050     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3051         decodeFunc = CRYPT_AsnDecodeEnumerated;
3052     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3053         decodeFunc = CRYPT_AsnDecodeBits;
3054     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3055         decodeFunc = CRYPT_AsnDecodeOctets;
3056     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3057         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3058     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3059         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3060     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3061         decodeFunc = CRYPT_AsnDecodeAltName;
3062     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3063         decodeFunc = CRYPT_AsnDecodeAltName;
3064     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3065         decodeFunc = CRYPT_AsnDecodeAltName;
3066     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3067         decodeFunc = CRYPT_AsnDecodeAltName;
3068     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3069         decodeFunc = CRYPT_AsnDecodeAltName;
3070     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3071         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3072     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3073         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3074     else
3075         TRACE("OID %s not found or unimplemented, looking for DLL\n",
3076          debugstr_a(lpszStructType));
3077     if (!decodeFunc)
3078     {
3079         if (!set)
3080             set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3081         CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3082          (void **)&decodeFunc, &hFunc);
3083     }
3084     if (decodeFunc)
3085         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3086          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3087     else
3088         SetLastError(ERROR_FILE_NOT_FOUND);
3089     if (hFunc)
3090         CryptFreeOIDFunctionAddress(hFunc, 0);
3091     return ret;
3092 }