~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/crypt32/decode.c

Version: ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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