ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

decode.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2005-2009 Juan Lang
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  *
00018  * This file implements ASN.1 DER decoding of a limited set of types.
00019  * It isn't a full ASN.1 implementation.  Microsoft implements BER
00020  * encoding of many of the basic types in msasn1.dll, but that interface isn't
00021  * implemented, so I implement them here.
00022  *
00023  * References:
00024  * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
00025  * (available online, look for a PDF copy as the HTML versions tend to have
00026  * translation errors.)
00027  *
00028  * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
00029  *
00030  * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
00031  */
00032 
00033 #include "config.h"
00034 #include "wine/port.h"
00035 
00036 #include <assert.h>
00037 #include <stdarg.h>
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 
00041 #define NONAMELESSUNION
00042 
00043 #include "windef.h"
00044 #include "winbase.h"
00045 #include "wincrypt.h"
00046 #include "winnls.h"
00047 #include "snmp.h"
00048 #include "wine/debug.h"
00049 #include "wine/exception.h"
00050 #include "crypt32_private.h"
00051 
00052 /* This is a bit arbitrary, but to set some limit: */
00053 #define MAX_ENCODED_LEN 0x02000000
00054 
00055 #define ASN_FLAGS_MASK 0xe0
00056 #define ASN_TYPE_MASK  0x1f
00057 
00058 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
00059 WINE_DECLARE_DEBUG_CHANNEL(crypt);
00060 
00061 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
00062  DWORD, DWORD, void *, DWORD *);
00063 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
00064  DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
00065 
00066 /* Internal decoders don't do memory allocation or exception handling, and
00067  * they report how many bytes they decoded.
00068  */
00069 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
00070  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
00071 
00072 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
00073  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00074  DWORD *pcbDecoded);
00075 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
00076  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00077  DWORD *pcbDecoded);
00078 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
00079  */
00080 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
00081  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
00082 /* Assumes algo->Parameters.pbData is set ahead of time. */
00083 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
00084  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
00085 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
00086  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
00087 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
00088 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
00089  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00090  DWORD *pcbDecoded);
00091 /* Doesn't check the tag, assumes the caller does so */
00092 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
00093  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
00094 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
00095  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
00096 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
00097  * member has been initialized, doesn't do exception handling, and doesn't do
00098  * memory allocation.  Also doesn't check tag, assumes the caller has checked
00099  * it.
00100  */
00101 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
00102  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00103  DWORD *pcbDecoded);
00104 /* Like CRYPT_AsnDecodeInteger, but unsigned.  */
00105 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
00106  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00107  DWORD *pcbDecoded);
00108 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
00109  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00110  DWORD *pcbDecoded);
00111 
00112 /* Gets the number of length bytes from the given (leading) length byte */
00113 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
00114 
00115 /* Helper function to get the encoded length of the data starting at pbEncoded,
00116  * where pbEncoded[0] is the tag.  If the data are too short to contain a
00117  * length or if the length is too large for cbEncoded, sets an appropriate
00118  * error code and returns FALSE.  If the encoded length is unknown due to
00119  * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
00120  */
00121 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
00122  DWORD *len)
00123 {
00124     BOOL ret;
00125 
00126     if (cbEncoded <= 1)
00127     {
00128         SetLastError(CRYPT_E_ASN1_CORRUPT);
00129         ret = FALSE;
00130     }
00131     else if (pbEncoded[1] <= 0x7f)
00132     {
00133         if (pbEncoded[1] + 1 > cbEncoded)
00134         {
00135             SetLastError(CRYPT_E_ASN1_EOD);
00136             ret = FALSE;
00137         }
00138         else
00139         {
00140             *len = pbEncoded[1];
00141             ret = TRUE;
00142         }
00143     }
00144     else if (pbEncoded[1] == 0x80)
00145     {
00146         *len = CMSG_INDEFINITE_LENGTH;
00147         ret = TRUE;
00148     }
00149     else
00150     {
00151         BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
00152 
00153         if (lenLen > sizeof(DWORD) + 1)
00154         {
00155             SetLastError(CRYPT_E_ASN1_LARGE);
00156             ret = FALSE;
00157         }
00158         else if (lenLen + 2 > cbEncoded)
00159         {
00160             SetLastError(CRYPT_E_ASN1_CORRUPT);
00161             ret = FALSE;
00162         }
00163         else
00164         {
00165             DWORD out = 0;
00166 
00167             pbEncoded += 2;
00168             while (--lenLen)
00169             {
00170                 out <<= 8;
00171                 out |= *pbEncoded++;
00172             }
00173             if (out + lenLen + 1 > cbEncoded)
00174             {
00175                 SetLastError(CRYPT_E_ASN1_EOD);
00176                 ret = FALSE;
00177             }
00178             else
00179             {
00180                 *len = out;
00181                 ret = TRUE;
00182             }
00183         }
00184     }
00185     return ret;
00186 }
00187 
00188 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
00189 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
00190 {
00191     BOOL ret;
00192 
00193     if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
00194      *len == CMSG_INDEFINITE_LENGTH)
00195     {
00196         SetLastError(CRYPT_E_ASN1_CORRUPT);
00197         ret = FALSE;
00198     }
00199     return ret;
00200 }
00201 
00202 /* Helper function to check *pcbStructInfo, set it to the required size, and
00203  * optionally to allocate memory.  Assumes pvStructInfo is not NULL.
00204  * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
00205  * pointer to the newly allocated memory.
00206  */
00207 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
00208  const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
00209  DWORD bytesNeeded)
00210 {
00211     BOOL ret = TRUE;
00212 
00213     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
00214     {
00215         if (pDecodePara && pDecodePara->pfnAlloc)
00216             *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
00217         else
00218             *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
00219         if (!*(BYTE **)pvStructInfo)
00220             ret = FALSE;
00221         else
00222             *pcbStructInfo = bytesNeeded;
00223     }
00224     else if (*pcbStructInfo < bytesNeeded)
00225     {
00226         *pcbStructInfo = bytesNeeded;
00227         SetLastError(ERROR_MORE_DATA);
00228         ret = FALSE;
00229     }
00230     else
00231         *pcbStructInfo = bytesNeeded;
00232     return ret;
00233 }
00234 
00235 static void CRYPT_FreeSpace(const CRYPT_DECODE_PARA *pDecodePara, LPVOID pv)
00236 {
00237     if (pDecodePara && pDecodePara->pfnFree)
00238         pDecodePara->pfnFree(pv);
00239     else
00240         LocalFree(pv);
00241 }
00242 
00243 /* Helper function to check *pcbStructInfo and set it to the required size.
00244  * Assumes pvStructInfo is not NULL.
00245  */
00246 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
00247 {
00248     BOOL ret;
00249 
00250     if (*pcbStructInfo < bytesNeeded)
00251     {
00252         *pcbStructInfo = bytesNeeded;
00253         SetLastError(ERROR_MORE_DATA);
00254         ret = FALSE;
00255     }
00256     else
00257     {
00258         *pcbStructInfo = bytesNeeded;
00259         ret = TRUE;
00260     }
00261     return ret;
00262 }
00263 
00264 /* tag:
00265  *     The expected tag of the item.  If tag is 0, decodeFunc is called
00266  *     regardless of the tag value seen.
00267  * offset:
00268  *     A sequence is decoded into a struct.  The offset member is the
00269  *     offset of this item within that struct.
00270  * decodeFunc:
00271  *     The decoder function to use.  If this is NULL, then the member isn't
00272  *     decoded, but minSize space is reserved for it.
00273  * minSize:
00274  *     The minimum amount of space occupied after decoding.  You must set this.
00275  * optional:
00276  *     If true, and the tag doesn't match the expected tag for this item,
00277  *     or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
00278  *     filled with 0 for this member.
00279  * hasPointer, pointerOffset:
00280  *     If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
00281  *     the offset within the struct of the data pointer (or to the
00282  *     first data pointer, if more than one exist).
00283  * size:
00284  *     Used by CRYPT_AsnDecodeSequence, not for your use.
00285  */
00286 struct AsnDecodeSequenceItem
00287 {
00288     BYTE               tag;
00289     DWORD              offset;
00290     InternalDecodeFunc decodeFunc;
00291     DWORD              minSize;
00292     BOOL               optional;
00293     BOOL               hasPointer;
00294     DWORD              pointerOffset;
00295     DWORD              size;
00296 };
00297 
00298 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
00299 #define MEMBERSIZE(s, member, nextmember) \
00300     (offsetof(s, nextmember) - offsetof(s, member))
00301 
00302 /* Decodes the items in a sequence, where the items are described in items,
00303  * the encoded data are in pbEncoded with length cbEncoded.  Decodes into
00304  * pvStructInfo.  nextData is a pointer to the memory location at which the
00305  * first decoded item with a dynamic pointer should point.
00306  * Upon decoding, *cbDecoded is the total number of bytes decoded.
00307  * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
00308  */
00309 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
00310  DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
00311  void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
00312 {
00313     BOOL ret;
00314     DWORD i, decoded = 0;
00315     const BYTE *ptr = pbEncoded;
00316 
00317     TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
00318      cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
00319 
00320     for (i = 0, ret = TRUE; ret && i < cItem; i++)
00321     {
00322         if (cbEncoded - (ptr - pbEncoded) != 0)
00323         {
00324             DWORD itemLen;
00325 
00326             if ((ret = CRYPT_GetLengthIndefinite(ptr,
00327              cbEncoded - (ptr - pbEncoded), &itemLen)))
00328             {
00329                 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
00330 
00331                 if (ptr[0] == items[i].tag || !items[i].tag)
00332                 {
00333                     DWORD itemEncodedLen;
00334 
00335                     if (itemLen == CMSG_INDEFINITE_LENGTH)
00336                         itemEncodedLen = cbEncoded - (ptr - pbEncoded);
00337                     else
00338                         itemEncodedLen = 1 + itemLenBytes + itemLen;
00339                     if (nextData && pvStructInfo && items[i].hasPointer)
00340                     {
00341                         TRACE("Setting next pointer to %p\n",
00342                          nextData);
00343                         *(BYTE **)((BYTE *)pvStructInfo +
00344                          items[i].pointerOffset) = nextData;
00345                     }
00346                     if (items[i].decodeFunc)
00347                     {
00348                         DWORD itemDecoded;
00349 
00350                         if (pvStructInfo)
00351                             TRACE("decoding item %d\n", i);
00352                         else
00353                             TRACE("sizing item %d\n", i);
00354                         ret = items[i].decodeFunc(ptr, itemEncodedLen,
00355                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
00356                          pvStructInfo ?  (BYTE *)pvStructInfo + items[i].offset
00357                          : NULL, &items[i].size, &itemDecoded);
00358                         if (ret)
00359                         {
00360                             if (items[i].size < items[i].minSize)
00361                                 items[i].size = items[i].minSize;
00362                             else if (items[i].size > items[i].minSize)
00363                             {
00364                                 /* Account for alignment padding */
00365                                 items[i].size = ALIGN_DWORD_PTR(items[i].size);
00366                             }
00367                             TRACE("item %d size: %d\n", i, items[i].size);
00368                             if (nextData && items[i].hasPointer &&
00369                              items[i].size > items[i].minSize)
00370                                 nextData += items[i].size - items[i].minSize;
00371                             if (itemDecoded > itemEncodedLen)
00372                             {
00373                                 WARN("decoded length %d exceeds encoded %d\n",
00374                                  itemDecoded, itemEncodedLen);
00375                                 SetLastError(CRYPT_E_ASN1_CORRUPT);
00376                                 ret = FALSE;
00377                             }
00378                             else
00379                             {
00380                                 ptr += itemDecoded;
00381                                 decoded += itemDecoded;
00382                                 TRACE("item %d: decoded %d bytes\n", i,
00383                                  itemDecoded);
00384                             }
00385                         }
00386                         else if (items[i].optional &&
00387                          GetLastError() == CRYPT_E_ASN1_BADTAG)
00388                         {
00389                             TRACE("skipping optional item %d\n", i);
00390                             items[i].size = items[i].minSize;
00391                             SetLastError(NOERROR);
00392                             ret = TRUE;
00393                         }
00394                         else
00395                             TRACE("item %d failed: %08x\n", i,
00396                              GetLastError());
00397                     }
00398                     else if (itemLen == CMSG_INDEFINITE_LENGTH)
00399                     {
00400                         ERR("can't use indefinite length encoding without a decoder\n");
00401                         SetLastError(CRYPT_E_ASN1_CORRUPT);
00402                         ret = FALSE;
00403                     }
00404                     else
00405                     {
00406                         TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
00407                         ptr += itemEncodedLen;
00408                         decoded += itemEncodedLen;
00409                         items[i].size = items[i].minSize;
00410                     }
00411                 }
00412                 else if (items[i].optional)
00413                 {
00414                     TRACE("skipping optional item %d\n", i);
00415                     items[i].size = items[i].minSize;
00416                 }
00417                 else
00418                 {
00419                     TRACE("item %d: tag %02x doesn't match expected %02x\n",
00420                      i, ptr[0], items[i].tag);
00421                     SetLastError(CRYPT_E_ASN1_BADTAG);
00422                     ret = FALSE;
00423                 }
00424             }
00425         }
00426         else if (items[i].optional)
00427         {
00428             TRACE("missing optional item %d, skipping\n", i);
00429             items[i].size = items[i].minSize;
00430         }
00431         else
00432         {
00433             TRACE("not enough bytes for item %d, failing\n", i);
00434             SetLastError(CRYPT_E_ASN1_CORRUPT);
00435             ret = FALSE;
00436         }
00437     }
00438     if (cbDecoded)
00439         *cbDecoded = decoded;
00440     TRACE("returning %d\n", ret);
00441     return ret;
00442 }
00443 
00444 /* This decodes an arbitrary sequence into a contiguous block of memory
00445  * (basically, a struct.)  Each element being decoded is described by a struct
00446  * AsnDecodeSequenceItem, see above.
00447  * startingPointer is an optional pointer to the first place where dynamic
00448  * data will be stored.  If you know the starting offset, you may pass it
00449  * here.  Otherwise, pass NULL, and one will be inferred from the items.
00450  */
00451 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
00452  DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
00453  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
00454  DWORD *pcbDecoded, void *startingPointer)
00455 {
00456     BOOL ret;
00457 
00458     TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
00459      cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
00460      startingPointer);
00461 
00462     if (!cbEncoded)
00463     {
00464         SetLastError(CRYPT_E_ASN1_EOD);
00465         return FALSE;
00466     }
00467     if (pbEncoded[0] == ASN_SEQUENCE)
00468     {
00469         DWORD dataLen;
00470 
00471         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
00472         {
00473             DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
00474             const BYTE *ptr = pbEncoded + 1 + lenBytes;
00475             BOOL indefinite = FALSE;
00476 
00477             cbEncoded -= 1 + lenBytes;
00478             if (dataLen == CMSG_INDEFINITE_LENGTH)
00479             {
00480                 dataLen = cbEncoded;
00481                 indefinite = TRUE;
00482             }
00483             else if (cbEncoded < dataLen)
00484             {
00485                 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
00486                  cbEncoded);
00487                 SetLastError(CRYPT_E_ASN1_CORRUPT);
00488                 ret = FALSE;
00489             }
00490             if (ret)
00491             {
00492                 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
00493                  ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
00494                 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
00495                 {
00496                     if (cbDecoded > cbEncoded - 2)
00497                     {
00498                         /* Not enough space for 0 TLV */
00499                         SetLastError(CRYPT_E_ASN1_CORRUPT);
00500                         ret = FALSE;
00501                     }
00502                     else if (*(ptr + cbDecoded) != 0 ||
00503                      *(ptr + cbDecoded + 1) != 0)
00504                     {
00505                         TRACE("expected 0 TLV\n");
00506                         SetLastError(CRYPT_E_ASN1_CORRUPT);
00507                         ret = FALSE;
00508                     }
00509                     else
00510                         cbDecoded += 2;
00511                 }
00512             }
00513             if (ret && !indefinite && cbDecoded != dataLen)
00514             {
00515                 TRACE("expected %d decoded, got %d, failing\n", dataLen,
00516                  cbDecoded);
00517                 SetLastError(CRYPT_E_ASN1_CORRUPT);
00518                 ret = FALSE;
00519             }
00520             if (ret)
00521             {
00522                 DWORD i, bytesNeeded = 0, structSize = 0;
00523 
00524                 for (i = 0; i < cItem; i++)
00525                 {
00526                     if (items[i].size > items[i].minSize)
00527                         bytesNeeded += items[i].size - items[i].minSize;
00528                     structSize = max( structSize, items[i].offset + items[i].minSize );
00529                 }
00530                 bytesNeeded += structSize;
00531                 if (pcbDecoded)
00532                     *pcbDecoded = 1 + lenBytes + cbDecoded;
00533                 if (!pvStructInfo)
00534                     *pcbStructInfo = bytesNeeded;
00535                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
00536                  pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
00537                 {
00538                     BYTE *nextData;
00539 
00540                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
00541                         pvStructInfo = *(BYTE **)pvStructInfo;
00542                     if (startingPointer)
00543                         nextData = startingPointer;
00544                     else
00545                         nextData = (BYTE *)pvStructInfo + structSize;
00546                     memset(pvStructInfo, 0, structSize);
00547                     ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
00548                      ptr, dataLen, dwFlags, pvStructInfo, nextData,
00549                      &cbDecoded);
00550                     if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
00551                         CRYPT_FreeSpace(pDecodePara, pvStructInfo);
00552                 }
00553             }
00554         }
00555     }
00556     else
00557     {
00558         SetLastError(CRYPT_E_ASN1_BADTAG);
00559         ret = FALSE;
00560     }
00561     TRACE("returning %d (%08x)\n", ret, GetLastError());
00562     return ret;
00563 }
00564 
00565 /* tag:
00566  *     The expected tag of the entire encoded array (usually a variant
00567  *     of ASN_SETOF or ASN_SEQUENCEOF.)  If tag is 0, decodeFunc is called
00568  *     regardless of the tag seen.
00569  * countOffset:
00570  *     The offset within the outer structure at which the count exists.
00571  *     For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
00572  *     while CRYPT_ATTRIBUTE has countOffset ==
00573  *     offsetof(CRYPT_ATTRIBUTE, cValue).
00574  * arrayOffset:
00575  *     The offset within the outer structure at which the array pointer exists.
00576  *     For example, CRYPT_ATTRIBUTES has arrayOffset ==
00577  *     offsetof(CRYPT_ATTRIBUTES, rgAttr).
00578  * minArraySize:
00579  *     The minimum size of the decoded array.  On WIN32, this is always 8:
00580  *     sizeof(DWORD) + sizeof(void *).  On WIN64, it can be larger due to
00581  *     alignment.
00582  * decodeFunc:
00583  *     used to decode each item in the array
00584  * itemSize:
00585  *      is the minimum size of each decoded item
00586  * hasPointer:
00587  *      indicates whether each item has a dynamic pointer
00588  * pointerOffset:
00589  *     indicates the offset within itemSize at which the pointer exists
00590  */
00591 struct AsnArrayDescriptor
00592 {
00593     BYTE               tag;
00594     DWORD              countOffset;
00595     DWORD              arrayOffset;
00596     DWORD              minArraySize;
00597     InternalDecodeFunc decodeFunc;
00598     DWORD              itemSize;
00599     BOOL               hasPointer;
00600     DWORD              pointerOffset;
00601 };
00602 
00603 struct AsnArrayItemSize
00604 {
00605     DWORD encodedLen;
00606     DWORD size;
00607 };
00608 
00609 /* Decodes an array of like types into a structure described by a struct
00610  * AsnArrayDescriptor.
00611  */
00612 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
00613  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
00614  const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
00615  DWORD *pcbDecoded)
00616 {
00617     BOOL ret = TRUE;
00618 
00619     TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
00620      cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
00621 
00622     if (!cbEncoded)
00623     {
00624         SetLastError(CRYPT_E_ASN1_EOD);
00625         ret = FALSE;
00626     }
00627     else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
00628     {
00629         DWORD dataLen;
00630 
00631         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
00632         {
00633             DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
00634             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
00635             /* There can be arbitrarily many items, but there is often only one.
00636              */
00637             struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
00638 
00639             decoded = 1 + lenBytes;
00640             if (dataLen)
00641             {
00642                 const BYTE *ptr;
00643                 BOOL doneDecoding = FALSE;
00644 
00645                 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
00646                 {
00647                     if (dataLen == CMSG_INDEFINITE_LENGTH)
00648                     {
00649                         if (ptr[0] == 0)
00650                         {
00651                             doneDecoding = TRUE;
00652                             if (ptr[1] != 0)
00653                             {
00654                                 SetLastError(CRYPT_E_ASN1_CORRUPT);
00655                                 ret = FALSE;
00656                             }
00657                             else
00658                                 decoded += 2;
00659                         }
00660                     }
00661                     else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
00662                         doneDecoding = TRUE;
00663                     if (!doneDecoding)
00664                     {
00665                         DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
00666 
00667                         /* Each item decoded may not tolerate extraneous bytes,
00668                          * so get the length of the next element if known.
00669                          */
00670                         if ((ret = CRYPT_GetLengthIndefinite(ptr,
00671                          cbEncoded - (ptr - pbEncoded), &itemDataLen)))
00672                         {
00673                             if (itemDataLen == CMSG_INDEFINITE_LENGTH)
00674                                 itemEncoded = cbEncoded - (ptr - pbEncoded);
00675                             else
00676                                 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
00677                                  itemDataLen;
00678                         }
00679                         if (ret)
00680                             ret = arrayDesc->decodeFunc(ptr, itemEncoded,
00681                              dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
00682                              &itemDecoded);
00683                         if (ret)
00684                         {
00685                             cItems++;
00686                             if (itemSizes != &itemSize)
00687                                 itemSizes = CryptMemRealloc(itemSizes,
00688                                  cItems * sizeof(struct AsnArrayItemSize));
00689                             else if (cItems > 1)
00690                             {
00691                                 itemSizes =
00692                                  CryptMemAlloc(
00693                                  cItems * sizeof(struct AsnArrayItemSize));
00694                                 if (itemSizes)
00695                                     memcpy(itemSizes, &itemSize,
00696                                      sizeof(itemSize));
00697                             }
00698                             if (itemSizes)
00699                             {
00700                                 decoded += itemDecoded;
00701                                 itemSizes[cItems - 1].encodedLen = itemEncoded;
00702                                 itemSizes[cItems - 1].size = size;
00703                                 bytesNeeded += size;
00704                                 ptr += itemEncoded;
00705                             }
00706                             else
00707                                 ret = FALSE;
00708                         }
00709                     }
00710                 }
00711             }
00712             if (ret)
00713             {
00714                 if (pcbDecoded)
00715                     *pcbDecoded = decoded;
00716                 if (!pvStructInfo)
00717                     *pcbStructInfo = bytesNeeded;
00718                 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
00719                  pvStructInfo, pcbStructInfo, bytesNeeded)))
00720                 {
00721                     DWORD i, *pcItems;
00722                     BYTE *nextData;
00723                     const BYTE *ptr;
00724                     void *rgItems;
00725 
00726                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
00727                         pvStructInfo = *(void **)pvStructInfo;
00728                     pcItems = pvStructInfo;
00729                     *pcItems = cItems;
00730                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
00731                     {
00732                         rgItems = (BYTE *)pvStructInfo +
00733                          arrayDesc->minArraySize;
00734                         *(void **)((BYTE *)pcItems -
00735                          arrayDesc->countOffset + arrayDesc->arrayOffset) =
00736                          rgItems;
00737                     }
00738                     else
00739                         rgItems = *(void **)((BYTE *)pcItems -
00740                          arrayDesc->countOffset + arrayDesc->arrayOffset);
00741                     nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
00742                     for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
00743                      i < cItems && ptr - pbEncoded - 1 - lenBytes <
00744                      dataLen; i++)
00745                     {
00746                         DWORD itemDecoded;
00747 
00748                         if (arrayDesc->hasPointer)
00749                             *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
00750                              + arrayDesc->pointerOffset) = nextData;
00751                         ret = arrayDesc->decodeFunc(ptr,
00752                          itemSizes[i].encodedLen,
00753                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
00754                          (BYTE *)rgItems + i * arrayDesc->itemSize,
00755                          &itemSizes[i].size, &itemDecoded);
00756                         if (ret)
00757                         {
00758                             nextData += itemSizes[i].size - arrayDesc->itemSize;
00759                             ptr += itemDecoded;
00760                         }
00761                     }
00762                     if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
00763                         CRYPT_FreeSpace(pDecodePara, pvStructInfo);
00764                 }
00765             }
00766             if (itemSizes != &itemSize)
00767                 CryptMemFree(itemSizes);
00768         }
00769     }
00770     else
00771     {
00772         SetLastError(CRYPT_E_ASN1_BADTAG);
00773         ret = FALSE;
00774     }
00775     return ret;
00776 }
00777 
00778 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
00779  * pvStructInfo.  The BLOB must be non-empty, otherwise the last error is set
00780  * to CRYPT_E_ASN1_CORRUPT.
00781  * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
00782  * set!
00783  */
00784 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
00785  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
00786 {
00787     BOOL ret;
00788     DWORD dataLen;
00789 
00790     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
00791     {
00792         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
00793         DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
00794        
00795         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
00796             bytesNeeded += 1 + lenBytes + dataLen;
00797 
00798         if (pcbDecoded)
00799             *pcbDecoded = 1 + lenBytes + dataLen;
00800         if (!pvStructInfo)
00801             *pcbStructInfo = bytesNeeded;
00802         else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
00803         {
00804             CRYPT_DER_BLOB *blob;
00805 
00806             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
00807                 pvStructInfo = *(BYTE **)pvStructInfo;
00808             blob = pvStructInfo;
00809             blob->cbData = 1 + lenBytes + dataLen;
00810             if (blob->cbData)
00811             {
00812                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
00813                     blob->pbData = (BYTE *)pbEncoded;
00814                 else
00815                 {
00816                     assert(blob->pbData);
00817                     memcpy(blob->pbData, pbEncoded, blob->cbData);
00818                 }
00819             }
00820             else
00821             {
00822                 SetLastError(CRYPT_E_ASN1_CORRUPT);
00823                 ret = FALSE;
00824             }
00825         }
00826     }
00827     return ret;
00828 }
00829 
00830 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
00831 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
00832  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00833  DWORD *pcbDecoded)
00834 {
00835     BOOL ret;
00836 
00837     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
00838      pvStructInfo, *pcbStructInfo, pcbDecoded);
00839 
00840     /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
00841      * place.
00842      */
00843     ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
00844      dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
00845      pcbDecoded);
00846     if (ret && pvStructInfo)
00847     {
00848         CRYPT_BIT_BLOB *blob = pvStructInfo;
00849 
00850         if (blob->cbData)
00851         {
00852             DWORD i;
00853             BYTE temp;
00854 
00855             for (i = 0; i < blob->cbData / 2; i++)
00856             {
00857                 temp = blob->pbData[i];
00858                 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
00859                 blob->pbData[blob->cbData - i - 1] = temp;
00860             }
00861         }
00862     }
00863     TRACE("returning %d (%08x)\n", ret, GetLastError());
00864     return ret;
00865 }
00866 
00867 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
00868  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
00869  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
00870 {
00871     BOOL ret = TRUE;
00872 
00873     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
00874      pDecodePara, pvStructInfo, *pcbStructInfo);
00875 
00876     __TRY
00877     {
00878         struct AsnDecodeSequenceItem items[] = {
00879          { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
00880            CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
00881            offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
00882          { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
00883            SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
00884            sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
00885            offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
00886          { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
00887            CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
00888            offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
00889         };
00890 
00891         if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
00892             items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
00893         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
00894          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
00895          pcbStructInfo, NULL, NULL);
00896     }
00897     __EXCEPT_PAGE_FAULT
00898     {
00899         SetLastError(STATUS_ACCESS_VIOLATION);
00900         ret = FALSE;
00901     }
00902     __ENDTRY
00903 
00904     TRACE("Returning %d (%08x)\n", ret, GetLastError());
00905     return ret;
00906 }
00907 
00908 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
00909  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
00910 {
00911     BOOL ret;
00912     DWORD dataLen;
00913 
00914     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
00915     {
00916         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
00917 
00918         ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
00919          dwFlags, pvStructInfo, pcbStructInfo, NULL);
00920         if (pcbDecoded)
00921             *pcbDecoded = 1 + lenBytes + dataLen;
00922     }
00923     return ret;
00924 }
00925 
00926 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
00927  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
00928 {
00929     BOOL ret;
00930 
00931     struct AsnDecodeSequenceItem items[] = {
00932      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
00933        CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
00934      { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
00935        CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
00936     };
00937 
00938     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
00939      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
00940      pcbDecoded, NULL);
00941     return ret;
00942 }
00943 
00944 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
00945  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00946  DWORD *pcbDecoded)
00947 {
00948     BOOL ret = TRUE;
00949     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
00950      offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
00951      FINALMEMBERSIZE(CERT_INFO, cExtension),
00952      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
00953      offsetof(CERT_EXTENSION, pszObjId) };
00954 
00955     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
00956      pvStructInfo, *pcbStructInfo, pcbDecoded);
00957 
00958     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
00959      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
00960     return ret;
00961 }
00962 
00963 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
00964  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
00965  DWORD *pcbDecoded)
00966 {
00967     BOOL ret;
00968     DWORD dataLen;
00969 
00970     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
00971     {
00972         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
00973 
00974         ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
00975          dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
00976         if (ret && pcbDecoded)
00977             *pcbDecoded = 1 + lenBytes + dataLen;
00978     }
00979     return ret;
00980 }
00981 
00982 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
00983  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
00984  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
00985 {
00986     BOOL ret = TRUE;
00987     struct AsnDecodeSequenceItem items[] = {
00988      { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
00989        CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
00990      { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
00991        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
00992        TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
00993      { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
00994        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
00995        FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
00996      { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
00997        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
00998        Issuer.pbData) },
00999      { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
01000        CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
01001        FALSE, 0 },
01002      { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
01003        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
01004        Subject.pbData) },
01005      { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
01006        CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
01007        FALSE, TRUE, offsetof(CERT_INFO,
01008        SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
01009      { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
01010        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
01011        offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
01012      { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
01013        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
01014        offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
01015      { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
01016        CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
01017        TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
01018     };
01019 
01020     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01021      pDecodePara, pvStructInfo, *pcbStructInfo);
01022 
01023     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
01024      pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
01025      NULL, NULL);
01026     if (ret && pvStructInfo)
01027     {
01028         CERT_INFO *info;
01029 
01030         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
01031             info = *(CERT_INFO **)pvStructInfo;
01032         else
01033             info = pvStructInfo;
01034         if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
01035          !info->Subject.cbData)
01036         {
01037             SetLastError(CRYPT_E_ASN1_CORRUPT);
01038             /* Don't need to deallocate, because it should have failed on the
01039              * first pass (and no memory was allocated.)
01040              */
01041             ret = FALSE;
01042         }
01043     }
01044 
01045     TRACE("Returning %d (%08x)\n", ret, GetLastError());
01046     return ret;
01047 }
01048 
01049 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
01050  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01051  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01052 {
01053     BOOL ret = FALSE;
01054 
01055     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01056      pDecodePara, pvStructInfo, *pcbStructInfo);
01057 
01058     __TRY
01059     {
01060         DWORD size = 0;
01061 
01062         /* Unless told not to, first try to decode it as a signed cert. */
01063         if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
01064         {
01065             PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
01066 
01067             ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
01068              X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
01069              &signedCert, &size);
01070             if (ret)
01071             {
01072                 size = 0;
01073                 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
01074                  X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
01075                  signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
01076                  pvStructInfo, pcbStructInfo);
01077                 LocalFree(signedCert);
01078             }
01079         }
01080         /* Failing that, try it as an unsigned cert */
01081         if (!ret)
01082         {
01083             size = 0;
01084             ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
01085              X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
01086              pDecodePara, pvStructInfo, pcbStructInfo);
01087         }
01088     }
01089     __EXCEPT_PAGE_FAULT
01090     {
01091         SetLastError(STATUS_ACCESS_VIOLATION);
01092     }
01093     __ENDTRY
01094 
01095     TRACE("Returning %d (%08x)\n", ret, GetLastError());
01096     return ret;
01097 }
01098 
01099 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
01100  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01101  DWORD *pcbDecoded)
01102 {
01103     BOOL ret = TRUE;
01104     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
01105      offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
01106      FINALMEMBERSIZE(CRL_ENTRY, cExtension),
01107      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
01108      offsetof(CERT_EXTENSION, pszObjId) };
01109 
01110     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
01111      pvStructInfo, *pcbStructInfo, pcbDecoded);
01112 
01113     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
01114      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
01115     return ret;
01116 }
01117 
01118 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
01119  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01120 {
01121     BOOL ret;
01122     struct AsnDecodeSequenceItem items[] = {
01123      { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
01124        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
01125        offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
01126      { 0, offsetof(CRL_ENTRY, RevocationDate),
01127        CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
01128      { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
01129        CRYPT_AsnDecodeCRLEntryExtensions,
01130        FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
01131        offsetof(CRL_ENTRY, rgExtension), 0 },
01132     };
01133     PCRL_ENTRY entry = pvStructInfo;
01134 
01135     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
01136      *pcbStructInfo);
01137 
01138     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
01139      pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
01140      entry ? entry->SerialNumber.pbData : NULL);
01141     if (ret && entry && !entry->SerialNumber.cbData)
01142     {
01143         WARN("empty CRL entry serial number\n");
01144         SetLastError(CRYPT_E_ASN1_CORRUPT);
01145         ret = FALSE;
01146     }
01147     return ret;
01148 }
01149 
01150 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
01151  * whose rgCRLEntry member has been set prior to calling.
01152  */
01153 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
01154  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01155 {
01156     BOOL ret;
01157     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
01158      offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
01159      MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
01160      CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
01161      offsetof(CRL_ENTRY, SerialNumber.pbData) };
01162 
01163     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
01164      pvStructInfo, *pcbStructInfo, pcbDecoded);
01165 
01166     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
01167      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
01168     TRACE("Returning %d (%08x)\n", ret, GetLastError());
01169     return ret;
01170 }
01171 
01172 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
01173  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01174  DWORD *pcbDecoded)
01175 {
01176     BOOL ret = TRUE;
01177     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
01178      offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
01179      FINALMEMBERSIZE(CRL_INFO, cExtension),
01180      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
01181      offsetof(CERT_EXTENSION, pszObjId) };
01182 
01183     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
01184      pvStructInfo, *pcbStructInfo, pcbDecoded);
01185 
01186     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
01187      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
01188     return ret;
01189 }
01190 
01191 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
01192  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01193  DWORD *pcbDecoded)
01194 {
01195     BOOL ret;
01196     DWORD dataLen;
01197 
01198     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01199     {
01200         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01201 
01202         ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
01203          dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
01204         if (ret && pcbDecoded)
01205             *pcbDecoded = 1 + lenBytes + dataLen;
01206     }
01207     return ret;
01208 }
01209 
01210 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
01211  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01212  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01213 {
01214     struct AsnDecodeSequenceItem items[] = {
01215      { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
01216        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
01217      { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
01218        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
01219        FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
01220      { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
01221        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
01222        Issuer.pbData) },
01223      { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
01224        sizeof(FILETIME), FALSE, FALSE, 0 },
01225      { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
01226        sizeof(FILETIME), TRUE, FALSE, 0 },
01227      { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
01228        CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
01229        TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
01230      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
01231        CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
01232        TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
01233     };
01234     BOOL ret = TRUE;
01235 
01236     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01237      pDecodePara, pvStructInfo, *pcbStructInfo);
01238 
01239     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
01240      pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
01241      NULL, NULL);
01242 
01243     TRACE("Returning %d (%08x)\n", ret, GetLastError());
01244     return ret;
01245 }
01246 
01247 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
01248  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01249  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01250 {
01251     BOOL ret = FALSE;
01252 
01253     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01254      pDecodePara, pvStructInfo, *pcbStructInfo);
01255 
01256     __TRY
01257     {
01258         DWORD size = 0;
01259 
01260         /* Unless told not to, first try to decode it as a signed crl. */
01261         if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
01262         {
01263             PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
01264 
01265             ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
01266              X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
01267              &signedCrl, &size);
01268             if (ret)
01269             {
01270                 size = 0;
01271                 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
01272                  X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
01273                  signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
01274                  pvStructInfo, pcbStructInfo);
01275                 LocalFree(signedCrl);
01276             }
01277         }
01278         /* Failing that, try it as an unsigned crl */
01279         if (!ret)
01280         {
01281             size = 0;
01282             ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
01283              X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
01284              dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
01285         }
01286     }
01287     __EXCEPT_PAGE_FAULT
01288     {
01289         SetLastError(STATUS_ACCESS_VIOLATION);
01290     }
01291     __ENDTRY
01292 
01293     TRACE("Returning %d (%08x)\n", ret, GetLastError());
01294     return ret;
01295 }
01296 
01297 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
01298  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01299 {
01300     BOOL ret = TRUE;
01301     DWORD dataLen;
01302 
01303     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01304      pvStructInfo, *pcbStructInfo);
01305 
01306     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01307     {
01308         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01309         DWORD bytesNeeded = sizeof(LPSTR);
01310 
01311         if (dataLen)
01312         {
01313             /* The largest possible string for the first two components
01314              * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
01315              */
01316             char firstTwo[6];
01317             const BYTE *ptr;
01318 
01319             snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
01320              pbEncoded[1 + lenBytes] / 40,
01321              pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
01322              * 40);
01323             bytesNeeded += strlen(firstTwo) + 1;
01324             for (ptr = pbEncoded + 2 + lenBytes; ret &&
01325              ptr - pbEncoded - 1 - lenBytes < dataLen; )
01326             {
01327                 /* large enough for ".4000000" */
01328                 char str[9];
01329                 int val = 0;
01330 
01331                 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
01332                  (*ptr & 0x80))
01333                 {
01334                     val <<= 7;
01335                     val |= *ptr & 0x7f;
01336                     ptr++;
01337                 }
01338                 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
01339                  (*ptr & 0x80))
01340                 {
01341                     SetLastError(CRYPT_E_ASN1_CORRUPT);
01342                     ret = FALSE;
01343                 }
01344                 else
01345                 {
01346                     val <<= 7;
01347                     val |= *ptr++;
01348                     snprintf(str, sizeof(str), ".%d", val);
01349                     bytesNeeded += strlen(str);
01350                 }
01351             }
01352         }
01353         if (pcbDecoded)
01354             *pcbDecoded = 1 + lenBytes + dataLen;
01355         if (!pvStructInfo)
01356             *pcbStructInfo = bytesNeeded;
01357         else if (*pcbStructInfo < bytesNeeded)
01358         {
01359             *pcbStructInfo = bytesNeeded;
01360             SetLastError(ERROR_MORE_DATA);
01361             ret = FALSE;
01362         }
01363         else
01364         {
01365             if (dataLen)
01366             {
01367                 const BYTE *ptr;
01368                 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
01369 
01370                 *pszObjId = 0;
01371                 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
01372                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
01373                  40) * 40);
01374                 pszObjId += strlen(pszObjId);
01375                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
01376                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
01377                 {
01378                     int val = 0;
01379 
01380                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
01381                      (*ptr & 0x80))
01382                     {
01383                         val <<= 7;
01384                         val |= *ptr & 0x7f;
01385                         ptr++;
01386                     }
01387                     val <<= 7;
01388                     val |= *ptr++;
01389                     sprintf(pszObjId, ".%d", val);
01390                     pszObjId += strlen(pszObjId);
01391                 }
01392             }
01393             else
01394                 *(LPSTR *)pvStructInfo = NULL;
01395             *pcbStructInfo = bytesNeeded;
01396         }
01397     }
01398     return ret;
01399 }
01400 
01401 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
01402  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01403 {
01404     BOOL ret;
01405 
01406     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01407      pvStructInfo, *pcbStructInfo);
01408 
01409     if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
01410         ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
01411          pvStructInfo, pcbStructInfo, pcbDecoded);
01412     else
01413     {
01414         SetLastError(CRYPT_E_ASN1_BADTAG);
01415         ret = FALSE;
01416     }
01417     return ret;
01418 }
01419 
01420 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
01421  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01422 {
01423     struct AsnDecodeSequenceItem items[] = {
01424      { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
01425        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
01426        offsetof(CERT_EXTENSION, pszObjId), 0 },
01427      { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
01428        sizeof(BOOL), TRUE, FALSE, 0, 0 },
01429      { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
01430        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
01431        offsetof(CERT_EXTENSION, Value.pbData) },
01432     };
01433     BOOL ret = TRUE;
01434     PCERT_EXTENSION ext = pvStructInfo;
01435 
01436     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
01437      *pcbStructInfo);
01438 
01439     if (ext)
01440         TRACE("ext->pszObjId is %p\n", ext->pszObjId);
01441     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
01442      pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
01443      pcbDecoded, ext ? ext->pszObjId : NULL);
01444     if (ext)
01445         TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
01446          debugstr_a(ext->pszObjId));
01447     TRACE("returning %d (%08x)\n", ret, GetLastError());
01448     return ret;
01449 }
01450 
01451 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
01452  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01453  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01454 {
01455     BOOL ret = TRUE;
01456 
01457     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01458      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
01459 
01460     __TRY
01461     {
01462         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
01463          offsetof(CERT_EXTENSIONS, cExtension),
01464          offsetof(CERT_EXTENSIONS, rgExtension),
01465          sizeof(CERT_EXTENSIONS),
01466          CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
01467          offsetof(CERT_EXTENSION, pszObjId) };
01468         CERT_EXTENSIONS *exts = pvStructInfo;
01469 
01470         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
01471             exts->rgExtension = (CERT_EXTENSION *)(exts + 1);
01472         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
01473          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
01474     }
01475     __EXCEPT_PAGE_FAULT
01476     {
01477         SetLastError(STATUS_ACCESS_VIOLATION);
01478         ret = FALSE;
01479     }
01480     __ENDTRY
01481     return ret;
01482 }
01483 
01484 /* Warning: this assumes the address of value->Value.pbData is already set, in
01485  * order to avoid overwriting memory.  (In some cases, it may change it, if it
01486  * doesn't copy anything to memory.)  Be sure to set it correctly!
01487  */
01488 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
01489  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01490  DWORD *pcbDecoded)
01491 {
01492     BOOL ret = TRUE;
01493     DWORD dataLen;
01494     CERT_NAME_VALUE *value = pvStructInfo;
01495 
01496     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01497     {
01498         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01499         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
01500 
01501         switch (pbEncoded[0])
01502         {
01503         case ASN_OCTETSTRING:
01504             valueType = CERT_RDN_OCTET_STRING;
01505             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01506                 bytesNeeded += dataLen;
01507             break;
01508         case ASN_NUMERICSTRING:
01509             valueType = CERT_RDN_NUMERIC_STRING;
01510             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01511                 bytesNeeded += dataLen;
01512             break;
01513         case ASN_PRINTABLESTRING:
01514             valueType = CERT_RDN_PRINTABLE_STRING;
01515             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01516                 bytesNeeded += dataLen;
01517             break;
01518         case ASN_IA5STRING:
01519             valueType = CERT_RDN_IA5_STRING;
01520             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01521                 bytesNeeded += dataLen;
01522             break;
01523         case ASN_T61STRING:
01524             valueType = CERT_RDN_T61_STRING;
01525             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01526                 bytesNeeded += dataLen;
01527             break;
01528         case ASN_VIDEOTEXSTRING:
01529             valueType = CERT_RDN_VIDEOTEX_STRING;
01530             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01531                 bytesNeeded += dataLen;
01532             break;
01533         case ASN_GRAPHICSTRING:
01534             valueType = CERT_RDN_GRAPHIC_STRING;
01535             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01536                 bytesNeeded += dataLen;
01537             break;
01538         case ASN_VISIBLESTRING:
01539             valueType = CERT_RDN_VISIBLE_STRING;
01540             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01541                 bytesNeeded += dataLen;
01542             break;
01543         case ASN_GENERALSTRING:
01544             valueType = CERT_RDN_GENERAL_STRING;
01545             if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01546                 bytesNeeded += dataLen;
01547             break;
01548         case ASN_UNIVERSALSTRING:
01549             FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
01550             SetLastError(CRYPT_E_ASN1_BADTAG);
01551             return FALSE;
01552         case ASN_BMPSTRING:
01553             valueType = CERT_RDN_BMP_STRING;
01554             bytesNeeded += dataLen;
01555             break;
01556         case ASN_UTF8STRING:
01557             valueType = CERT_RDN_UTF8_STRING;
01558             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
01559              (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
01560             break;
01561         default:
01562             SetLastError(CRYPT_E_ASN1_BADTAG);
01563             return FALSE;
01564         }
01565 
01566         if (pcbDecoded)
01567             *pcbDecoded = 1 + lenBytes + dataLen;
01568         if (!value)
01569             *pcbStructInfo = bytesNeeded;
01570         else if (*pcbStructInfo < bytesNeeded)
01571         {
01572             *pcbStructInfo = bytesNeeded;
01573             SetLastError(ERROR_MORE_DATA);
01574             ret = FALSE;
01575         }
01576         else
01577         {
01578             *pcbStructInfo = bytesNeeded;
01579             value->dwValueType = valueType;
01580             if (dataLen)
01581             {
01582                 DWORD i;
01583 
01584                 assert(value->Value.pbData);
01585                 switch (pbEncoded[0])
01586                 {
01587                 case ASN_OCTETSTRING:
01588                 case ASN_NUMERICSTRING:
01589                 case ASN_PRINTABLESTRING:
01590                 case ASN_IA5STRING:
01591                 case ASN_T61STRING:
01592                 case ASN_VIDEOTEXSTRING:
01593                 case ASN_GRAPHICSTRING:
01594                 case ASN_VISIBLESTRING:
01595                 case ASN_GENERALSTRING:
01596                     value->Value.cbData = dataLen;
01597                     if (dataLen)
01598                     {
01599                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01600                             memcpy(value->Value.pbData,
01601                              pbEncoded + 1 + lenBytes, dataLen);
01602                         else
01603                             value->Value.pbData = (LPBYTE)pbEncoded + 1 +
01604                              lenBytes;
01605                     }
01606                     break;
01607                 case ASN_BMPSTRING:
01608                 {
01609                     LPWSTR str = (LPWSTR)value->Value.pbData;
01610 
01611                     value->Value.cbData = dataLen;
01612                     for (i = 0; i < dataLen / 2; i++)
01613                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
01614                          pbEncoded[1 + lenBytes + 2 * i + 1];
01615                     break;
01616                 }
01617                 case ASN_UTF8STRING:
01618                 {
01619                     LPWSTR str = (LPWSTR)value->Value.pbData;
01620 
01621                     value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
01622                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, 
01623                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
01624                     break;
01625                 }
01626                 }
01627             }
01628             else
01629             {
01630                 value->Value.cbData = 0;
01631                 value->Value.pbData = NULL;
01632             }
01633         }
01634     }
01635     return ret;
01636 }
01637 
01638 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
01639  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01640  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01641 {
01642     BOOL ret = TRUE;
01643 
01644     __TRY
01645     {
01646         ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
01647          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
01648         if (ret && pvStructInfo)
01649         {
01650             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
01651              pcbStructInfo, *pcbStructInfo);
01652             if (ret)
01653             {
01654                 CERT_NAME_VALUE *value;
01655 
01656                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
01657                     pvStructInfo = *(BYTE **)pvStructInfo;
01658                 value = pvStructInfo;
01659                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
01660                 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
01661                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
01662                  pcbStructInfo, NULL);
01663                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
01664                     CRYPT_FreeSpace(pDecodePara, value);
01665             }
01666         }
01667     }
01668     __EXCEPT_PAGE_FAULT
01669     {
01670         SetLastError(STATUS_ACCESS_VIOLATION);
01671         ret = FALSE;
01672     }
01673     __ENDTRY
01674     return ret;
01675 }
01676 
01677 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
01678  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01679  DWORD *pcbDecoded)
01680 {
01681     BOOL ret = TRUE;
01682     DWORD dataLen;
01683     CERT_NAME_VALUE *value = pvStructInfo;
01684 
01685     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01686     {
01687         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01688         DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
01689 
01690         switch (pbEncoded[0])
01691         {
01692         case ASN_NUMERICSTRING:
01693             valueType = CERT_RDN_NUMERIC_STRING;
01694             if (dataLen)
01695                 bytesNeeded += (dataLen + 1) * 2;
01696             break;
01697         case ASN_PRINTABLESTRING:
01698             valueType = CERT_RDN_PRINTABLE_STRING;
01699             if (dataLen)
01700                 bytesNeeded += (dataLen + 1) * 2;
01701             break;
01702         case ASN_IA5STRING:
01703             valueType = CERT_RDN_IA5_STRING;
01704             if (dataLen)
01705                 bytesNeeded += (dataLen + 1) * 2;
01706             break;
01707         case ASN_T61STRING:
01708             valueType = CERT_RDN_T61_STRING;
01709             if (dataLen)
01710                 bytesNeeded += (dataLen + 1) * 2;
01711             break;
01712         case ASN_VIDEOTEXSTRING:
01713             valueType = CERT_RDN_VIDEOTEX_STRING;
01714             if (dataLen)
01715                 bytesNeeded += (dataLen + 1) * 2;
01716             break;
01717         case ASN_GRAPHICSTRING:
01718             valueType = CERT_RDN_GRAPHIC_STRING;
01719             if (dataLen)
01720                 bytesNeeded += (dataLen + 1) * 2;
01721             break;
01722         case ASN_VISIBLESTRING:
01723             valueType = CERT_RDN_VISIBLE_STRING;
01724             if (dataLen)
01725                 bytesNeeded += (dataLen + 1) * 2;
01726             break;
01727         case ASN_GENERALSTRING:
01728             valueType = CERT_RDN_GENERAL_STRING;
01729             if (dataLen)
01730                 bytesNeeded += (dataLen + 1) * 2;
01731             break;
01732         case ASN_UNIVERSALSTRING:
01733             valueType = CERT_RDN_UNIVERSAL_STRING;
01734             if (dataLen)
01735                 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
01736             break;
01737         case ASN_BMPSTRING:
01738             valueType = CERT_RDN_BMP_STRING;
01739             if (dataLen)
01740                 bytesNeeded += dataLen + sizeof(WCHAR);
01741             break;
01742         case ASN_UTF8STRING:
01743             valueType = CERT_RDN_UTF8_STRING;
01744             if (dataLen)
01745                 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
01746                  (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
01747             break;
01748         default:
01749             SetLastError(CRYPT_E_ASN1_BADTAG);
01750             return FALSE;
01751         }
01752 
01753         if (pcbDecoded)
01754             *pcbDecoded = 1 + lenBytes + dataLen;
01755         if (!value)
01756             *pcbStructInfo = bytesNeeded;
01757         else if (*pcbStructInfo < bytesNeeded)
01758         {
01759             *pcbStructInfo = bytesNeeded;
01760             SetLastError(ERROR_MORE_DATA);
01761             ret = FALSE;
01762         }
01763         else
01764         {
01765             *pcbStructInfo = bytesNeeded;
01766             value->dwValueType = valueType;
01767             if (dataLen)
01768             {
01769                 DWORD i;
01770                 LPWSTR str = (LPWSTR)value->Value.pbData;
01771 
01772                 assert(value->Value.pbData);
01773                 switch (pbEncoded[0])
01774                 {
01775                 case ASN_NUMERICSTRING:
01776                 case ASN_PRINTABLESTRING:
01777                 case ASN_IA5STRING:
01778                 case ASN_T61STRING:
01779                 case ASN_VIDEOTEXSTRING:
01780                 case ASN_GRAPHICSTRING:
01781                 case ASN_VISIBLESTRING:
01782                 case ASN_GENERALSTRING:
01783                     value->Value.cbData = dataLen * 2;
01784                     for (i = 0; i < dataLen; i++)
01785                         str[i] = pbEncoded[1 + lenBytes + i];
01786                     str[i] = 0;
01787                     break;
01788                 case ASN_UNIVERSALSTRING:
01789                     value->Value.cbData = dataLen / 2;
01790                     for (i = 0; i < dataLen / 4; i++)
01791                         str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
01792                          | pbEncoded[1 + lenBytes + 2 * i + 3];
01793                     str[i] = 0;
01794                     break;
01795                 case ASN_BMPSTRING:
01796                     value->Value.cbData = dataLen;
01797                     for (i = 0; i < dataLen / 2; i++)
01798                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
01799                          pbEncoded[1 + lenBytes + 2 * i + 1];
01800                     str[i] = 0;
01801                     break;
01802                 case ASN_UTF8STRING:
01803                     value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
01804                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
01805                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
01806                     *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
01807                     value->Value.cbData += sizeof(WCHAR);
01808                     break;
01809                 }
01810             }
01811             else
01812             {
01813                 value->Value.cbData = 0;
01814                 value->Value.pbData = NULL;
01815             }
01816         }
01817     }
01818     return ret;
01819 }
01820 
01821 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
01822  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01823  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01824 {
01825     BOOL ret = TRUE;
01826 
01827     __TRY
01828     {
01829         ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
01830          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
01831         if (ret && pvStructInfo)
01832         {
01833             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
01834              pcbStructInfo, *pcbStructInfo);
01835             if (ret)
01836             {
01837                 CERT_NAME_VALUE *value;
01838 
01839                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
01840                     pvStructInfo = *(BYTE **)pvStructInfo;
01841                 value = pvStructInfo;
01842                 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
01843                 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
01844                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
01845                  pcbStructInfo, NULL);
01846                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
01847                     CRYPT_FreeSpace(pDecodePara, value);
01848             }
01849         }
01850     }
01851     __EXCEPT_PAGE_FAULT
01852     {
01853         SetLastError(STATUS_ACCESS_VIOLATION);
01854         ret = FALSE;
01855     }
01856     __ENDTRY
01857     return ret;
01858 }
01859 
01860 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
01861  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01862 {
01863     BOOL ret;
01864     struct AsnDecodeSequenceItem items[] = {
01865      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
01866        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
01867        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
01868      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
01869        CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
01870        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
01871     };
01872     CERT_RDN_ATTR *attr = pvStructInfo;
01873 
01874     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01875      pvStructInfo, *pcbStructInfo);
01876 
01877     if (attr)
01878         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
01879     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
01880      pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
01881      attr ? attr->pszObjId : NULL);
01882     if (attr)
01883     {
01884         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
01885          debugstr_a(attr->pszObjId));
01886         TRACE("attr->dwValueType is %d\n", attr->dwValueType);
01887     }
01888     TRACE("returning %d (%08x)\n", ret, GetLastError());
01889     return ret;
01890 }
01891 
01892 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
01893  DWORD dwFlags,  void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01894 {
01895     BOOL ret = TRUE;
01896     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
01897      offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
01898      sizeof(CERT_RDN),
01899      CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
01900      offsetof(CERT_RDN_ATTR, pszObjId) };
01901 
01902     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
01903      NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
01904     return ret;
01905 }
01906 
01907 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
01908  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01909  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
01910 {
01911     BOOL ret = TRUE;
01912 
01913     __TRY
01914     {
01915         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
01916          offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
01917          sizeof(CERT_NAME_INFO),
01918          CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
01919          offsetof(CERT_RDN, rgRDNAttr) };
01920         DWORD bytesNeeded;
01921 
01922         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
01923          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
01924          NULL);
01925         if (ret)
01926         {
01927             if (!pvStructInfo)
01928                 *pcbStructInfo = bytesNeeded;
01929             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
01930              pvStructInfo, pcbStructInfo, bytesNeeded)))
01931             {
01932                 CERT_NAME_INFO *info;
01933 
01934                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
01935                     pvStructInfo = *(BYTE **)pvStructInfo;
01936                 info = pvStructInfo;
01937                 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
01938                  sizeof(CERT_NAME_INFO));
01939                 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
01940                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
01941                  &bytesNeeded, NULL);
01942                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
01943                     CRYPT_FreeSpace(pDecodePara, info);
01944             }
01945         }
01946     }
01947     __EXCEPT_PAGE_FAULT
01948     {
01949         SetLastError(STATUS_ACCESS_VIOLATION);
01950         ret = FALSE;
01951     }
01952     __ENDTRY
01953     return ret;
01954 }
01955 
01956 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
01957  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01958  DWORD *pcbDecoded)
01959 {
01960     BOOL ret;
01961     struct AsnDecodeSequenceItem items[] = {
01962      { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
01963        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
01964        offsetof(CERT_RDN_ATTR, pszObjId), 0 },
01965      { 0, offsetof(CERT_RDN_ATTR, dwValueType),
01966        CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
01967        FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
01968     };
01969     CERT_RDN_ATTR *attr = pvStructInfo;
01970 
01971     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01972      pvStructInfo, *pcbStructInfo);
01973 
01974     if (attr)
01975         TRACE("attr->pszObjId is %p\n", attr->pszObjId);
01976     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
01977      pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
01978      attr ? attr->pszObjId : NULL);
01979     if (attr)
01980     {
01981         TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
01982          debugstr_a(attr->pszObjId));
01983         TRACE("attr->dwValueType is %d\n", attr->dwValueType);
01984     }
01985     TRACE("returning %d (%08x)\n", ret, GetLastError());
01986     return ret;
01987 }
01988 
01989 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
01990  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
01991 {
01992     BOOL ret = TRUE;
01993     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
01994      offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
01995      sizeof(CERT_RDN),
01996      CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
01997      offsetof(CERT_RDN_ATTR, pszObjId) };
01998 
01999     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
02000      NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02001     return ret;
02002 }
02003 
02004 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
02005  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02006  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
02007 {
02008     BOOL ret = TRUE;
02009 
02010     __TRY
02011     {
02012         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
02013          offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
02014          sizeof(CERT_NAME_INFO),
02015          CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
02016          offsetof(CERT_RDN, rgRDNAttr) };
02017         DWORD bytesNeeded;
02018 
02019         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02020          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
02021          NULL);
02022         if (ret)
02023         {
02024             if (!pvStructInfo)
02025                 *pcbStructInfo = bytesNeeded;
02026             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
02027              pvStructInfo, pcbStructInfo, bytesNeeded)))
02028             {
02029                 CERT_NAME_INFO *info;
02030 
02031                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
02032                     pvStructInfo = *(BYTE **)pvStructInfo;
02033                 info = pvStructInfo;
02034                 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
02035                  sizeof(CERT_NAME_INFO));
02036                 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02037                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
02038                  &bytesNeeded, NULL);
02039                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
02040                     CRYPT_FreeSpace(pDecodePara, info);
02041             }
02042         }
02043     }
02044     __EXCEPT_PAGE_FAULT
02045     {
02046         SetLastError(STATUS_ACCESS_VIOLATION);
02047         ret = FALSE;
02048     }
02049     __ENDTRY
02050     return ret;
02051 }
02052 
02053 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
02054  DWORD *pcbDecoded)
02055 {
02056     BOOL ret = TRUE, done = FALSE;
02057     DWORD indefiniteNestingLevels = 0, decoded = 0;
02058 
02059     TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
02060 
02061     do {
02062         DWORD dataLen;
02063 
02064         if (!cbEncoded)
02065             done = TRUE;
02066         else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
02067          &dataLen)))
02068         {
02069             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02070 
02071             if (dataLen == CMSG_INDEFINITE_LENGTH)
02072             {
02073                 indefiniteNestingLevels++;
02074                 pbEncoded += 1 + lenBytes;
02075                 cbEncoded -= 1 + lenBytes;
02076                 decoded += 1 + lenBytes;
02077                 TRACE("indefiniteNestingLevels = %d\n",
02078                  indefiniteNestingLevels);
02079             }
02080             else
02081             {
02082                 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
02083                  indefiniteNestingLevels)
02084                 {
02085                     indefiniteNestingLevels--;
02086                     TRACE("indefiniteNestingLevels = %d\n",
02087                      indefiniteNestingLevels);
02088                 }
02089                 pbEncoded += 1 + lenBytes + dataLen;
02090                 cbEncoded -= 1 + lenBytes + dataLen;
02091                 decoded += 1 + lenBytes + dataLen;
02092                 if (!indefiniteNestingLevels)
02093                     done = TRUE;
02094             }
02095         }
02096     } while (ret && !done);
02097     /* If we haven't found all 0 TLVs, we haven't found the end */
02098     if (ret && indefiniteNestingLevels)
02099     {
02100         SetLastError(CRYPT_E_ASN1_EOD);
02101         ret = FALSE;
02102     }
02103     if (ret)
02104         *pcbDecoded = decoded;
02105     TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
02106     return ret;
02107 }
02108 
02109 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
02110  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02111  DWORD *pcbDecoded)
02112 {
02113     BOOL ret = TRUE;
02114     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
02115 
02116     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02117      pvStructInfo, *pcbStructInfo);
02118 
02119     if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
02120     {
02121         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
02122             bytesNeeded += encodedLen;
02123         if (!pvStructInfo)
02124             *pcbStructInfo = bytesNeeded;
02125         else if (*pcbStructInfo < bytesNeeded)
02126         {
02127             SetLastError(ERROR_MORE_DATA);
02128             *pcbStructInfo = bytesNeeded;
02129             ret = FALSE;
02130         }
02131         else
02132         {
02133             PCRYPT_OBJID_BLOB blob = pvStructInfo;
02134 
02135             *pcbStructInfo = bytesNeeded;
02136             blob->cbData = encodedLen;
02137             if (encodedLen)
02138             {
02139                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
02140                     blob->pbData = (LPBYTE)pbEncoded;
02141                 else
02142                 {
02143                     assert(blob->pbData);
02144                     memcpy(blob->pbData, pbEncoded, blob->cbData);
02145                 }
02146             }
02147             else
02148                 blob->pbData = NULL;
02149         }
02150         if (pcbDecoded)
02151             *pcbDecoded = encodedLen;
02152     }
02153     return ret;
02154 }
02155 
02156 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
02157  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
02158 {
02159     BOOL ret;
02160     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
02161      offsetof(CTL_USAGE, cUsageIdentifier),
02162      offsetof(CTL_USAGE, rgpszUsageIdentifier),
02163      sizeof(CTL_USAGE),
02164      CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
02165 
02166     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
02167      NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02168     return ret;
02169 }
02170 
02171 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
02172  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02173  DWORD *pcbDecoded)
02174 {
02175     struct AsnArrayDescriptor arrayDesc = { 0,
02176      offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
02177      FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
02178      CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
02179      offsetof(CRYPT_ATTRIBUTE, pszObjId) };
02180     BOOL ret;
02181 
02182     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02183      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02184     return ret;
02185 }
02186 
02187 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
02188  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
02189 {
02190     struct AsnDecodeSequenceItem items[] = {
02191      { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
02192        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
02193        offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
02194      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
02195        CRYPT_AsnDecodeCTLEntryAttributes,
02196        FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
02197        offsetof(CTL_ENTRY, rgAttribute), 0 },
02198     };
02199     BOOL ret = TRUE;
02200     CTL_ENTRY *entry = pvStructInfo;
02201 
02202     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
02203      *pcbStructInfo);
02204 
02205     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02206      pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
02207      pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
02208     return ret;
02209 }
02210 
02211 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
02212  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
02213 {
02214     BOOL ret;
02215     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
02216      offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
02217      FINALMEMBERSIZE(CTL_INFO, cExtension),
02218      CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
02219      offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
02220 
02221     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
02222      pvStructInfo, *pcbStructInfo, pcbDecoded);
02223 
02224     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02225      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02226     return ret;
02227 }
02228 
02229 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
02230  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02231  DWORD *pcbDecoded)
02232 {
02233     BOOL ret = TRUE;
02234     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
02235      offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
02236      FINALMEMBERSIZE(CTL_INFO, cExtension),
02237      CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
02238      offsetof(CERT_EXTENSION, pszObjId) };
02239 
02240     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
02241      pvStructInfo, *pcbStructInfo, pcbDecoded);
02242 
02243     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02244      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02245     return ret;
02246 }
02247 
02248 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
02249  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02250  DWORD *pcbDecoded)
02251 {
02252     BOOL ret;
02253     DWORD dataLen;
02254 
02255     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
02256     {
02257         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02258 
02259         ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
02260          dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
02261         if (ret && pcbDecoded)
02262             *pcbDecoded = 1 + lenBytes + dataLen;
02263     }
02264     return ret;
02265 }
02266 
02267 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
02268  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02269  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
02270 {
02271     BOOL ret = FALSE;
02272 
02273     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02274      pDecodePara, pvStructInfo, *pcbStructInfo);
02275 
02276     __TRY
02277     {
02278         struct AsnDecodeSequenceItem items[] = {
02279          { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
02280            CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
02281          { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
02282            CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
02283            offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
02284          { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
02285            CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
02286            TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
02287          { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
02288            CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
02289            TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
02290          { 0, offsetof(CTL_INFO, ThisUpdate),
02291            CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
02292            0 },
02293          { 0, offsetof(CTL_INFO, NextUpdate),
02294            CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
02295            0 },
02296          { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
02297            CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
02298            FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
02299          { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
02300            CRYPT_AsnDecodeCTLEntries,
02301            MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
02302            TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
02303          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
02304            CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
02305            TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
02306         };
02307 
02308         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02309          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
02310          pcbStructInfo, NULL, NULL);
02311     }
02312     __EXCEPT_PAGE_FAULT
02313     {
02314         SetLastError(STATUS_ACCESS_VIOLATION);
02315     }
02316     __ENDTRY
02317     return ret;
02318 }
02319 
02320 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
02321  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02322  DWORD *pcbDecoded)
02323 {
02324     BOOL ret;
02325     struct AsnDecodeSequenceItem items[] = {
02326      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
02327        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
02328        offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
02329      { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
02330        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
02331        offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
02332     };
02333     PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
02334 
02335     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02336      pvStructInfo, *pcbStructInfo);
02337 
02338     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02339      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
02340      pcbDecoded, capability ? capability->pszObjId : NULL);
02341     TRACE("returning %d\n", ret);
02342     return ret;
02343 }
02344 
02345 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
02346  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02347  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
02348 {
02349     BOOL ret = FALSE;
02350 
02351     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02352      pDecodePara, pvStructInfo, *pcbStructInfo);
02353 
02354     __TRY
02355     {
02356         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
02357          offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
02358          offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
02359          sizeof(CRYPT_SMIME_CAPABILITIES),
02360          CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
02361          offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
02362         CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
02363 
02364         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
02365             capabilities->rgCapability = (CRYPT_SMIME_CAPABILITY *)(capabilities + 1);
02366         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02367          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
02368     }
02369     __EXCEPT_PAGE_FAULT
02370     {
02371         SetLastError(STATUS_ACCESS_VIOLATION);
02372     }
02373     __ENDTRY
02374     TRACE("returning %d\n", ret);
02375     return ret;
02376 }
02377 
02378 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
02379  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02380  DWORD *pcbDecoded)
02381 {
02382     BOOL ret = TRUE;
02383     DWORD dataLen;
02384     LPSTR *pStr = pvStructInfo;
02385 
02386     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
02387     {
02388         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02389         DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
02390 
02391         if (pbEncoded[0] != ASN_IA5STRING)
02392         {
02393             SetLastError(CRYPT_E_ASN1_CORRUPT);
02394             ret = FALSE;
02395         }
02396         else
02397         {
02398             bytesNeeded += dataLen;
02399             if (pcbDecoded)
02400                 *pcbDecoded = 1 + lenBytes + dataLen;
02401             if (!pvStructInfo)
02402                 *pcbStructInfo = bytesNeeded;
02403             else if (*pcbStructInfo < bytesNeeded)
02404             {
02405                 *pcbStructInfo = bytesNeeded;
02406                 SetLastError(ERROR_MORE_DATA);
02407                 ret = FALSE;
02408             }
02409             else
02410             {
02411                 *pcbStructInfo = bytesNeeded;
02412                 if (dataLen)
02413                 {
02414                     LPSTR str = *pStr;
02415 
02416                     assert(str);
02417                     memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
02418                     str[dataLen] = 0;
02419                 }
02420                 else
02421                     *pStr = NULL;
02422             }
02423         }
02424     }
02425     return ret;
02426 }
02427 
02428 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
02429  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02430  DWORD *pcbDecoded)
02431 {
02432     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
02433      offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
02434      offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
02435      FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
02436      CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
02437     BOOL ret;
02438 
02439     TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
02440      pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
02441 
02442     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02443      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02444     TRACE("returning %d\n", ret);
02445     return ret;
02446 }
02447 
02448 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
02449  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02450  DWORD *pcbDecoded)
02451 {
02452     BOOL ret;
02453     struct AsnDecodeSequenceItem items[] = {
02454      { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
02455        pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
02456        offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
02457      { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
02458        cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
02459        FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
02460        FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
02461        rgNoticeNumbers), 0 },
02462     };
02463     DWORD bytesNeeded;
02464 
02465     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02466      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
02467 
02468     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02469      pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
02470      NULL);
02471     if (ret)
02472     {
02473         /* The caller is expecting a pointer to a
02474          * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
02475          * CRYPT_AsnDecodeSequence is decoding a
02476          * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.  Increment the bytes
02477          * needed, and decode again if the requisite space is available.
02478          */
02479         bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
02480         if (!pvStructInfo)
02481             *pcbStructInfo = bytesNeeded;
02482         else if (*pcbStructInfo < bytesNeeded)
02483         {
02484             *pcbStructInfo = bytesNeeded;
02485             SetLastError(ERROR_MORE_DATA);
02486             ret = FALSE;
02487         }
02488         else
02489         {
02490             PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
02491 
02492             *pcbStructInfo = bytesNeeded;
02493             /* The pointer (pvStructInfo) passed in points to the first dynamic
02494              * pointer, so use it as the pointer to the
02495              * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
02496              * appropriate offset for the first dynamic pointer within the
02497              * notice reference by pointing to the first memory location past
02498              * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
02499              */
02500             noticeRef =
02501              *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
02502             noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
02503              sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
02504             ret = CRYPT_AsnDecodeSequence(items,
02505              sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02506              NULL, noticeRef, &bytesNeeded, pcbDecoded,
02507              noticeRef->pszOrganization);
02508         }
02509     }
02510     TRACE("returning %d\n", ret);
02511     return ret;
02512 }
02513 
02514 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
02515  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02516  DWORD *pcbDecoded)
02517 {
02518     BOOL ret = TRUE;
02519     DWORD dataLen;
02520 
02521     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
02522     {
02523         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02524         DWORD bytesNeeded = sizeof(LPWSTR);
02525 
02526         switch (pbEncoded[0])
02527         {
02528         case ASN_NUMERICSTRING:
02529             if (dataLen)
02530                 bytesNeeded += (dataLen + 1) * 2;
02531             break;
02532         case ASN_PRINTABLESTRING:
02533             if (dataLen)
02534                 bytesNeeded += (dataLen + 1) * 2;
02535             break;
02536         case ASN_IA5STRING:
02537             if (dataLen)
02538                 bytesNeeded += (dataLen + 1) * 2;
02539             break;
02540         case ASN_T61STRING:
02541             if (dataLen)
02542                 bytesNeeded += (dataLen + 1) * 2;
02543             break;
02544         case ASN_VIDEOTEXSTRING:
02545             if (dataLen)
02546                 bytesNeeded += (dataLen + 1) * 2;
02547             break;
02548         case ASN_GRAPHICSTRING:
02549             if (dataLen)
02550                 bytesNeeded += (dataLen + 1) * 2;
02551             break;
02552         case ASN_VISIBLESTRING:
02553             if (dataLen)
02554                 bytesNeeded += (dataLen + 1) * 2;
02555             break;
02556         case ASN_GENERALSTRING:
02557             if (dataLen)
02558                 bytesNeeded += (dataLen + 1) * 2;
02559             break;
02560         case ASN_UNIVERSALSTRING:
02561             if (dataLen)
02562                 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
02563             break;
02564         case ASN_BMPSTRING:
02565             if (dataLen)
02566                 bytesNeeded += dataLen + sizeof(WCHAR);
02567             break;
02568         case ASN_UTF8STRING:
02569             if (dataLen)
02570                 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
02571                  (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
02572             break;
02573         default:
02574             SetLastError(CRYPT_E_ASN1_BADTAG);
02575             return FALSE;
02576         }
02577 
02578         if (pcbDecoded)
02579             *pcbDecoded = 1 + lenBytes + dataLen;
02580         if (!pvStructInfo)
02581             *pcbStructInfo = bytesNeeded;
02582         else if (*pcbStructInfo < bytesNeeded)
02583         {
02584             *pcbStructInfo = bytesNeeded;
02585             SetLastError(ERROR_MORE_DATA);
02586             ret = FALSE;
02587         }
02588         else
02589         {
02590             LPWSTR *pStr = pvStructInfo;
02591 
02592             *pcbStructInfo = bytesNeeded;
02593             if (dataLen)
02594             {
02595                 DWORD i;
02596                 LPWSTR str = *(LPWSTR *)pStr;
02597 
02598                 assert(str);
02599                 switch (pbEncoded[0])
02600                 {
02601                 case ASN_NUMERICSTRING:
02602                 case ASN_PRINTABLESTRING:
02603                 case ASN_IA5STRING:
02604                 case ASN_T61STRING:
02605                 case ASN_VIDEOTEXSTRING:
02606                 case ASN_GRAPHICSTRING:
02607                 case ASN_VISIBLESTRING:
02608                 case ASN_GENERALSTRING:
02609                     for (i = 0; i < dataLen; i++)
02610                         str[i] = pbEncoded[1 + lenBytes + i];
02611                     str[i] = 0;
02612                     break;
02613                 case ASN_UNIVERSALSTRING:
02614                     for (i = 0; i < dataLen / 4; i++)
02615                         str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
02616                          | pbEncoded[1 + lenBytes + 2 * i + 3];
02617                     str[i] = 0;
02618                     break;
02619                 case ASN_BMPSTRING:
02620                     for (i = 0; i < dataLen / 2; i++)
02621                         str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
02622                          pbEncoded[1 + lenBytes + 2 * i + 1];
02623                     str[i] = 0;
02624                     break;
02625                 case ASN_UTF8STRING:
02626                 {
02627                     int len = MultiByteToWideChar(CP_UTF8, 0,
02628                      (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
02629                      str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
02630                     str[len] = 0;
02631                     break;
02632                 }
02633                 }
02634             }
02635             else
02636                 *pStr = NULL;
02637         }
02638     }
02639     return ret;
02640 }
02641 
02642 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
02643  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
02644  DWORD *pcbStructInfo, DWORD *pcbDecoded)
02645 {
02646     BOOL ret;
02647     struct AsnDecodeSequenceItem items[] = {
02648      { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
02649        pNoticeReference), CRYPT_AsnDecodeNoticeReference,
02650        sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
02651        offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
02652      { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
02653        CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
02654        offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
02655     };
02656     PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
02657 
02658     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02659      pvStructInfo, *pcbStructInfo);
02660 
02661     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02662      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
02663      pcbDecoded, notice ? notice->pNoticeReference : NULL);
02664     TRACE("returning %d\n", ret);
02665     return ret;
02666 }
02667 
02668 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
02669  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
02670  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
02671  void *pvStructInfo, DWORD *pcbStructInfo)
02672 {
02673     BOOL ret = FALSE;
02674 
02675     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02676      pDecodePara, pvStructInfo, *pcbStructInfo);
02677 
02678     __TRY
02679     {
02680         DWORD bytesNeeded;
02681 
02682         ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
02683          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
02684          NULL);
02685         if (ret)
02686         {
02687             if (!pvStructInfo)
02688                 *pcbStructInfo = bytesNeeded;
02689             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
02690              pvStructInfo, pcbStructInfo, bytesNeeded)))
02691             {
02692                 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
02693 
02694                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
02695                     pvStructInfo = *(BYTE **)pvStructInfo;
02696                 notice = pvStructInfo;
02697                 notice->pNoticeReference =
02698                  (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
02699                  ((BYTE *)pvStructInfo +
02700                  sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
02701                 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
02702                  pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
02703                  pvStructInfo, &bytesNeeded, NULL);
02704                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
02705                     CRYPT_FreeSpace(pDecodePara, notice);
02706             }
02707         }
02708     }
02709     __EXCEPT_PAGE_FAULT
02710     {
02711         SetLastError(STATUS_ACCESS_VIOLATION);
02712     }
02713     __ENDTRY
02714     TRACE("returning %d\n", ret);
02715     return ret;
02716 }
02717 
02718 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
02719  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02720  DWORD *pcbDecoded)
02721 {
02722     BOOL ret;
02723     struct AsnArrayDescriptor arrayDesc = { 0,
02724      offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
02725      FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
02726      CRYPT_AsnDecodeCopyBytes,
02727      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
02728 
02729     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
02730      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
02731 
02732     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02733      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02734     return ret;
02735 }
02736 
02737 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
02738  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02739  DWORD *pcbDecoded)
02740 {
02741     BOOL ret;
02742     struct AsnDecodeSequenceItem items[] = {
02743      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
02744        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
02745        offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
02746      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
02747        CRYPT_AsnDecodePKCSAttributeValue,
02748        FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
02749        TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
02750     };
02751     PCRYPT_ATTRIBUTE attr = pvStructInfo;
02752 
02753     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02754      pvStructInfo, *pcbStructInfo);
02755 
02756     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02757      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
02758      pcbDecoded, attr ? attr->pszObjId : NULL);
02759     TRACE("returning %d\n", ret);
02760     return ret;
02761 }
02762 
02763 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
02764  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02765  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
02766 {
02767     BOOL ret = FALSE;
02768 
02769     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02770      pDecodePara, pvStructInfo, *pcbStructInfo);
02771 
02772     __TRY
02773     {
02774         DWORD bytesNeeded;
02775 
02776         ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
02777          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
02778         if (ret)
02779         {
02780             if (!pvStructInfo)
02781                 *pcbStructInfo = bytesNeeded;
02782             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
02783              pvStructInfo, pcbStructInfo, bytesNeeded)))
02784             {
02785                 PCRYPT_ATTRIBUTE attr;
02786 
02787                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
02788                     pvStructInfo = *(BYTE **)pvStructInfo;
02789                 attr = pvStructInfo;
02790                 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
02791                  sizeof(CRYPT_ATTRIBUTE));
02792                 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
02793                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
02794                  NULL);
02795                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
02796                     CRYPT_FreeSpace(pDecodePara, attr);
02797             }
02798         }
02799     }
02800     __EXCEPT_PAGE_FAULT
02801     {
02802         SetLastError(STATUS_ACCESS_VIOLATION);
02803     }
02804     __ENDTRY
02805     TRACE("returning %d\n", ret);
02806     return ret;
02807 }
02808 
02809 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
02810  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02811  DWORD *pcbDecoded)
02812 {
02813     struct AsnArrayDescriptor arrayDesc = { 0,
02814      offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
02815      sizeof(CRYPT_ATTRIBUTES),
02816      CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
02817      offsetof(CRYPT_ATTRIBUTE, pszObjId) };
02818     BOOL ret;
02819 
02820     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
02821      NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
02822     return ret;
02823 }
02824 
02825 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
02826  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02827  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
02828 {
02829     BOOL ret = FALSE;
02830 
02831     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02832      pDecodePara, pvStructInfo, *pcbStructInfo);
02833 
02834     __TRY
02835     {
02836         struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
02837          offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
02838          sizeof(CRYPT_ATTRIBUTES),
02839          CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
02840          TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
02841         CRYPT_ATTRIBUTES *attrs = pvStructInfo;
02842 
02843         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
02844             attrs->rgAttr = (CRYPT_ATTRIBUTE *)(attrs + 1);
02845         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
02846          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
02847     }
02848     __EXCEPT_PAGE_FAULT
02849     {
02850         SetLastError(STATUS_ACCESS_VIOLATION);
02851     }
02852     __ENDTRY
02853     TRACE("returning %d\n", ret);
02854     return ret;
02855 }
02856 
02857 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
02858  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
02859 {
02860     CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
02861     BOOL ret = TRUE;
02862     struct AsnDecodeSequenceItem items[] = {
02863      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
02864        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
02865        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
02866      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
02867        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
02868        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
02869     };
02870 
02871     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
02872      pvStructInfo, *pcbStructInfo, pcbDecoded);
02873 
02874     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02875      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
02876      pcbDecoded, algo ? algo->pszObjId : NULL);
02877     if (ret && pvStructInfo)
02878     {
02879         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
02880          debugstr_a(algo->pszObjId));
02881     }
02882     return ret;
02883 }
02884 
02885 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
02886  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
02887  DWORD *pcbDecoded)
02888 {
02889     BOOL ret = TRUE;
02890     struct AsnDecodeSequenceItem items[] = {
02891      { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
02892        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
02893        FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
02894        Algorithm.pszObjId) },
02895      { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
02896        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
02897        offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
02898     };
02899     PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
02900 
02901     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
02902      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
02903      pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
02904     return ret;
02905 }
02906 
02907 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
02908  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02909  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
02910 {
02911     BOOL ret = TRUE;
02912 
02913     __TRY
02914     {
02915         DWORD bytesNeeded;
02916 
02917         if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
02918          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
02919         {
02920             if (!pvStructInfo)
02921                 *pcbStructInfo = bytesNeeded;
02922             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
02923              pvStructInfo, pcbStructInfo, bytesNeeded)))
02924             {
02925                 PCERT_PUBLIC_KEY_INFO info;
02926 
02927                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
02928                     pvStructInfo = *(BYTE **)pvStructInfo;
02929                 info = pvStructInfo;
02930                 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
02931                  sizeof(CERT_PUBLIC_KEY_INFO);
02932                 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
02933                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
02934                  &bytesNeeded, NULL);
02935                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
02936                     CRYPT_FreeSpace(pDecodePara, info);
02937             }
02938         }
02939     }
02940     __EXCEPT_PAGE_FAULT
02941     {
02942         SetLastError(STATUS_ACCESS_VIOLATION);
02943         ret = FALSE;
02944     }
02945     __ENDTRY
02946     return ret;
02947 }
02948 
02949 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
02950  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
02951 {
02952     BOOL ret;
02953 
02954     if (cbEncoded < 3)
02955     {
02956         SetLastError(CRYPT_E_ASN1_CORRUPT);
02957         return FALSE;
02958     }
02959     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
02960     {
02961         SetLastError(CRYPT_E_ASN1_CORRUPT);
02962         return FALSE;
02963     }
02964     if (pbEncoded[1] > 1)
02965     {
02966         SetLastError(CRYPT_E_ASN1_CORRUPT);
02967         return FALSE;
02968     }
02969     if (pcbDecoded)
02970         *pcbDecoded = 3;
02971     if (!pvStructInfo)
02972     {
02973         *pcbStructInfo = sizeof(BOOL);
02974         ret = TRUE;
02975     }
02976     else if (*pcbStructInfo < sizeof(BOOL))
02977     {
02978         *pcbStructInfo = sizeof(BOOL);
02979         SetLastError(ERROR_MORE_DATA);
02980         ret = FALSE;
02981     }
02982     else
02983     {
02984         *pcbStructInfo = sizeof(BOOL);
02985         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
02986         ret = TRUE;
02987     }
02988     TRACE("returning %d (%08x)\n", ret, GetLastError());
02989     return ret;
02990 }
02991 
02992 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
02993  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
02994 {
02995     PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
02996     DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
02997     BOOL ret;
02998 
02999     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03000      pvStructInfo, *pcbStructInfo);
03001 
03002     if (cbEncoded < 2)
03003     {
03004         SetLastError(CRYPT_E_ASN1_CORRUPT);
03005         return FALSE;
03006     }
03007     lenBytes = GET_LEN_BYTES(pbEncoded[1]);
03008     if (1 + lenBytes > cbEncoded)
03009     {
03010         SetLastError(CRYPT_E_ASN1_CORRUPT);
03011         return FALSE;
03012     }
03013     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
03014     {
03015         switch (pbEncoded[0] & ASN_TYPE_MASK)
03016         {
03017         case 1: /* rfc822Name */
03018         case 2: /* dNSName */
03019         case 6: /* uniformResourceIdentifier */
03020             if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
03021             {
03022                 SetLastError(CRYPT_E_ASN1_RULE);
03023                 ret = FALSE;
03024             }
03025             else
03026                 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
03027             break;
03028         case 4: /* directoryName */
03029         case 7: /* iPAddress */
03030             bytesNeeded += dataLen;
03031             break;
03032         case 8: /* registeredID */
03033             ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
03034              &dataLen, NULL);
03035             if (ret)
03036             {
03037                 /* FIXME: ugly, shouldn't need to know internals of OID decode
03038                  * function to use it.
03039                  */
03040                 bytesNeeded += dataLen - sizeof(LPSTR);
03041             }
03042             break;
03043         case 0: /* otherName */
03044             FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
03045             SetLastError(CRYPT_E_ASN1_BADTAG);
03046             ret = FALSE;
03047             break;
03048         case 3: /* x400Address, unimplemented */
03049         case 5: /* ediPartyName, unimplemented */
03050             TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
03051             SetLastError(CRYPT_E_ASN1_BADTAG);
03052             ret = FALSE;
03053             break;
03054         default:
03055             TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
03056             SetLastError(CRYPT_E_ASN1_CORRUPT);
03057             ret = FALSE;
03058         }
03059         if (ret)
03060         {
03061             if (pcbDecoded)
03062                 *pcbDecoded = 1 + lenBytes + dataLen;
03063             if (!entry)
03064                 *pcbStructInfo = bytesNeeded;
03065             else if (*pcbStructInfo < bytesNeeded)
03066             {
03067                 *pcbStructInfo = bytesNeeded;
03068                 SetLastError(ERROR_MORE_DATA);
03069                 ret = FALSE;
03070             }
03071             else
03072             {
03073                 *pcbStructInfo = bytesNeeded;
03074                 /* MS used values one greater than the asn1 ones.. sigh */
03075                 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
03076                 switch (pbEncoded[0] & ASN_TYPE_MASK)
03077                 {
03078                 case 1: /* rfc822Name */
03079                 case 2: /* dNSName */
03080                 case 6: /* uniformResourceIdentifier */
03081                 {
03082                     DWORD i;
03083 
03084                     for (i = 0; i < dataLen; i++)
03085                         entry->u.pwszURL[i] =
03086                          (WCHAR)pbEncoded[1 + lenBytes + i];
03087                     entry->u.pwszURL[i] = 0;
03088                     TRACE("URL is %p (%s)\n", entry->u.pwszURL,
03089                      debugstr_w(entry->u.pwszURL));
03090                     break;
03091                 }
03092                 case 4: /* directoryName */
03093                     /* The data are memory-equivalent with the IPAddress case,
03094                      * fall-through
03095                      */
03096                 case 7: /* iPAddress */
03097                     /* The next data pointer is in the pwszURL spot, that is,
03098                      * the first 4 bytes.  Need to move it to the next spot.
03099                      */
03100                     entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
03101                     entry->u.IPAddress.cbData = dataLen;
03102                     memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
03103                      dataLen);
03104                     break;
03105                 case 8: /* registeredID */
03106                     ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
03107                      &entry->u.pszRegisteredID, &dataLen, NULL);
03108                     break;
03109                 }
03110             }
03111         }
03112     }
03113     return ret;
03114 }
03115 
03116 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
03117  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03118  DWORD *pcbDecoded)
03119 {
03120     BOOL ret;
03121     struct AsnArrayDescriptor arrayDesc = { 0,
03122      offsetof(CERT_ALT_NAME_INFO, cAltEntry),
03123      offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
03124      sizeof(CERT_ALT_NAME_INFO),
03125      CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
03126      offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
03127 
03128     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
03129      pvStructInfo, *pcbStructInfo, pcbDecoded);
03130 
03131     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
03132      NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
03133     return ret;
03134 }
03135 
03136 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
03137  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03138  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03139 {
03140     BOOL ret;
03141 
03142     __TRY
03143     {
03144         struct AsnDecodeSequenceItem items[] = {
03145          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
03146            CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB),
03147            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
03148          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
03149            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
03150            CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
03151            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
03152          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
03153            CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
03154            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
03155            offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
03156         };
03157 
03158         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03159          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
03160          pcbStructInfo, NULL, NULL);
03161     }
03162     __EXCEPT_PAGE_FAULT
03163     {
03164         SetLastError(STATUS_ACCESS_VIOLATION);
03165         ret = FALSE;
03166     }
03167     __ENDTRY
03168     return ret;
03169 }
03170 
03171 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
03172  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03173  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03174 {
03175     BOOL ret;
03176 
03177     __TRY
03178     {
03179         struct AsnDecodeSequenceItem items[] = {
03180          { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
03181            CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB),
03182            TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
03183          { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
03184            offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
03185            CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
03186            TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
03187            AuthorityCertIssuer.rgAltEntry), 0 },
03188          { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
03189            AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
03190            sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
03191            offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
03192            AuthorityCertSerialNumber.pbData), 0 },
03193         };
03194 
03195         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03196          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
03197          pcbStructInfo, NULL, NULL);
03198     }
03199     __EXCEPT_PAGE_FAULT
03200     {
03201         SetLastError(STATUS_ACCESS_VIOLATION);
03202         ret = FALSE;
03203     }
03204     __ENDTRY
03205     return ret;
03206 }
03207 
03208 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
03209  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03210  DWORD *pcbDecoded)
03211 {
03212     struct AsnDecodeSequenceItem items[] = {
03213      { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
03214        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
03215        offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
03216      { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
03217        CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
03218        TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
03219     };
03220     CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
03221 
03222     return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03223      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
03224      pcbDecoded, descr ? descr->pszAccessMethod : NULL);
03225 }
03226 
03227 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
03228  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03229  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03230 {
03231     BOOL ret;
03232 
03233     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03234      pDecodePara, pvStructInfo, *pcbStructInfo);
03235 
03236     __TRY
03237     {
03238         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
03239          offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
03240          offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
03241          sizeof(CERT_AUTHORITY_INFO_ACCESS),
03242          CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
03243          TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
03244         CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
03245 
03246         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
03247             info->rgAccDescr = (CERT_ACCESS_DESCRIPTION *)(info + 1);
03248         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
03249          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
03250     }
03251     __EXCEPT_PAGE_FAULT
03252     {
03253         SetLastError(STATUS_ACCESS_VIOLATION);
03254         ret = FALSE;
03255     }
03256     __ENDTRY
03257     return ret;
03258 }
03259 
03260 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
03261  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
03262 {
03263     BOOL ret;
03264     DWORD dataLen;
03265 
03266     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
03267      pvStructInfo, *pcbStructInfo, pcbDecoded);
03268 
03269     /* The caller has already checked the tag, no need to check it again.
03270      * Check the outer length is valid:
03271      */
03272     if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
03273     {
03274         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
03275         DWORD innerLen;
03276 
03277         pbEncoded += 1 + lenBytes;
03278         cbEncoded -= 1 + lenBytes;
03279         if (dataLen == CMSG_INDEFINITE_LENGTH)
03280             cbEncoded -= 2; /* space for 0 TLV */
03281         /* Check the inner length is valid: */
03282         if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
03283         {
03284             DWORD decodedLen;
03285 
03286             ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
03287              pvStructInfo, pcbStructInfo, &decodedLen);
03288             if (dataLen == CMSG_INDEFINITE_LENGTH)
03289             {
03290                 if (*(pbEncoded + decodedLen) != 0 ||
03291                  *(pbEncoded + decodedLen + 1) != 0)
03292                 {
03293                     TRACE("expected 0 TLV, got {%02x,%02x}\n",
03294                      *(pbEncoded + decodedLen),
03295                      *(pbEncoded + decodedLen + 1));
03296                     SetLastError(CRYPT_E_ASN1_CORRUPT);
03297                     ret = FALSE;
03298                 }
03299                 else
03300                     decodedLen += 2;
03301             }
03302             if (ret && pcbDecoded)
03303             {
03304                 *pcbDecoded = 1 + lenBytes + decodedLen;
03305                 TRACE("decoded %d bytes\n", *pcbDecoded);
03306             }
03307         }
03308     }
03309     return ret;
03310 }
03311 
03312 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
03313  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03314  DWORD *pcbDecoded)
03315 {
03316     CRYPT_CONTENT_INFO *info = pvStructInfo;
03317     struct AsnDecodeSequenceItem items[] = {
03318      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
03319        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
03320        offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
03321      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
03322        offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
03323        sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
03324        offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
03325     };
03326     BOOL ret;
03327 
03328     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
03329      pvStructInfo, *pcbStructInfo, pcbDecoded);
03330 
03331     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03332      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
03333      pcbDecoded, info ? info->pszObjId : NULL);
03334     return ret;
03335 }
03336 
03337 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
03338  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03339  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03340 {
03341     BOOL ret = FALSE;
03342 
03343     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03344      pDecodePara, pvStructInfo, *pcbStructInfo);
03345 
03346     __TRY
03347     {
03348         ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
03349          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
03350         if (ret && pvStructInfo)
03351         {
03352             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
03353              pcbStructInfo, *pcbStructInfo);
03354             if (ret)
03355             {
03356                 CRYPT_CONTENT_INFO *info;
03357 
03358                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
03359                     pvStructInfo = *(BYTE **)pvStructInfo;
03360                 info = pvStructInfo;
03361                 info->pszObjId = (LPSTR)((BYTE *)info +
03362                  sizeof(CRYPT_CONTENT_INFO));
03363                 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
03364                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
03365                  pcbStructInfo, NULL);
03366                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
03367                     CRYPT_FreeSpace(pDecodePara, info);
03368             }
03369         }
03370     }
03371     __EXCEPT_PAGE_FAULT
03372     {
03373         SetLastError(STATUS_ACCESS_VIOLATION);
03374     }
03375     __ENDTRY
03376     return ret;
03377 }
03378 
03379 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
03380  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
03381  CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
03382 {
03383     BOOL ret;
03384     struct AsnDecodeSequenceItem items[] = {
03385      { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
03386        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
03387      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
03388        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
03389        FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
03390        0 },
03391      { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
03392        CRYPT_AsnDecodePKCSContentInfoInternal,
03393        sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
03394        ContentInfo.pszObjId), 0 },
03395      { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
03396        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
03397        offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
03398     };
03399 
03400     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03401      pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
03402      NULL, NULL);
03403     return ret;
03404 }
03405 
03406 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
03407  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03408  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03409 {
03410     BOOL ret = TRUE;
03411 
03412     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03413      pDecodePara, pvStructInfo, *pcbStructInfo);
03414 
03415     __TRY
03416     {
03417         DWORD bytesNeeded;
03418 
03419         if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
03420          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
03421         {
03422             if (!pvStructInfo)
03423                 *pcbStructInfo = bytesNeeded;
03424             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
03425              pvStructInfo, pcbStructInfo, bytesNeeded)))
03426             {
03427                 CERT_ALT_NAME_INFO *name;
03428 
03429                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
03430                     pvStructInfo = *(BYTE **)pvStructInfo;
03431                 name = pvStructInfo;
03432                 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
03433                  ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
03434                 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
03435                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
03436                  &bytesNeeded, NULL);
03437                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
03438                     CRYPT_FreeSpace(pDecodePara, name);
03439             }
03440         }
03441     }
03442     __EXCEPT_PAGE_FAULT
03443     {
03444         SetLastError(STATUS_ACCESS_VIOLATION);
03445         ret = FALSE;
03446     }
03447     __ENDTRY
03448     return ret;
03449 }
03450 
03451 struct PATH_LEN_CONSTRAINT
03452 {
03453     BOOL  fPathLenConstraint;
03454     DWORD dwPathLenConstraint;
03455 };
03456 
03457 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
03458  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03459  DWORD *pcbDecoded)
03460 {
03461     BOOL ret = TRUE;
03462     DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
03463 
03464     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
03465      pvStructInfo, *pcbStructInfo, pcbDecoded);
03466 
03467     if (!pvStructInfo)
03468     {
03469         ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
03470          &size, pcbDecoded);
03471         *pcbStructInfo = bytesNeeded;
03472     }
03473     else if (*pcbStructInfo < bytesNeeded)
03474     {
03475         SetLastError(ERROR_MORE_DATA);
03476         *pcbStructInfo = bytesNeeded;
03477         ret = FALSE;
03478     }
03479     else
03480     {
03481         struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
03482 
03483         *pcbStructInfo = bytesNeeded;
03484         size = sizeof(constraint->dwPathLenConstraint);
03485         ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
03486          &constraint->dwPathLenConstraint, &size, pcbDecoded);
03487         if (ret)
03488             constraint->fPathLenConstraint = TRUE;
03489         TRACE("got an int, dwPathLenConstraint is %d\n",
03490          constraint->dwPathLenConstraint);
03491     }
03492     TRACE("returning %d (%08x)\n", ret, GetLastError());
03493     return ret;
03494 }
03495 
03496 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
03497  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03498  DWORD *pcbDecoded)
03499 {
03500     BOOL ret;
03501     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
03502      offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
03503      offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
03504      FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
03505      CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
03506      offsetof(CERT_NAME_BLOB, pbData) };
03507 
03508     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
03509      pvStructInfo, *pcbStructInfo, pcbDecoded);
03510 
03511     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
03512      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
03513     TRACE("Returning %d (%08x)\n", ret, GetLastError());
03514     return ret;
03515 }
03516 
03517 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
03518  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03519  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03520 {
03521     BOOL ret;
03522 
03523     __TRY
03524     {
03525         struct AsnDecodeSequenceItem items[] = {
03526          { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
03527            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, 
03528            offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
03529          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
03530            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
03531            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
03532          { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
03533            cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
03534            FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
03535            TRUE, TRUE,
03536            offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
03537         };
03538 
03539         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03540          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
03541          pcbStructInfo, NULL, NULL);
03542     }
03543     __EXCEPT_PAGE_FAULT
03544     {
03545         SetLastError(STATUS_ACCESS_VIOLATION);
03546         ret = FALSE;
03547     }
03548     __ENDTRY
03549     return ret;
03550 }
03551 
03552 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
03553  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03554  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03555 {
03556     BOOL ret;
03557 
03558     __TRY
03559     {
03560         struct AsnDecodeSequenceItem items[] = {
03561          { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
03562            CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
03563          { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
03564            fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
03565            sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
03566         };
03567 
03568         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03569          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
03570          pcbStructInfo, NULL, NULL);
03571     }
03572     __EXCEPT_PAGE_FAULT
03573     {
03574         SetLastError(STATUS_ACCESS_VIOLATION);
03575         ret = FALSE;
03576     }
03577     __ENDTRY
03578     return ret;
03579 }
03580 
03581 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
03582  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03583  DWORD *pcbDecoded)
03584 {
03585     struct AsnDecodeSequenceItem items[] = {
03586      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
03587        pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
03588        FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
03589        0 },
03590      { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
03591        CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
03592        offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
03593     };
03594     BOOL ret;
03595     CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
03596 
03597     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03598      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03599 
03600     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03601      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
03602      pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
03603     return ret;
03604 }
03605 
03606 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
03607  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03608  DWORD *pcbDecoded)
03609 {
03610     BOOL ret;
03611     struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
03612      offsetof(CERT_POLICY_INFO, cPolicyQualifier),
03613      offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
03614      FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
03615      CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
03616      offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
03617 
03618     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03619      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03620 
03621     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
03622      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
03623     TRACE("Returning %d (%08x)\n", ret, GetLastError());
03624     return ret;
03625 }
03626 
03627 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
03628  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
03629 {
03630     struct AsnDecodeSequenceItem items[] = {
03631      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
03632        CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
03633        offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
03634      { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
03635        CRYPT_AsnDecodePolicyQualifiers,
03636        FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
03637        TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
03638     };
03639     CERT_POLICY_INFO *info = pvStructInfo;
03640     BOOL ret;
03641 
03642     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03643      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03644 
03645     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03646      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
03647      pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
03648     return ret;
03649 }
03650 
03651 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
03652  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03653  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03654 {
03655     BOOL ret = FALSE;
03656 
03657     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03658      pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03659 
03660     __TRY
03661     {
03662         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
03663          offsetof(CERT_POLICIES_INFO, cPolicyInfo),
03664          offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
03665          sizeof(CERT_POLICIES_INFO),
03666          CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
03667          offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
03668         CERT_POLICIES_INFO *info = pvStructInfo;
03669 
03670         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
03671             info->rgPolicyInfo = (CERT_POLICY_INFO *)(info + 1);
03672 
03673         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
03674          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
03675     }
03676     __EXCEPT_PAGE_FAULT
03677     {
03678         SetLastError(STATUS_ACCESS_VIOLATION);
03679     }
03680     __ENDTRY
03681     return ret;
03682 }
03683 
03684 static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
03685  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03686  DWORD *pcbDecoded)
03687 {
03688     struct AsnDecodeSequenceItem items[] = {
03689      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
03690        pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
03691        FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
03692      { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
03693        pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
03694        FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
03695     };
03696     CERT_POLICY_MAPPING *mapping = pvStructInfo;
03697     BOOL ret;
03698 
03699     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03700      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03701 
03702     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03703      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
03704      pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
03705     return ret;
03706 }
03707 
03708 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
03709  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03710  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03711 {
03712     BOOL ret = FALSE;
03713 
03714     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03715      pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03716 
03717     __TRY
03718     {
03719         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
03720          offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
03721          offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
03722          sizeof(CERT_POLICY_MAPPING),
03723          CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
03724          offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
03725         CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
03726 
03727         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
03728             info->rgPolicyMapping = (CERT_POLICY_MAPPING *)(info + 1);
03729         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
03730          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
03731     }
03732     __EXCEPT_PAGE_FAULT
03733     {
03734         SetLastError(STATUS_ACCESS_VIOLATION);
03735     }
03736     __ENDTRY
03737     return ret;
03738 }
03739 
03740 static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
03741  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03742  DWORD *pcbDecoded)
03743 {
03744     BOOL ret;
03745     DWORD skip, size = sizeof(skip);
03746 
03747     if (!cbEncoded)
03748     {
03749         SetLastError(CRYPT_E_ASN1_EOD);
03750         return FALSE;
03751     }
03752     if (pbEncoded[0] != (ASN_CONTEXT | 0))
03753     {
03754         SetLastError(CRYPT_E_ASN1_BADTAG);
03755         return FALSE;
03756     }
03757     if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
03758      &skip, &size, pcbDecoded)))
03759     {
03760         DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
03761          fRequireExplicitPolicy, fInhibitPolicyMapping);
03762 
03763         if (!pvStructInfo)
03764             *pcbStructInfo = bytesNeeded;
03765         else if (*pcbStructInfo < bytesNeeded)
03766         {
03767             *pcbStructInfo = bytesNeeded;
03768             SetLastError(ERROR_MORE_DATA);
03769             ret = FALSE;
03770         }
03771         else
03772         {
03773             CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
03774               CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
03775 
03776             *pcbStructInfo = bytesNeeded;
03777             /* The BOOL is implicit:  if the integer is present, then it's
03778              * TRUE.
03779              */
03780             info->fRequireExplicitPolicy = TRUE;
03781             info->dwRequireExplicitPolicySkipCerts = skip;
03782         }
03783     }
03784     return ret;
03785 }
03786 
03787 static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
03788  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03789  DWORD *pcbDecoded)
03790 {
03791     BOOL ret;
03792     DWORD skip, size = sizeof(skip);
03793 
03794     if (!cbEncoded)
03795     {
03796         SetLastError(CRYPT_E_ASN1_EOD);
03797         return FALSE;
03798     }
03799     if (pbEncoded[0] != (ASN_CONTEXT | 1))
03800     {
03801         SetLastError(CRYPT_E_ASN1_BADTAG);
03802         return FALSE;
03803     }
03804     if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
03805      &skip, &size, pcbDecoded)))
03806     {
03807         DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
03808          fInhibitPolicyMapping);
03809 
03810         if (!pvStructInfo)
03811             *pcbStructInfo = bytesNeeded;
03812         else if (*pcbStructInfo < bytesNeeded)
03813         {
03814             *pcbStructInfo = bytesNeeded;
03815             SetLastError(ERROR_MORE_DATA);
03816             ret = FALSE;
03817         }
03818         else
03819         {
03820             CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
03821               CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
03822 
03823             *pcbStructInfo = bytesNeeded;
03824             /* The BOOL is implicit:  if the integer is present, then it's
03825              * TRUE.
03826              */
03827             info->fInhibitPolicyMapping = TRUE;
03828             info->dwInhibitPolicyMappingSkipCerts = skip;
03829         }
03830     }
03831     return ret;
03832 }
03833 
03834 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
03835  DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
03836  DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
03837  void *pvStructInfo, DWORD *pcbStructInfo)
03838 {
03839     BOOL ret = FALSE;
03840 
03841     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
03842      pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
03843 
03844     __TRY
03845     {
03846         struct AsnDecodeSequenceItem items[] = {
03847          { ASN_CONTEXT | 0,
03848            offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
03849            CRYPT_AsnDecodeRequireExplicit,
03850            MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
03851            fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
03852          { ASN_CONTEXT | 1,
03853            offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
03854            CRYPT_AsnDecodeInhibitMapping,
03855            FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
03856            TRUE, FALSE, 0, 0 },
03857         };
03858 
03859         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03860          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
03861          pcbStructInfo, NULL, NULL);
03862     }
03863     __EXCEPT_PAGE_FAULT
03864     {
03865         SetLastError(STATUS_ACCESS_VIOLATION);
03866     }
03867     __ENDTRY
03868     return ret;
03869 }
03870 
03871 #define RSA1_MAGIC 0x31415352
03872 
03873 struct DECODED_RSA_PUB_KEY
03874 {
03875     DWORD              pubexp;
03876     CRYPT_INTEGER_BLOB modulus;
03877 };
03878 
03879 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
03880  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03881  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03882 {
03883     BOOL ret;
03884 
03885     __TRY
03886     {
03887         struct AsnDecodeSequenceItem items[] = {
03888          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
03889            CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
03890            FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
03891            0 },
03892          { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
03893            CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
03894         };
03895         struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
03896         DWORD size = 0;
03897 
03898         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
03899          pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
03900          &size, NULL, NULL);
03901         if (ret)
03902         {
03903             DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
03904              decodedKey->modulus.cbData;
03905 
03906             if (!pvStructInfo)
03907             {
03908                 *pcbStructInfo = bytesNeeded;
03909                 ret = TRUE;
03910             }
03911             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
03912              pvStructInfo, pcbStructInfo, bytesNeeded)))
03913             {
03914                 BLOBHEADER *hdr;
03915                 RSAPUBKEY *rsaPubKey;
03916 
03917                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
03918                     pvStructInfo = *(BYTE **)pvStructInfo;
03919                 hdr = pvStructInfo;
03920                 hdr->bType = PUBLICKEYBLOB;
03921                 hdr->bVersion = CUR_BLOB_VERSION;
03922                 hdr->reserved = 0;
03923                 hdr->aiKeyAlg = CALG_RSA_KEYX;
03924                 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
03925                  sizeof(BLOBHEADER));
03926                 rsaPubKey->magic = RSA1_MAGIC;
03927                 rsaPubKey->pubexp = decodedKey->pubexp;
03928                 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
03929                 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
03930                  sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
03931                  decodedKey->modulus.cbData);
03932             }
03933             LocalFree(decodedKey);
03934         }
03935     }
03936     __EXCEPT_PAGE_FAULT
03937     {
03938         SetLastError(STATUS_ACCESS_VIOLATION);
03939         ret = FALSE;
03940     }
03941     __ENDTRY
03942     return ret;
03943 }
03944 
03945 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
03946  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
03947  DWORD *pcbDecoded)
03948 {
03949     BOOL ret;
03950     DWORD bytesNeeded, dataLen;
03951 
03952     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
03953      pvStructInfo, *pcbStructInfo, pcbDecoded);
03954 
03955     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
03956     {
03957         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
03958 
03959         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
03960             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
03961         else
03962             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
03963         if (pcbDecoded)
03964             *pcbDecoded = 1 + lenBytes + dataLen;
03965         if (!pvStructInfo)
03966             *pcbStructInfo = bytesNeeded;
03967         else if (*pcbStructInfo < bytesNeeded)
03968         {
03969             SetLastError(ERROR_MORE_DATA);
03970             *pcbStructInfo = bytesNeeded;
03971             ret = FALSE;
03972         }
03973         else
03974         {
03975             CRYPT_DATA_BLOB *blob;
03976 
03977             *pcbStructInfo = bytesNeeded;
03978             blob = pvStructInfo;
03979             blob->cbData = dataLen;
03980             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
03981                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
03982             else
03983             {
03984                 assert(blob->pbData);
03985                 if (blob->cbData)
03986                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
03987                      blob->cbData);
03988             }
03989         }
03990     }
03991     return ret;
03992 }
03993 
03994 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
03995  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
03996  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
03997 {
03998     BOOL ret;
03999 
04000     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
04001      pDecodePara, pvStructInfo, *pcbStructInfo);
04002 
04003     __TRY
04004     {
04005         DWORD bytesNeeded;
04006 
04007         if (!cbEncoded)
04008         {
04009             SetLastError(CRYPT_E_ASN1_CORRUPT);
04010             ret = FALSE;
04011         }
04012         else if (pbEncoded[0] != ASN_OCTETSTRING)
04013         {
04014             SetLastError(CRYPT_E_ASN1_BADTAG);
04015             ret = FALSE;
04016         }
04017         else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
04018          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
04019         {
04020             if (!pvStructInfo)
04021                 *pcbStructInfo = bytesNeeded;
04022             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04023              pvStructInfo, pcbStructInfo, bytesNeeded)))
04024             {
04025                 CRYPT_DATA_BLOB *blob;
04026 
04027                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04028                     pvStructInfo = *(BYTE **)pvStructInfo;
04029                 blob = pvStructInfo;
04030                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
04031                 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
04032                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
04033                  &bytesNeeded, NULL);
04034                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04035                     CRYPT_FreeSpace(pDecodePara, blob);
04036             }
04037         }
04038     }
04039     __EXCEPT_PAGE_FAULT
04040     {
04041         SetLastError(STATUS_ACCESS_VIOLATION);
04042         ret = FALSE;
04043     }
04044     __ENDTRY
04045     return ret;
04046 }
04047 
04048 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
04049  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
04050 {
04051     BOOL ret;
04052     DWORD bytesNeeded, dataLen;
04053     BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
04054 
04055     TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
04056      pvStructInfo, *pcbStructInfo, pcbDecoded);
04057 
04058     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
04059     {
04060         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
04061             bytesNeeded = sizeof(CRYPT_BIT_BLOB);
04062         else
04063             bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
04064         if (pcbDecoded)
04065             *pcbDecoded = 1 + lenBytes + dataLen;
04066         if (!pvStructInfo)
04067             *pcbStructInfo = bytesNeeded;
04068         else if (*pcbStructInfo < bytesNeeded)
04069         {
04070             *pcbStructInfo = bytesNeeded;
04071             SetLastError(ERROR_MORE_DATA);
04072             ret = FALSE;
04073         }
04074         else
04075         {
04076             CRYPT_BIT_BLOB *blob;
04077 
04078             *pcbStructInfo = bytesNeeded;
04079             blob = pvStructInfo;
04080             blob->cbData = dataLen - 1;
04081             blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
04082             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
04083             {
04084                 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
04085             }
04086             else
04087             {
04088                 assert(blob->pbData);
04089                 if (blob->cbData)
04090                 {
04091                     BYTE mask = 0xff << blob->cUnusedBits;
04092 
04093                     memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
04094                      blob->cbData);
04095                     blob->pbData[blob->cbData - 1] &= mask;
04096                 }
04097             }
04098         }
04099     }
04100     return ret;
04101 }
04102 
04103 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
04104  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04105  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04106 {
04107     BOOL ret;
04108 
04109     TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
04110      pDecodePara, pvStructInfo, pcbStructInfo);
04111 
04112     __TRY
04113     {
04114         DWORD bytesNeeded;
04115 
04116         if (!cbEncoded)
04117         {
04118             SetLastError(CRYPT_E_ASN1_CORRUPT);
04119             ret = FALSE;
04120         }
04121         else if (pbEncoded[0] != ASN_BITSTRING)
04122         {
04123             SetLastError(CRYPT_E_ASN1_BADTAG);
04124             ret = FALSE;
04125         }
04126         else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
04127          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
04128         {
04129             if (!pvStructInfo)
04130                 *pcbStructInfo = bytesNeeded;
04131             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04132              pvStructInfo, pcbStructInfo, bytesNeeded)))
04133             {
04134                 CRYPT_BIT_BLOB *blob;
04135 
04136                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04137                     pvStructInfo = *(BYTE **)pvStructInfo;
04138                 blob = pvStructInfo;
04139                 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
04140                 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
04141                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
04142                  &bytesNeeded, NULL);
04143                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04144                     CRYPT_FreeSpace(pDecodePara, blob);
04145             }
04146         }
04147     }
04148     __EXCEPT_PAGE_FAULT
04149     {
04150         SetLastError(STATUS_ACCESS_VIOLATION);
04151         ret = FALSE;
04152     }
04153     __ENDTRY
04154     TRACE("returning %d (%08x)\n", ret, GetLastError());
04155     return ret;
04156 }
04157 
04158 /* Ignores tag.  Only allows integers 4 bytes or smaller in size. */
04159 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
04160  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
04161 {
04162     BOOL ret;
04163     DWORD dataLen;
04164 
04165     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
04166     {
04167         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
04168 
04169         if (pcbDecoded)
04170             *pcbDecoded = 1 + lenBytes + dataLen;
04171         if (dataLen > sizeof(int))
04172         {
04173             SetLastError(CRYPT_E_ASN1_LARGE);
04174             ret = FALSE;
04175         }
04176         else if (!pvStructInfo)
04177             *pcbStructInfo = sizeof(int);
04178         else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
04179         {
04180             int val, i;
04181 
04182             if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
04183             {
04184                 /* initialize to a negative value to sign-extend */
04185                 val = -1;
04186             }
04187             else
04188                 val = 0;
04189             for (i = 0; i < dataLen; i++)
04190             {
04191                 val <<= 8;
04192                 val |= pbEncoded[1 + lenBytes + i];
04193             }
04194             memcpy(pvStructInfo, &val, sizeof(int));
04195         }
04196     }
04197     return ret;
04198 }
04199 
04200 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
04201  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04202  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04203 {
04204     BOOL ret;
04205 
04206     __TRY
04207     {
04208         DWORD bytesNeeded;
04209 
04210         if (!cbEncoded)
04211         {
04212             SetLastError(CRYPT_E_ASN1_EOD);
04213             ret = FALSE;
04214         }
04215         else if (pbEncoded[0] != ASN_INTEGER)
04216         {
04217             SetLastError(CRYPT_E_ASN1_BADTAG);
04218             ret = FALSE;
04219         }
04220         else
04221             ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
04222              dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
04223         if (ret)
04224         {
04225             if (!pvStructInfo)
04226                 *pcbStructInfo = bytesNeeded;
04227             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04228              pvStructInfo, pcbStructInfo, bytesNeeded)))
04229             {
04230                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04231                     pvStructInfo = *(BYTE **)pvStructInfo;
04232                 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
04233                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
04234                  &bytesNeeded, NULL);
04235                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04236                     CRYPT_FreeSpace(pDecodePara, pvStructInfo);
04237             }
04238         }
04239     }
04240     __EXCEPT_PAGE_FAULT
04241     {
04242         SetLastError(STATUS_ACCESS_VIOLATION);
04243         ret = FALSE;
04244     }
04245     __ENDTRY
04246     return ret;
04247 }
04248 
04249 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
04250  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
04251  DWORD *pcbDecoded)
04252 {
04253     BOOL ret;
04254     DWORD bytesNeeded, dataLen;
04255 
04256     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
04257     {
04258         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
04259 
04260         bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
04261         if (pcbDecoded)
04262             *pcbDecoded = 1 + lenBytes + dataLen;
04263         if (!pvStructInfo)
04264             *pcbStructInfo = bytesNeeded;
04265         else if (*pcbStructInfo < bytesNeeded)
04266         {
04267             *pcbStructInfo = bytesNeeded;
04268             SetLastError(ERROR_MORE_DATA);
04269             ret = FALSE;
04270         }
04271         else
04272         {
04273             CRYPT_INTEGER_BLOB *blob = pvStructInfo;
04274 
04275             *pcbStructInfo = bytesNeeded;
04276             blob->cbData = dataLen;
04277             assert(blob->pbData);
04278             if (blob->cbData)
04279             {
04280                 DWORD i;
04281 
04282                 for (i = 0; i < blob->cbData; i++)
04283                 {
04284                     blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
04285                      dataLen - i - 1);
04286                 }
04287             }
04288         }
04289     }
04290     return ret;
04291 }
04292 
04293 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
04294  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04295  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04296 {
04297     BOOL ret;
04298 
04299     __TRY
04300     {
04301         DWORD bytesNeeded;
04302 
04303         if (pbEncoded[0] != ASN_INTEGER)
04304         {
04305             SetLastError(CRYPT_E_ASN1_BADTAG);
04306             ret = FALSE;
04307         }
04308         else
04309             ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
04310              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
04311         if (ret)
04312         {
04313             if (!pvStructInfo)
04314                 *pcbStructInfo = bytesNeeded;
04315             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04316              pvStructInfo, pcbStructInfo, bytesNeeded)))
04317             {
04318                 CRYPT_INTEGER_BLOB *blob;
04319 
04320                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04321                     pvStructInfo = *(BYTE **)pvStructInfo;
04322                 blob = pvStructInfo;
04323                 blob->pbData = (BYTE *)pvStructInfo +
04324                  sizeof(CRYPT_INTEGER_BLOB);
04325                 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
04326                  dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
04327                  &bytesNeeded, NULL);
04328                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04329                     CRYPT_FreeSpace(pDecodePara, blob);
04330             }
04331         }
04332     }
04333     __EXCEPT_PAGE_FAULT
04334     {
04335         SetLastError(STATUS_ACCESS_VIOLATION);
04336         ret = FALSE;
04337     }
04338     __ENDTRY
04339     return ret;
04340 }
04341 
04342 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
04343  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
04344  DWORD *pcbDecoded)
04345 {
04346     BOOL ret;
04347 
04348     if (pbEncoded[0] == ASN_INTEGER)
04349     {
04350         DWORD bytesNeeded, dataLen;
04351 
04352         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
04353         {
04354             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
04355 
04356             if (pcbDecoded)
04357                 *pcbDecoded = 1 + lenBytes + dataLen;
04358             bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
04359             if (!pvStructInfo)
04360                 *pcbStructInfo = bytesNeeded;
04361             else if (*pcbStructInfo < bytesNeeded)
04362             {
04363                 *pcbStructInfo = bytesNeeded;
04364                 SetLastError(ERROR_MORE_DATA);
04365                 ret = FALSE;
04366             }
04367             else
04368             {
04369                 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
04370 
04371                 *pcbStructInfo = bytesNeeded;
04372                 blob->cbData = dataLen;
04373                 assert(blob->pbData);
04374                 /* remove leading zero byte if it exists */
04375                 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
04376                 {
04377                     blob->cbData--;
04378                     blob->pbData++;
04379                 }
04380                 if (blob->cbData)
04381                 {
04382                     DWORD i;
04383 
04384                     for (i = 0; i < blob->cbData; i++)
04385                     {
04386                         blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
04387                          dataLen - i - 1);
04388                     }
04389                 }
04390             }
04391         }
04392     }
04393     else
04394     {
04395         SetLastError(CRYPT_E_ASN1_BADTAG);
04396         ret = FALSE;
04397     }
04398     return ret;
04399 }
04400 
04401 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
04402  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04403  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04404 {
04405     BOOL ret;
04406 
04407     __TRY
04408     {
04409         DWORD bytesNeeded;
04410 
04411         if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
04412          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
04413         {
04414             if (!pvStructInfo)
04415                 *pcbStructInfo = bytesNeeded;
04416             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04417              pvStructInfo, pcbStructInfo, bytesNeeded)))
04418             {
04419                 CRYPT_INTEGER_BLOB *blob;
04420 
04421                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04422                     pvStructInfo = *(BYTE **)pvStructInfo;
04423                 blob = pvStructInfo;
04424                 blob->pbData = (BYTE *)pvStructInfo +
04425                  sizeof(CRYPT_INTEGER_BLOB);
04426                 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
04427                  cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
04428                  &bytesNeeded, NULL);
04429                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04430                     CRYPT_FreeSpace(pDecodePara, blob);
04431             }
04432         }
04433     }
04434     __EXCEPT_PAGE_FAULT
04435     {
04436         SetLastError(STATUS_ACCESS_VIOLATION);
04437         ret = FALSE;
04438     }
04439     __ENDTRY
04440     return ret;
04441 }
04442 
04443 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
04444  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04445  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04446 {
04447     BOOL ret;
04448 
04449     if (!pvStructInfo)
04450     {
04451         *pcbStructInfo = sizeof(int);
04452         return TRUE;
04453     }
04454     __TRY
04455     {
04456         if (pbEncoded[0] == ASN_ENUMERATED)
04457         {
04458             unsigned int val = 0, i;
04459 
04460             if (cbEncoded <= 1)
04461             {
04462                 SetLastError(CRYPT_E_ASN1_EOD);
04463                 ret = FALSE;
04464             }
04465             else if (pbEncoded[1] == 0)
04466             {
04467                 SetLastError(CRYPT_E_ASN1_CORRUPT);
04468                 ret = FALSE;
04469             }
04470             else
04471             {
04472                 /* A little strange looking, but we have to accept a sign byte:
04473                  * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff.  Also,
04474                  * assuming a small length is okay here, it has to be in short
04475                  * form.
04476                  */
04477                 if (pbEncoded[1] > sizeof(unsigned int) + 1)
04478                 {
04479                     SetLastError(CRYPT_E_ASN1_LARGE);
04480                     return FALSE;
04481                 }
04482                 for (i = 0; i < pbEncoded[1]; i++)
04483                 {
04484                     val <<= 8;
04485                     val |= pbEncoded[2 + i];
04486                 }
04487                 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04488                  pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
04489                 {
04490                     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04491                         pvStructInfo = *(BYTE **)pvStructInfo;
04492                     memcpy(pvStructInfo, &val, sizeof(unsigned int));
04493                 }
04494             }
04495         }
04496         else
04497         {
04498             SetLastError(CRYPT_E_ASN1_BADTAG);
04499             ret = FALSE;
04500         }
04501     }
04502     __EXCEPT_PAGE_FAULT
04503     {
04504         SetLastError(STATUS_ACCESS_VIOLATION);
04505         ret = FALSE;
04506     }
04507     __ENDTRY
04508     return ret;
04509 }
04510 
04511 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
04512  * if it fails.
04513  */
04514 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
04515  do { \
04516     BYTE i; \
04517  \
04518     (word) = 0; \
04519     for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
04520     { \
04521         if (!isdigit(*(pbEncoded))) \
04522         { \
04523             SetLastError(CRYPT_E_ASN1_CORRUPT); \
04524             ret = FALSE; \
04525         } \
04526         else \
04527         { \
04528             (word) *= 10; \
04529             (word) += *(pbEncoded)++ - '0'; \
04530         } \
04531     } \
04532  } while (0)
04533 
04534 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
04535  SYSTEMTIME *sysTime)
04536 {
04537     BOOL ret = TRUE;
04538 
04539     if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
04540     {
04541         WORD hours, minutes = 0;
04542         BYTE sign = *pbEncoded++;
04543 
04544         len--;
04545         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
04546         if (ret && hours >= 24)
04547         {
04548             SetLastError(CRYPT_E_ASN1_CORRUPT);
04549             ret = FALSE;
04550         }
04551         else if (len >= 2)
04552         {
04553             CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
04554             if (ret && minutes >= 60)
04555             {
04556                 SetLastError(CRYPT_E_ASN1_CORRUPT);
04557                 ret = FALSE;
04558             }
04559         }
04560         if (ret)
04561         {
04562             if (sign == '+')
04563             {
04564                 sysTime->wHour += hours;
04565                 sysTime->wMinute += minutes;
04566             }
04567             else
04568             {
04569                 if (hours > sysTime->wHour)
04570                 {
04571                     sysTime->wDay--;
04572                     sysTime->wHour = 24 - (hours - sysTime->wHour);
04573                 }
04574                 else
04575                     sysTime->wHour -= hours;
04576                 if (minutes > sysTime->wMinute)
04577                 {
04578                     sysTime->wHour--;
04579                     sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
04580                 }
04581                 else
04582                     sysTime->wMinute -= minutes;
04583             }
04584         }
04585     }
04586     return ret;
04587 }
04588 
04589 #define MIN_ENCODED_TIME_LENGTH 10
04590 
04591 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
04592  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
04593  DWORD *pcbDecoded)
04594 {
04595     BOOL ret = FALSE;
04596 
04597     if (pbEncoded[0] == ASN_UTCTIME)
04598     {
04599         if (cbEncoded <= 1)
04600             SetLastError(CRYPT_E_ASN1_EOD);
04601         else if (pbEncoded[1] > 0x7f)
04602         {
04603             /* long-form date strings really can't be valid */
04604             SetLastError(CRYPT_E_ASN1_CORRUPT);
04605         }
04606         else
04607         {
04608             SYSTEMTIME sysTime = { 0 };
04609             BYTE len = pbEncoded[1];
04610 
04611             if (len < MIN_ENCODED_TIME_LENGTH)
04612                 SetLastError(CRYPT_E_ASN1_CORRUPT);
04613             else
04614             {
04615                 ret = TRUE;
04616                 if (pcbDecoded)
04617                     *pcbDecoded = 2 + len;
04618                 pbEncoded += 2;
04619                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
04620                 if (sysTime.wYear >= 50)
04621                     sysTime.wYear += 1900;
04622                 else
04623                     sysTime.wYear += 2000;
04624                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
04625                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
04626                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
04627                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
04628                 if (ret && len > 0)
04629                 {
04630                     if (len >= 2 && isdigit(*pbEncoded) &&
04631                      isdigit(*(pbEncoded + 1)))
04632                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
04633                          sysTime.wSecond);
04634                     else if (isdigit(*pbEncoded))
04635                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
04636                          sysTime.wSecond);
04637                     if (ret)
04638                         ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
04639                          &sysTime);
04640                 }
04641                 if (ret)
04642                 {
04643                     if (!pvStructInfo)
04644                         *pcbStructInfo = sizeof(FILETIME);
04645                     else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
04646                      sizeof(FILETIME))))
04647                         ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
04648                 }
04649             }
04650         }
04651     }
04652     else
04653         SetLastError(CRYPT_E_ASN1_BADTAG);
04654     return ret;
04655 }
04656 
04657 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
04658  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04659  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04660 {
04661     BOOL ret = FALSE;
04662 
04663     __TRY
04664     {
04665         DWORD bytesNeeded;
04666 
04667         ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
04668          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
04669         if (ret)
04670         {
04671             if (!pvStructInfo)
04672                 *pcbStructInfo = bytesNeeded;
04673             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
04674              pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
04675             {
04676                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04677                     pvStructInfo = *(BYTE **)pvStructInfo;
04678                 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
04679                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
04680                  &bytesNeeded, NULL);
04681                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04682                     CRYPT_FreeSpace(pDecodePara, pvStructInfo);
04683             }
04684         }
04685     }
04686     __EXCEPT_PAGE_FAULT
04687     {
04688         SetLastError(STATUS_ACCESS_VIOLATION);
04689     }
04690     __ENDTRY
04691     return ret;
04692 }
04693 
04694 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
04695  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
04696  DWORD *pcbDecoded)
04697 {
04698     BOOL ret = FALSE;
04699 
04700     if (pbEncoded[0] == ASN_GENERALTIME)
04701     {
04702         if (cbEncoded <= 1)
04703             SetLastError(CRYPT_E_ASN1_EOD);
04704         else if (pbEncoded[1] > 0x7f)
04705         {
04706             /* long-form date strings really can't be valid */
04707             SetLastError(CRYPT_E_ASN1_CORRUPT);
04708         }
04709         else
04710         {
04711             BYTE len = pbEncoded[1];
04712 
04713             if (len < MIN_ENCODED_TIME_LENGTH)
04714                 SetLastError(CRYPT_E_ASN1_CORRUPT);
04715             else
04716             {
04717                 SYSTEMTIME sysTime = { 0 };
04718 
04719                 ret = TRUE;
04720                 if (pcbDecoded)
04721                     *pcbDecoded = 2 + len;
04722                 pbEncoded += 2;
04723                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
04724                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
04725                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
04726                 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
04727                 if (ret && len > 0)
04728                 {
04729                     CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
04730                      sysTime.wMinute);
04731                     if (ret && len > 0)
04732                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
04733                          sysTime.wSecond);
04734                     if (ret && len > 0 && (*pbEncoded == '.' ||
04735                      *pbEncoded == ','))
04736                     {
04737                         BYTE digits;
04738 
04739                         pbEncoded++;
04740                         len--;
04741                         /* workaround macro weirdness */
04742                         digits = min(len, 3);
04743                         CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
04744                          sysTime.wMilliseconds);
04745                     }
04746                     if (ret)
04747                         ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
04748                          &sysTime);
04749                 }
04750                 if (ret)
04751                 {
04752                     if (!pvStructInfo)
04753                         *pcbStructInfo = sizeof(FILETIME);
04754                     else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
04755                      sizeof(FILETIME))))
04756                         ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
04757                 }
04758             }
04759         }
04760     }
04761     else
04762         SetLastError(CRYPT_E_ASN1_BADTAG);
04763     return ret;
04764 }
04765 
04766 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
04767  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
04768  DWORD *pcbDecoded)
04769 {
04770     BOOL ret;
04771     InternalDecodeFunc decode = NULL;
04772 
04773     if (pbEncoded[0] == ASN_UTCTIME)
04774         decode = CRYPT_AsnDecodeUtcTimeInternal;
04775     else if (pbEncoded[0] == ASN_GENERALTIME)
04776         decode = CRYPT_AsnDecodeGeneralizedTime;
04777     if (decode)
04778         ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
04779          pcbStructInfo, pcbDecoded);
04780     else
04781     {
04782         SetLastError(CRYPT_E_ASN1_BADTAG);
04783         ret = FALSE;
04784     }
04785     return ret;
04786 }
04787 
04788 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
04789  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04790  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04791 {
04792     BOOL ret;
04793 
04794     __TRY
04795     {
04796         DWORD bytesNeeded;
04797 
04798         ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
04799          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
04800         if (ret)
04801         {
04802             if (!pvStructInfo)
04803                 *pcbStructInfo = bytesNeeded;
04804             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04805              pvStructInfo, pcbStructInfo, bytesNeeded)))
04806             {
04807                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04808                     pvStructInfo = *(BYTE **)pvStructInfo;
04809                 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
04810                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
04811                  &bytesNeeded, NULL);
04812                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04813                     CRYPT_FreeSpace(pDecodePara, pvStructInfo);
04814             }
04815         }
04816     }
04817     __EXCEPT_PAGE_FAULT
04818     {
04819         SetLastError(STATUS_ACCESS_VIOLATION);
04820         ret = FALSE;
04821     }
04822     __ENDTRY
04823     return ret;
04824 }
04825 
04826 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
04827  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
04828  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
04829 {
04830     BOOL ret = TRUE;
04831 
04832     __TRY
04833     {
04834         if (pbEncoded[0] == ASN_SEQUENCEOF)
04835         {
04836             DWORD bytesNeeded, dataLen, remainingLen, cValue;
04837 
04838             if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
04839             {
04840                 BYTE lenBytes;
04841                 const BYTE *ptr;
04842 
04843                 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
04844                 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
04845                 cValue = 0;
04846                 ptr = pbEncoded + 1 + lenBytes;
04847                 remainingLen = dataLen;
04848                 while (ret && remainingLen)
04849                 {
04850                     DWORD nextLen;
04851 
04852                     ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
04853                     if (ret)
04854                     {
04855                         DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
04856 
04857                         remainingLen -= 1 + nextLenBytes + nextLen;
04858                         ptr += 1 + nextLenBytes + nextLen;
04859                         bytesNeeded += sizeof(CRYPT_DER_BLOB);
04860                         if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
04861                             bytesNeeded += 1 + nextLenBytes + nextLen;
04862                         cValue++;
04863                     }
04864                 }
04865                 if (ret)
04866                 {
04867                     CRYPT_SEQUENCE_OF_ANY *seq;
04868                     BYTE *nextPtr;
04869                     DWORD i;
04870 
04871                     if (!pvStructInfo)
04872                         *pcbStructInfo = bytesNeeded;
04873                     else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
04874                      pvStructInfo, pcbStructInfo, bytesNeeded)))
04875                     {
04876                         if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
04877                             pvStructInfo = *(BYTE **)pvStructInfo;
04878                         seq = pvStructInfo;
04879                         seq->cValue = cValue;
04880                         seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
04881                          sizeof(*seq));
04882                         nextPtr = (BYTE *)seq->rgValue +
04883                          cValue * sizeof(CRYPT_DER_BLOB);
04884                         ptr = pbEncoded + 1 + lenBytes;
04885                         remainingLen = dataLen;
04886                         i = 0;
04887                         while (ret && remainingLen)
04888                         {
04889                             DWORD nextLen;
04890 
04891                             ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
04892                             if (ret)
04893                             {
04894                                 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
04895 
04896                                 seq->rgValue[i].cbData = 1 + nextLenBytes +
04897                                  nextLen;
04898                                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
04899                                     seq->rgValue[i].pbData = (BYTE *)ptr;
04900                                 else
04901                                 {
04902                                     seq->rgValue[i].pbData = nextPtr;
04903                                     memcpy(nextPtr, ptr, 1 + nextLenBytes +
04904                                      nextLen);
04905                                     nextPtr += 1 + nextLenBytes + nextLen;
04906                                 }
04907                                 remainingLen -= 1 + nextLenBytes + nextLen;
04908                                 ptr += 1 + nextLenBytes + nextLen;
04909                                 i++;
04910                             }
04911                         }
04912                         if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
04913                             CRYPT_FreeSpace(pDecodePara, seq);
04914                     }
04915                 }
04916             }
04917         }
04918         else
04919         {
04920             SetLastError(CRYPT_E_ASN1_BADTAG);
04921             ret = FALSE;
04922         }
04923     }
04924     __EXCEPT_PAGE_FAULT
04925     {
04926         SetLastError(STATUS_ACCESS_VIOLATION);
04927         ret = FALSE;
04928     }
04929     __ENDTRY
04930     return ret;
04931 }
04932 
04933 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
04934  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
04935  DWORD *pcbDecoded)
04936 {
04937     BOOL ret;
04938 
04939     if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
04940     {
04941         DWORD bytesNeeded, dataLen;
04942 
04943         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
04944         {
04945             struct AsnArrayDescriptor arrayDesc = {
04946              ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
04947              offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
04948              offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
04949              FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
04950              CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
04951              offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
04952             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
04953             DWORD nameLen;
04954 
04955             if (dataLen)
04956             {
04957                 ret = CRYPT_AsnDecodeArray(&arrayDesc,
04958                  pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
04959                  dwFlags, NULL, NULL, &nameLen, NULL);
04960                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
04961                  FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
04962             }
04963             else
04964                 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
04965             if (pcbDecoded)
04966                 *pcbDecoded = 1 + lenBytes + dataLen;
04967             if (!pvStructInfo)
04968                 *pcbStructInfo = bytesNeeded;
04969             else if (*pcbStructInfo < bytesNeeded)
04970             {
04971                 *pcbStructInfo = bytesNeeded;
04972                 SetLastError(ERROR_MORE_DATA);
04973                 ret = FALSE;
04974             }
04975             else
04976             {
04977                 CRL_DIST_POINT_NAME *name = pvStructInfo;
04978 
04979                 *pcbStructInfo = bytesNeeded;
04980                 if (dataLen)
04981                 {
04982                     name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
04983                     ret = CRYPT_AsnDecodeArray(&arrayDesc,
04984                      pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
04985                      dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
04986                      NULL);
04987                 }
04988                 else
04989                     name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
04990             }
04991         }
04992     }
04993     else
04994     {
04995         SetLastError(CRYPT_E_ASN1_BADTAG);
04996         ret = FALSE;
04997     }
04998     return ret;
04999 }
05000 
05001 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
05002  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
05003 {
05004     struct AsnDecodeSequenceItem items[] = {
05005      { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
05006        DistPointName), CRYPT_AsnDecodeDistPointName,
05007        sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
05008        DistPointName.u.FullName.rgAltEntry), 0 },
05009      { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
05010        CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
05011        offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
05012      { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
05013        CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
05014        offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
05015     };
05016     CRL_DIST_POINT *point = pvStructInfo;
05017     BOOL ret;
05018 
05019     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05020      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05021      pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
05022     return ret;
05023 }
05024 
05025 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
05026  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
05027  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
05028 {
05029     BOOL ret;
05030 
05031     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05032      pDecodePara, pvStructInfo, *pcbStructInfo);
05033 
05034     __TRY
05035     {
05036         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
05037          offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
05038          offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
05039          sizeof(CRL_DIST_POINTS_INFO),
05040          CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
05041          offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
05042         CRL_DIST_POINTS_INFO *info = pvStructInfo;
05043 
05044         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
05045             info->rgDistPoint = (CRL_DIST_POINT *)(info + 1);
05046         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05047          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
05048     }
05049     __EXCEPT_PAGE_FAULT
05050     {
05051         SetLastError(STATUS_ACCESS_VIOLATION);
05052         ret = FALSE;
05053     }
05054     __ENDTRY
05055     return ret;
05056 }
05057 
05058 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
05059  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
05060  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
05061 {
05062     BOOL ret;
05063 
05064     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05065      pDecodePara, pvStructInfo, *pcbStructInfo);
05066 
05067     __TRY
05068     {
05069         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
05070          offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
05071          offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
05072          sizeof(CERT_ENHKEY_USAGE),
05073          CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
05074         CERT_ENHKEY_USAGE *usage = pvStructInfo;
05075 
05076         if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
05077             usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1);
05078         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05079          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
05080     }
05081     __EXCEPT_PAGE_FAULT
05082     {
05083         SetLastError(STATUS_ACCESS_VIOLATION);
05084         ret = FALSE;
05085     }
05086     __ENDTRY
05087     return ret;
05088 }
05089 
05090 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
05091  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
05092  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
05093 {
05094     BOOL ret;
05095 
05096     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05097      pDecodePara, pvStructInfo, *pcbStructInfo);
05098 
05099     __TRY
05100     {
05101         struct AsnDecodeSequenceItem items[] = {
05102          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
05103            DistPointName), CRYPT_AsnDecodeDistPointName,
05104            sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
05105            offsetof(CRL_ISSUING_DIST_POINT,
05106            DistPointName.u.FullName.rgAltEntry), 0 },
05107          { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
05108            fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
05109            FALSE, 0 },
05110          { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
05111            fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
05112            FALSE, 0 },
05113          { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
05114            OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
05115            sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
05116            OnlySomeReasonFlags.pbData), 0 },
05117          { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
05118            fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
05119         };
05120 
05121         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05122          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
05123          pcbStructInfo, NULL, NULL);
05124     }
05125     __EXCEPT_PAGE_FAULT
05126     {
05127         SetLastError(STATUS_ACCESS_VIOLATION);
05128         ret = FALSE;
05129     }
05130     __ENDTRY
05131     return ret;
05132 }
05133 
05134 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
05135  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05136  DWORD *pcbDecoded)
05137 {
05138     BOOL ret;
05139     DWORD max, size = sizeof(max);
05140 
05141     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05142      pvStructInfo, *pcbStructInfo, pcbDecoded);
05143 
05144     if (!cbEncoded)
05145     {
05146         SetLastError(CRYPT_E_ASN1_EOD);
05147         return FALSE;
05148     }
05149     if (pbEncoded[0] != (ASN_CONTEXT | 1))
05150     {
05151         SetLastError(CRYPT_E_ASN1_BADTAG);
05152         return FALSE;
05153     }
05154     if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
05155      &max, &size, pcbDecoded)))
05156     {
05157         DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
05158 
05159         if (!pvStructInfo)
05160             *pcbStructInfo = bytesNeeded;
05161         else if (*pcbStructInfo < bytesNeeded)
05162         {
05163             *pcbStructInfo = bytesNeeded;
05164             SetLastError(ERROR_MORE_DATA);
05165             ret = FALSE;
05166         }
05167         else
05168         {
05169             CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
05170              CERT_GENERAL_SUBTREE, fMaximum);
05171 
05172             *pcbStructInfo = bytesNeeded;
05173             /* The BOOL is implicit:  if the integer is present, then it's
05174              * TRUE.
05175              */
05176             subtree->fMaximum = TRUE;
05177             subtree->dwMaximum = max;
05178         }
05179     }
05180     TRACE("returning %d\n", ret);
05181     return ret;
05182 }
05183 
05184 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
05185  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05186  DWORD *pcbDecoded)
05187 {
05188     BOOL ret;
05189     struct AsnDecodeSequenceItem items[] = {
05190      { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
05191        CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
05192        offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
05193      { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
05194        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
05195      { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
05196        CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
05197        TRUE, FALSE, 0, 0 },
05198     };
05199     CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
05200 
05201     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05202      pvStructInfo, *pcbStructInfo, pcbDecoded);
05203 
05204     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05205      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05206      pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
05207     if (pcbDecoded)
05208     {
05209         TRACE("%d\n", *pcbDecoded);
05210         if (*pcbDecoded < cbEncoded)
05211             TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
05212              *(pbEncoded + *pcbDecoded + 1));
05213     }
05214     TRACE("returning %d\n", ret);
05215     return ret;
05216 }
05217 
05218 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
05219  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05220  DWORD *pcbDecoded)
05221 {
05222     BOOL ret = TRUE;
05223     struct AsnArrayDescriptor arrayDesc = { 0,
05224      offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
05225      offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
05226      MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
05227                 cExcludedSubtree),
05228      CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
05229      offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
05230 
05231     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05232      pvStructInfo, *pcbStructInfo, pcbDecoded);
05233 
05234     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05235      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
05236     return ret;
05237 }
05238 
05239 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
05240  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05241  DWORD *pcbDecoded)
05242 {
05243     BOOL ret = TRUE;
05244     struct AsnArrayDescriptor arrayDesc = { 0,
05245      offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
05246      offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
05247      FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
05248      CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
05249      offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
05250 
05251     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05252      pvStructInfo, *pcbStructInfo, pcbDecoded);
05253 
05254     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05255      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
05256     return ret;
05257 }
05258 
05259 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
05260  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
05261  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
05262 {
05263     BOOL ret = FALSE;
05264 
05265     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05266      pDecodePara, pvStructInfo, *pcbStructInfo);
05267 
05268     __TRY
05269     {
05270         struct AsnDecodeSequenceItem items[] = {
05271          { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
05272            offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
05273            CRYPT_AsnDecodePermittedSubtree,
05274            MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
05275            cExcludedSubtree), TRUE, TRUE,
05276            offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
05277          { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
05278            offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
05279            CRYPT_AsnDecodeExcludedSubtree,
05280            FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
05281            TRUE, TRUE,
05282            offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
05283         };
05284 
05285         ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05286          pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
05287          pcbStructInfo, NULL, NULL);
05288     }
05289     __EXCEPT_PAGE_FAULT
05290     {
05291         SetLastError(STATUS_ACCESS_VIOLATION);
05292     }
05293     __ENDTRY
05294     return ret;
05295 }
05296 
05297 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
05298  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05299  DWORD *pcbDecoded)
05300 {
05301     BOOL ret;
05302     struct AsnDecodeSequenceItem items[] = {
05303      { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
05304        sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
05305        Issuer.pbData) },
05306      { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
05307        CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
05308        TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
05309     };
05310     CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
05311 
05312     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05313      pvStructInfo, *pcbStructInfo, pcbDecoded);
05314 
05315     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05316      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05317      pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
05318     if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
05319     {
05320         SetLastError(CRYPT_E_ASN1_CORRUPT);
05321         ret = FALSE;
05322     }
05323     TRACE("returning %d\n", ret);
05324     return ret;
05325 }
05326 
05327 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
05328  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05329  DWORD *pcbDecoded)
05330 {
05331     CMSG_SIGNER_INFO *info = pvStructInfo;
05332     struct AsnDecodeSequenceItem items[] = {
05333      { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
05334        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
05335      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
05336        CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
05337        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
05338      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
05339        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
05340        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
05341      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
05342        offsetof(CMSG_SIGNER_INFO, AuthAttrs),
05343        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
05344        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
05345      { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
05346        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
05347        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
05348        HashEncryptionAlgorithm.pszObjId), 0 },
05349      { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
05350        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
05351        FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
05352      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
05353        offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
05354        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
05355        TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
05356     };
05357     BOOL ret;
05358 
05359     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05360      pvStructInfo, *pcbStructInfo);
05361 
05362     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05363      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05364      pcbDecoded, info ? info->Issuer.pbData : NULL);
05365     return ret;
05366 }
05367 
05368 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
05369  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
05370  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
05371 {
05372     BOOL ret = FALSE;
05373 
05374     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05375      pDecodePara, pvStructInfo, *pcbStructInfo);
05376 
05377     __TRY
05378     {
05379         ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
05380          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
05381         if (ret && pvStructInfo)
05382         {
05383             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
05384              pcbStructInfo, *pcbStructInfo);
05385             if (ret)
05386             {
05387                 CMSG_SIGNER_INFO *info;
05388 
05389                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
05390                     pvStructInfo = *(BYTE **)pvStructInfo;
05391                 info = pvStructInfo;
05392                 info->Issuer.pbData = ((BYTE *)info +
05393                  sizeof(CMSG_SIGNER_INFO));
05394                 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
05395                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
05396                  pcbStructInfo, NULL);
05397                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
05398                     CRYPT_FreeSpace(pDecodePara, info);
05399             }
05400         }
05401     }
05402     __EXCEPT_PAGE_FAULT
05403     {
05404         SetLastError(STATUS_ACCESS_VIOLATION);
05405     }
05406     __ENDTRY
05407     TRACE("returning %d\n", ret);
05408     return ret;
05409 }
05410 
05411 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
05412  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05413  DWORD *pcbDecoded)
05414 {
05415     BOOL ret;
05416     struct AsnArrayDescriptor arrayDesc = { 0,
05417      offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
05418      offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
05419      MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
05420      CRYPT_AsnDecodeCopyBytes,
05421      sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
05422 
05423     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05424      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
05425 
05426     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05427      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
05428     return ret;
05429 }
05430 
05431 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
05432  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05433  DWORD *pcbDecoded)
05434 {
05435     BOOL ret;
05436     struct AsnArrayDescriptor arrayDesc = { 0,
05437      offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
05438      offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
05439      MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
05440      CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
05441      TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
05442 
05443     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05444      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
05445 
05446     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05447      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
05448     return ret;
05449 }
05450 
05451 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
05452  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05453  DWORD *pcbDecoded)
05454 {
05455     CERT_ID *id = pvStructInfo;
05456     BOOL ret = FALSE;
05457 
05458     if (*pbEncoded == ASN_SEQUENCEOF)
05459     {
05460         ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
05461          id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
05462         if (ret)
05463         {
05464             if (id)
05465                 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
05466             if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
05467                 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
05468                  sizeof(CERT_ISSUER_SERIAL_NUMBER);
05469             else
05470                 *pcbStructInfo = sizeof(CERT_ID);
05471         }
05472     }
05473     else if (*pbEncoded == (ASN_CONTEXT | 0))
05474     {
05475         ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
05476          id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
05477         if (ret)
05478         {
05479             if (id)
05480                 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
05481             if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
05482                 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
05483                  sizeof(CRYPT_DATA_BLOB);
05484             else
05485                 *pcbStructInfo = sizeof(CERT_ID);
05486         }
05487     }
05488     else
05489         SetLastError(CRYPT_E_ASN1_BADTAG);
05490     return ret;
05491 }
05492 
05493 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
05494  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05495  DWORD *pcbDecoded)
05496 {
05497     CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
05498     struct AsnDecodeSequenceItem items[] = {
05499      { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
05500        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
05501      { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
05502        CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
05503        offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
05504      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
05505        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
05506        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
05507      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
05508        offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
05509        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
05510        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
05511      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
05512        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
05513        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
05514        HashEncryptionAlgorithm.pszObjId), 0 },
05515      { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
05516        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
05517        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
05518      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
05519        offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
05520        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
05521        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
05522     };
05523     BOOL ret;
05524 
05525     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05526      pvStructInfo, *pcbStructInfo);
05527 
05528     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05529      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05530      pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
05531     return ret;
05532 }
05533 
05534 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
05535  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
05536  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
05537 {
05538     BOOL ret = FALSE;
05539 
05540     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05541      pDecodePara, pvStructInfo, *pcbStructInfo);
05542 
05543     __TRY
05544     {
05545         ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
05546          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
05547         if (ret && pvStructInfo)
05548         {
05549             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
05550              pcbStructInfo, *pcbStructInfo);
05551             if (ret)
05552             {
05553                 CMSG_CMS_SIGNER_INFO *info;
05554 
05555                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
05556                     pvStructInfo = *(BYTE **)pvStructInfo;
05557                 info = pvStructInfo;
05558                 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
05559                  sizeof(CMSG_CMS_SIGNER_INFO));
05560                 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
05561                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
05562                  pcbStructInfo, NULL);
05563                 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
05564                     CRYPT_FreeSpace(pDecodePara, info);
05565             }
05566         }
05567     }
05568     __EXCEPT_PAGE_FAULT
05569     {
05570         SetLastError(STATUS_ACCESS_VIOLATION);
05571     }
05572     __ENDTRY
05573     TRACE("returning %d\n", ret);
05574     return ret;
05575 }
05576 
05577 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
05578  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
05579 {
05580     BOOL ret;
05581     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
05582      offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
05583      offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
05584      FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
05585      CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
05586      offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
05587 
05588     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05589      pvStructInfo, *pcbStructInfo, pcbDecoded);
05590 
05591     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05592      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
05593     return ret;
05594 }
05595 
05596 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
05597  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
05598  CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
05599 {
05600     BOOL ret = FALSE;
05601     struct AsnDecodeSequenceItem items[] = {
05602      { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
05603        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
05604      /* Placeholder for the hash algorithms - redundant with those in the
05605       * signers, so just ignore them.
05606       */
05607      { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
05608      { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
05609        CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
05610        FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
05611      { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
05612        offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
05613        MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
05614        offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
05615      { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
05616        offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
05617        MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
05618        offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
05619      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
05620        CRYPT_DecodeSignerArray,
05621        FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
05622        offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
05623     };
05624 
05625     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05626      pDecodePara, signedInfo, *pcbSignedInfo);
05627 
05628     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05629      pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
05630      NULL, NULL);
05631     TRACE("returning %d\n", ret);
05632     return ret;
05633 }
05634 
05635 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
05636  DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
05637 {
05638     BOOL ret;
05639     CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
05640     struct AsnDecodeSequenceItem items[] = {
05641      { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
05642        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
05643      { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
05644        RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
05645        sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
05646        offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
05647        RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
05648      { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
05649        KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
05650        sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
05651        offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
05652        KeyEncryptionAlgorithm.pszObjId), 0 },
05653      { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
05654        CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
05655        offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
05656     };
05657 
05658     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05659      pvStructInfo, *pcbStructInfo, pcbDecoded);
05660 
05661     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05662      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05663      pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
05664      NULL);
05665     if (info)
05666         info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
05667     TRACE("returning %d\n", ret);
05668     return ret;
05669 }
05670 
05671 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
05672  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05673  DWORD *pcbDecoded)
05674 {
05675     BOOL ret;
05676     struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
05677      offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
05678      offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
05679      MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
05680      CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
05681      offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
05682      RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
05683 
05684     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05685      pvStructInfo, *pcbStructInfo, pcbDecoded);
05686 
05687     ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
05688      dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
05689     TRACE("returning %d\n", ret);
05690     return ret;
05691 }
05692 
05693 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
05694  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
05695  DWORD *pcbDecoded)
05696 {
05697     BOOL ret;
05698     CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
05699     struct AsnDecodeSequenceItem items[] = {
05700      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
05701        contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
05702        FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
05703        contentType), 0 },
05704      { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
05705        contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
05706        sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
05707        offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
05708        contentEncryptionAlgorithm.pszObjId), 0 },
05709      { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
05710        encryptedContent), CRYPT_AsnDecodeOctetsInternal,
05711        sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
05712        offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
05713     };
05714 
05715     TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
05716      pvStructInfo, *pcbStructInfo, pcbDecoded);
05717 
05718     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05719      pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
05720      pcbDecoded, info ? info->contentType : NULL);
05721     TRACE("returning %d\n", ret);
05722     return ret;
05723 }
05724 
05725 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
05726  DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
05727  CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
05728 {
05729     BOOL ret;
05730     struct AsnDecodeSequenceItem items[] = {
05731      { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
05732        CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
05733      { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
05734        cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
05735        MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
05736        FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
05737      { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
05738        CRYPT_AsnDecodeEncryptedContentInfo,
05739        sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
05740        offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
05741     };
05742 
05743     TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
05744      pDecodePara, envelopedData, *pcbEnvelopedData);
05745 
05746     ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
05747      pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
05748      pcbEnvelopedData, NULL, NULL);
05749     TRACE("returning %d\n", ret);
05750     return ret;
05751 }
05752 
05753 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
05754  LPCSTR lpszStructType)
05755 {
05756     CryptDecodeObjectExFunc decodeFunc = NULL;
05757 
05758     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
05759      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
05760     {
05761         SetLastError(ERROR_FILE_NOT_FOUND);
05762         return NULL;
05763     }
05764     if (IS_INTOID(lpszStructType))
05765     {
05766         switch (LOWORD(lpszStructType))
05767         {
05768         case LOWORD(X509_CERT):
05769             decodeFunc = CRYPT_AsnDecodeCertSignedContent;
05770             break;
05771         case LOWORD(X509_CERT_TO_BE_SIGNED):
05772             decodeFunc = CRYPT_AsnDecodeCert;
05773             break;
05774         case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
05775             decodeFunc = CRYPT_AsnDecodeCRL;
05776             break;
05777         case LOWORD(X509_EXTENSIONS):
05778             decodeFunc = CRYPT_AsnDecodeExtensions;
05779             break;
05780         case LOWORD(X509_NAME_VALUE):
05781             decodeFunc = CRYPT_AsnDecodeNameValue;
05782             break;
05783         case LOWORD(X509_NAME):
05784             decodeFunc = CRYPT_AsnDecodeName;
05785             break;
05786         case LOWORD(X509_PUBLIC_KEY_INFO):
05787             decodeFunc = CRYPT_AsnDecodePubKeyInfo;
05788             break;
05789         case LOWORD(X509_AUTHORITY_KEY_ID):
05790             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
05791             break;
05792         case LOWORD(X509_ALTERNATE_NAME):
05793             decodeFunc = CRYPT_AsnDecodeAltName;
05794             break;
05795         case LOWORD(X509_BASIC_CONSTRAINTS):
05796             decodeFunc = CRYPT_AsnDecodeBasicConstraints;
05797             break;
05798         case LOWORD(X509_BASIC_CONSTRAINTS2):
05799             decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
05800             break;
05801         case LOWORD(X509_CERT_POLICIES):
05802             decodeFunc = CRYPT_AsnDecodeCertPolicies;
05803             break;
05804         case LOWORD(RSA_CSP_PUBLICKEYBLOB):
05805             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
05806             break;
05807         case LOWORD(X509_UNICODE_NAME):
05808             decodeFunc = CRYPT_AsnDecodeUnicodeName;
05809             break;
05810         case LOWORD(PKCS_ATTRIBUTE):
05811             decodeFunc = CRYPT_AsnDecodePKCSAttribute;
05812             break;
05813         case LOWORD(X509_UNICODE_NAME_VALUE):
05814             decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
05815             break;
05816         case LOWORD(X509_OCTET_STRING):
05817             decodeFunc = CRYPT_AsnDecodeOctets;
05818             break;
05819         case LOWORD(X509_BITS):
05820         case LOWORD(X509_KEY_USAGE):
05821             decodeFunc = CRYPT_AsnDecodeBits;
05822             break;
05823         case LOWORD(X509_INTEGER):
05824             decodeFunc = CRYPT_AsnDecodeInt;
05825             break;
05826         case LOWORD(X509_MULTI_BYTE_INTEGER):
05827             decodeFunc = CRYPT_AsnDecodeInteger;
05828             break;
05829         case LOWORD(X509_MULTI_BYTE_UINT):
05830             decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
05831             break;
05832         case LOWORD(X509_ENUMERATED):
05833             decodeFunc = CRYPT_AsnDecodeEnumerated;
05834             break;
05835         case LOWORD(X509_CHOICE_OF_TIME):
05836             decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
05837             break;
05838         case LOWORD(X509_AUTHORITY_KEY_ID2):
05839             decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
05840             break;
05841         case LOWORD(X509_AUTHORITY_INFO_ACCESS):
05842             decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
05843             break;
05844         case LOWORD(PKCS_CONTENT_INFO):
05845             decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
05846             break;
05847         case LOWORD(X509_SEQUENCE_OF_ANY):
05848             decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
05849             break;
05850         case LOWORD(PKCS_UTC_TIME):
05851             decodeFunc = CRYPT_AsnDecodeUtcTime;
05852             break;
05853         case LOWORD(X509_CRL_DIST_POINTS):
05854             decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
05855             break;
05856         case LOWORD(X509_ENHANCED_KEY_USAGE):
05857             decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
05858             break;
05859         case LOWORD(PKCS_CTL):
05860             decodeFunc = CRYPT_AsnDecodeCTL;
05861             break;
05862         case LOWORD(PKCS_SMIME_CAPABILITIES):
05863             decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
05864             break;
05865         case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
05866             decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
05867             break;
05868         case LOWORD(PKCS_ATTRIBUTES):
05869             decodeFunc = CRYPT_AsnDecodePKCSAttributes;
05870             break;
05871         case LOWORD(X509_ISSUING_DIST_POINT):
05872             decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
05873             break;
05874         case LOWORD(X509_NAME_CONSTRAINTS):
05875             decodeFunc = CRYPT_AsnDecodeNameConstraints;
05876             break;
05877         case LOWORD(X509_POLICY_MAPPINGS):
05878             decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
05879             break;
05880         case LOWORD(X509_POLICY_CONSTRAINTS):
05881             decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
05882             break;
05883         case LOWORD(PKCS7_SIGNER_INFO):
05884             decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
05885             break;
05886         case LOWORD(CMS_SIGNER_INFO):
05887             decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
05888             break;
05889         }
05890     }
05891     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
05892         decodeFunc = CRYPT_AsnDecodeExtensions;
05893     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
05894         decodeFunc = CRYPT_AsnDecodeUtcTime;
05895     else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
05896         decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
05897     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
05898         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
05899     else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
05900         decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
05901     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
05902         decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
05903     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
05904         decodeFunc = CRYPT_AsnDecodeEnumerated;
05905     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
05906         decodeFunc = CRYPT_AsnDecodeBits;
05907     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
05908         decodeFunc = CRYPT_AsnDecodeOctets;
05909     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
05910         decodeFunc = CRYPT_AsnDecodeBasicConstraints;
05911     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
05912         decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
05913     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
05914         decodeFunc = CRYPT_AsnDecodeAltName;
05915     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
05916         decodeFunc = CRYPT_AsnDecodeAltName;
05917     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
05918         decodeFunc = CRYPT_AsnDecodeAltName;
05919     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
05920         decodeFunc = CRYPT_AsnDecodeAltName;
05921     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
05922         decodeFunc = CRYPT_AsnDecodeAltName;
05923     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
05924         decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
05925     else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
05926         decodeFunc = CRYPT_AsnDecodeCertPolicies;
05927     else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
05928         decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
05929     else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
05930         decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
05931     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
05932         decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
05933     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
05934         decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
05935     else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
05936         decodeFunc = CRYPT_AsnDecodeNameConstraints;
05937     else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
05938         decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
05939     else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
05940         decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
05941     else if (!strcmp(lpszStructType, szOID_CTL))
05942         decodeFunc = CRYPT_AsnDecodeCTL;
05943     return decodeFunc;
05944 }
05945 
05946 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
05947  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
05948 {
05949     static HCRYPTOIDFUNCSET set = NULL;
05950     CryptDecodeObjectFunc decodeFunc = NULL;
05951 
05952     if (!set)
05953         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
05954     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
05955      (void **)&decodeFunc, hFunc);
05956     return decodeFunc;
05957 }
05958 
05959 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
05960  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
05961 {
05962     static HCRYPTOIDFUNCSET set = NULL;
05963     CryptDecodeObjectExFunc decodeFunc = NULL;
05964 
05965     if (!set)
05966         set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
05967     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
05968      (void **)&decodeFunc, hFunc);
05969     return decodeFunc;
05970 }
05971 
05972 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
05973  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
05974  DWORD *pcbStructInfo)
05975 {
05976     BOOL ret = FALSE;
05977     CryptDecodeObjectFunc pCryptDecodeObject = NULL;
05978     CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
05979     HCRYPTOIDFUNCADDR hFunc = NULL;
05980 
05981     TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
05982      debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
05983      pvStructInfo, pcbStructInfo);
05984 
05985     if (!pvStructInfo && !pcbStructInfo)
05986     {
05987         SetLastError(ERROR_INVALID_PARAMETER);
05988         return FALSE;
05989     }
05990     if (cbEncoded > MAX_ENCODED_LEN)
05991     {
05992         SetLastError(CRYPT_E_ASN1_LARGE);
05993         return FALSE;
05994     }
05995 
05996     if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
05997      lpszStructType)))
05998     {
05999         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
06000          debugstr_a(lpszStructType));
06001         pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
06002          lpszStructType, &hFunc);
06003         if (!pCryptDecodeObject)
06004             pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
06005              lpszStructType, &hFunc);
06006     }
06007     if (pCryptDecodeObject)
06008         ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
06009          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
06010     else if (pCryptDecodeObjectEx)
06011         ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
06012          pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
06013          pvStructInfo, pcbStructInfo);
06014     if (hFunc)
06015         CryptFreeOIDFunctionAddress(hFunc, 0);
06016     TRACE_(crypt)("returning %d\n", ret);
06017     return ret;
06018 }
06019 
06020 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
06021  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
06022  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
06023 {
06024     BOOL ret = FALSE;
06025     CryptDecodeObjectExFunc decodeFunc;
06026     HCRYPTOIDFUNCADDR hFunc = NULL;
06027 
06028     TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
06029      dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
06030      cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
06031 
06032     if (!pvStructInfo && !pcbStructInfo)
06033     {
06034         SetLastError(ERROR_INVALID_PARAMETER);
06035         return FALSE;
06036     }
06037     if (cbEncoded > MAX_ENCODED_LEN)
06038     {
06039         SetLastError(CRYPT_E_ASN1_LARGE);
06040         return FALSE;
06041     }
06042 
06043     SetLastError(NOERROR);
06044     if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
06045     {
06046         if (!pvStructInfo)
06047         {
06048             SetLastError(ERROR_INVALID_PARAMETER);
06049             return FALSE;
06050         }
06051         *(BYTE **)pvStructInfo = NULL;
06052     }
06053     decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
06054     if (!decodeFunc)
06055     {
06056         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
06057          debugstr_a(lpszStructType));
06058         decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
06059          &hFunc);
06060     }
06061     if (decodeFunc)
06062         ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
06063          cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
06064     else
06065     {
06066         CryptDecodeObjectFunc pCryptDecodeObject =
06067          CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
06068 
06069         /* Try CryptDecodeObject function.  Don't call CryptDecodeObject
06070          * directly, as that could cause an infinite loop.
06071          */
06072         if (pCryptDecodeObject)
06073         {
06074             if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
06075             {
06076                 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
06077                  pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
06078                 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
06079                  pvStructInfo, pcbStructInfo, *pcbStructInfo)))
06080                 {
06081                     ret = pCryptDecodeObject(dwCertEncodingType,
06082                      lpszStructType, pbEncoded, cbEncoded, dwFlags,
06083                      *(BYTE **)pvStructInfo, pcbStructInfo);
06084                     if (!ret)
06085                         CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
06086                 }
06087             }
06088             else
06089                 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
06090                  pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
06091         }
06092     }
06093     if (hFunc)
06094         CryptFreeOIDFunctionAddress(hFunc, 0);
06095     TRACE_(crypt)("returning %d\n", ret);
06096     return ret;
06097 }
06098 
06099 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
06100 {
06101     BOOL ret;
06102 
06103     TRACE_(crypt)("(%p)\n", pPFX);
06104 
06105     /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
06106      * version integer of length 1 (3 encoded byes) and at least one other
06107      * datum (two encoded bytes), plus at least two bytes for the outer
06108      * sequence.  Thus, even an empty PFX blob is at least 7 bytes in length.
06109      */
06110     if (pPFX->cbData < 7)
06111         ret = FALSE;
06112     else if (pPFX->pbData[0] == ASN_SEQUENCE)
06113     {
06114         DWORD len;
06115 
06116         if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
06117         {
06118             BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
06119 
06120             /* Need at least three bytes for the integer version */
06121             if (pPFX->cbData < 1 + lenLen + 3)
06122                 ret = FALSE;
06123             else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
06124              pPFX->pbData[1 + lenLen + 1] != 1 ||          /* Definite length */
06125              pPFX->pbData[1 + lenLen + 2] != 3)            /* PFX version */
06126                 ret = FALSE;
06127         }
06128     }
06129     else
06130         ret = FALSE;
06131     return ret;
06132 }
06133 
06134 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
06135  DWORD dwFlags)
06136 {
06137     FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
06138     return NULL;
06139 }
06140 
06141 BOOL WINAPI PFXVerifyPassword(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
06142  DWORD dwFlags)
06143 {
06144     FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
06145     return FALSE;
06146 }

Generated on Sun May 27 2012 04:23:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.