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

encode.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2005-2008 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 encoding 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 "snmp.h"
00047 #include "wine/debug.h"
00048 #include "wine/exception.h"
00049 #include "wine/unicode.h"
00050 #include "crypt32_private.h"
00051 
00052 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
00053 WINE_DECLARE_DEBUG_CHANNEL(crypt);
00054 
00055 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
00056  BYTE *, DWORD *);
00057 
00058 /* Prototypes for built-in encoders.  They follow the Ex style prototypes.
00059  * The dwCertEncodingType and lpszStructType are ignored by the built-in
00060  * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
00061  * since it must call functions in external DLLs that follow these signatures.
00062  */
00063 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
00064  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00065  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00066 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
00067  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00068  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00069 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
00070  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00071  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00072 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
00073  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00074  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00075 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
00076  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00077  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00078 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
00079  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00080  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00081 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
00082  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00083  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00084 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
00085  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00086  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00087 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
00088  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00089  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00090 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
00091  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00092  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00093 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
00094  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00095  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00096 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
00097  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00098  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00099 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
00100  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00101  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
00102 
00103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara,
00104  BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
00105 {
00106     BOOL ret = TRUE;
00107 
00108     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00109     {
00110         if (pEncodePara && pEncodePara->pfnAlloc)
00111             *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
00112         else
00113             *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
00114         if (!*(BYTE **)pbEncoded)
00115             ret = FALSE;
00116         else
00117             *pcbEncoded = bytesNeeded;
00118     }
00119     else if (bytesNeeded > *pcbEncoded)
00120     {
00121         *pcbEncoded = bytesNeeded;
00122         SetLastError(ERROR_MORE_DATA);
00123         ret = FALSE;
00124     }
00125     else
00126         *pcbEncoded = bytesNeeded;
00127     return ret;
00128 }
00129 
00130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
00131 {
00132     if (pEncodePara && pEncodePara->pfnFree)
00133         pEncodePara->pfnFree(pv);
00134     else
00135         LocalFree(pv);
00136 }
00137 
00138 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
00139 {
00140     DWORD bytesNeeded, significantBytes = 0;
00141 
00142     if (len <= 0x7f)
00143         bytesNeeded = 1;
00144     else
00145     {
00146         DWORD temp;
00147 
00148         for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
00149          temp <<= 8, significantBytes--)
00150             ;
00151         bytesNeeded = significantBytes + 1;
00152     }
00153     if (!pbEncoded)
00154     {
00155         *pcbEncoded = bytesNeeded;
00156         return TRUE;
00157     }
00158     if (*pcbEncoded < bytesNeeded)
00159     {
00160         SetLastError(ERROR_MORE_DATA);
00161         return FALSE;
00162     }
00163     if (len <= 0x7f)
00164         *pbEncoded = (BYTE)len;
00165     else
00166     {
00167         DWORD i;
00168 
00169         *pbEncoded++ = significantBytes | 0x80;
00170         for (i = 0; i < significantBytes; i++)
00171         {
00172             *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
00173             len >>= 8;
00174         }
00175     }
00176     *pcbEncoded = bytesNeeded;
00177     return TRUE;
00178 }
00179 
00180 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
00181  struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
00182  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00183 {
00184     BOOL ret;
00185     DWORD i, dataLen = 0;
00186 
00187     TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
00188      pbEncoded, pbEncoded ? *pcbEncoded : 0);
00189     for (i = 0, ret = TRUE; ret && i < cItem; i++)
00190     {
00191         ret = items[i].encodeFunc(dwCertEncodingType, NULL,
00192          items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
00193          NULL, &items[i].size);
00194         /* Some functions propagate their errors through the size */
00195         if (!ret)
00196             *pcbEncoded = items[i].size;
00197         dataLen += items[i].size;
00198     }
00199     if (ret)
00200     {
00201         DWORD lenBytes, bytesNeeded;
00202 
00203         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
00204         bytesNeeded = 1 + lenBytes + dataLen;
00205         if (!pbEncoded)
00206             *pcbEncoded = bytesNeeded;
00207         else
00208         {
00209             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
00210              pcbEncoded, bytesNeeded)))
00211             {
00212                 BYTE *out;
00213 
00214                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00215                     pbEncoded = *(BYTE **)pbEncoded;
00216                 out = pbEncoded;
00217                 *out++ = ASN_SEQUENCE;
00218                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
00219                 out += lenBytes;
00220                 for (i = 0; ret && i < cItem; i++)
00221                 {
00222                     ret = items[i].encodeFunc(dwCertEncodingType, NULL,
00223                      items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
00224                      NULL, out, &items[i].size);
00225                     /* Some functions propagate their errors through the size */
00226                     if (!ret)
00227                         *pcbEncoded = items[i].size;
00228                     out += items[i].size;
00229                 }
00230                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
00231                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
00232             }
00233         }
00234     }
00235     TRACE("returning %d (%08x)\n", ret, GetLastError());
00236     return ret;
00237 }
00238 
00239 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
00240  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00241  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00242 {
00243     BOOL ret;
00244     const struct AsnConstructedItem *item = pvStructInfo;
00245     DWORD len;
00246 
00247     if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
00248      item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
00249     {
00250         DWORD dataLen, bytesNeeded;
00251 
00252         CRYPT_EncodeLen(len, NULL, &dataLen);
00253         bytesNeeded = 1 + dataLen + len;
00254         if (!pbEncoded)
00255             *pcbEncoded = bytesNeeded;
00256         else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
00257          pbEncoded, pcbEncoded, bytesNeeded)))
00258         {
00259             BYTE *out;
00260 
00261             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00262                 pbEncoded = *(BYTE **)pbEncoded;
00263             out = pbEncoded;
00264             *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
00265             CRYPT_EncodeLen(len, out, &dataLen);
00266             out += dataLen;
00267             ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
00268              item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
00269              out, &len);
00270             if (!ret)
00271             {
00272                 /* Some functions propagate their errors through the size */
00273                 *pcbEncoded = len;
00274                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00275                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
00276             }
00277         }
00278     }
00279     else
00280     {
00281         /* Some functions propagate their errors through the size */
00282         *pcbEncoded = len;
00283     }
00284     return ret;
00285 }
00286 
00287 struct AsnEncodeTagSwappedItem
00288 {
00289     BYTE                    tag;
00290     const void             *pvStructInfo;
00291     CryptEncodeObjectExFunc encodeFunc;
00292 };
00293 
00294 /* Sort of a wacky hack, it encodes something using the struct
00295  * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
00296  * given in the struct AsnEncodeTagSwappedItem.
00297  */
00298 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
00299  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00300  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00301 {
00302     BOOL ret;
00303     const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
00304 
00305     ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
00306      item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
00307     if (ret && pbEncoded)
00308         *pbEncoded = item->tag;
00309     return ret;
00310 }
00311 
00312 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
00313  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00314  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00315 {
00316     const DWORD *ver = pvStructInfo;
00317     BOOL ret;
00318 
00319     /* CERT_V1 is not encoded */
00320     if (*ver == CERT_V1)
00321     {
00322         *pcbEncoded = 0;
00323         ret = TRUE;
00324     }
00325     else
00326     {
00327         struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
00328 
00329         ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
00330          &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
00331     }
00332     return ret;
00333 }
00334 
00335 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
00336  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00337  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00338 {
00339     const CRYPT_DER_BLOB *blob = pvStructInfo;
00340     BOOL ret;
00341 
00342     if (!pbEncoded)
00343     {
00344         *pcbEncoded = blob->cbData;
00345         ret = TRUE;
00346     }
00347     else
00348     {
00349         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
00350          pcbEncoded, blob->cbData)))
00351         {
00352             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00353                 pbEncoded = *(BYTE **)pbEncoded;
00354             if (blob->cbData)
00355                 memcpy(pbEncoded, blob->pbData, blob->cbData);
00356             *pcbEncoded = blob->cbData;
00357         }
00358     }
00359     return ret;
00360 }
00361 
00362 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
00363  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00364  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00365 {
00366     BOOL ret;
00367     /* This has two filetimes in a row, a NotBefore and a NotAfter */
00368     const FILETIME *timePtr = pvStructInfo;
00369     struct AsnEncodeSequenceItem items[] = {
00370      { timePtr,     CRYPT_AsnEncodeChoiceOfTime, 0 },
00371      { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
00372     };
00373 
00374     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 
00375      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
00376      pcbEncoded);
00377     return ret;
00378 }
00379 
00380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
00381  * if they are empty.
00382  */
00383 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
00384  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
00385  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
00386  DWORD *pcbEncoded)
00387 {
00388     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
00389     static const BYTE asn1Null[] = { ASN_NULL, 0 };
00390     static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
00391      (LPBYTE)asn1Null };
00392     BOOL ret;
00393     struct AsnEncodeSequenceItem items[2] = {
00394      { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
00395      { NULL,           CRYPT_CopyEncodedBlob, 0 },
00396     };
00397 
00398     if (algo->Parameters.cbData)
00399         items[1].pvStructInfo = &algo->Parameters;
00400     else
00401         items[1].pvStructInfo = &nullBlob;
00402     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
00403      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
00404      pcbEncoded);
00405     return ret;
00406 }
00407 
00408 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
00409  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00410  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00411 {
00412     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
00413     BOOL ret;
00414     struct AsnEncodeSequenceItem items[] = {
00415      { algo->pszObjId,    CRYPT_AsnEncodeOid, 0 },
00416      { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
00417     };
00418 
00419     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
00420      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
00421      pcbEncoded);
00422     return ret;
00423 }
00424 
00425 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
00426  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00427  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00428 {
00429     BOOL ret;
00430 
00431     __TRY
00432     {
00433         const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
00434         struct AsnEncodeSequenceItem items[] = {
00435          { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
00436          { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
00437         };
00438 
00439         TRACE("Encoding public key with OID %s\n",
00440          debugstr_a(info->Algorithm.pszObjId));
00441         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
00442          sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
00443          pcbEncoded);
00444     }
00445     __EXCEPT_PAGE_FAULT
00446     {
00447         SetLastError(STATUS_ACCESS_VIOLATION);
00448         ret = FALSE;
00449     }
00450     __ENDTRY
00451     return ret;
00452 }
00453 
00454 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
00455  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00456  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00457 {
00458     BOOL ret;
00459 
00460     __TRY
00461     {
00462         const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
00463         struct AsnEncodeSequenceItem items[] = {
00464          { &info->ToBeSigned,         CRYPT_CopyEncodedBlob, 0 },
00465          { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
00466          { &info->Signature,          CRYPT_AsnEncodeBitsSwapBytes, 0 },
00467         };
00468 
00469         if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
00470             items[2].encodeFunc = CRYPT_AsnEncodeBits;
00471         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, 
00472          sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
00473          pcbEncoded);
00474     }
00475     __EXCEPT_PAGE_FAULT
00476     {
00477         SetLastError(STATUS_ACCESS_VIOLATION);
00478         ret = FALSE;
00479     }
00480     __ENDTRY
00481     return ret;
00482 }
00483 
00484 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
00485  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00486  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00487 {
00488     BOOL ret;
00489     const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
00490     struct AsnEncodeSequenceItem items[] = {
00491      { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
00492      { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
00493     };
00494 
00495     TRACE("Encoding public key with OID %s\n",
00496      debugstr_a(info->Algorithm.pszObjId));
00497     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
00498      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
00499      pcbEncoded);
00500     return ret;
00501 }
00502 
00503 /* Like in Windows, this blithely ignores the validity of the passed-in
00504  * CERT_INFO, and just encodes it as-is.  The resulting encoded data may not
00505  * decode properly, see CRYPT_AsnDecodeCertInfo.
00506  */
00507 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
00508  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00509  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00510 {
00511     BOOL ret;
00512 
00513     __TRY
00514     {
00515         const CERT_INFO *info = pvStructInfo;
00516         struct AsnEncodeSequenceItem items[10] = {
00517          { &info->dwVersion,            CRYPT_AsnEncodeCertVersion, 0 },
00518          { &info->SerialNumber,         CRYPT_AsnEncodeInteger, 0 },
00519          { &info->SignatureAlgorithm,   CRYPT_AsnEncodeAlgorithmId, 0 },
00520          { &info->Issuer,               CRYPT_CopyEncodedBlob, 0 },
00521          { &info->NotBefore,            CRYPT_AsnEncodeValidity, 0 },
00522          { &info->Subject,              CRYPT_CopyEncodedBlob, 0 },
00523          { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
00524          { 0 }
00525         };
00526         struct AsnConstructedItem constructed = { 0 };
00527         struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
00528         DWORD cItem = 7, cSwapped = 0;
00529 
00530         if (info->IssuerUniqueId.cbData)
00531         {
00532             swapped[cSwapped].tag = ASN_CONTEXT | 1;
00533             swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
00534             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
00535             items[cItem].pvStructInfo = &swapped[cSwapped];
00536             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
00537             cSwapped++;
00538             cItem++;
00539         }
00540         if (info->SubjectUniqueId.cbData)
00541         {
00542             swapped[cSwapped].tag = ASN_CONTEXT | 2;
00543             swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
00544             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
00545             items[cItem].pvStructInfo = &swapped[cSwapped];
00546             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
00547             cSwapped++;
00548             cItem++;
00549         }
00550         if (info->cExtension)
00551         {
00552             constructed.tag = 3;
00553             constructed.pvStructInfo = &info->cExtension;
00554             constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
00555             items[cItem].pvStructInfo = &constructed;
00556             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
00557             cItem++;
00558         }
00559 
00560         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
00561          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
00562     }
00563     __EXCEPT_PAGE_FAULT
00564     {
00565         SetLastError(STATUS_ACCESS_VIOLATION);
00566         ret = FALSE;
00567     }
00568     __ENDTRY
00569     return ret;
00570 }
00571 
00572 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
00573  BYTE *pbEncoded, DWORD *pcbEncoded)
00574 {
00575     struct AsnEncodeSequenceItem items[3] = {
00576      { &entry->SerialNumber,   CRYPT_AsnEncodeInteger, 0 },
00577      { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
00578      { 0 }
00579     };
00580     DWORD cItem = 2;
00581     BOOL ret;
00582 
00583     TRACE("%p, %p, %d\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0);
00584 
00585     if (entry->cExtension)
00586     {
00587         items[cItem].pvStructInfo = &entry->cExtension;
00588         items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
00589         cItem++;
00590     }
00591 
00592     ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
00593      pbEncoded, pcbEncoded);
00594 
00595     TRACE("returning %d (%08x)\n", ret, GetLastError());
00596     return ret;
00597 }
00598 
00599 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
00600  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00601  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00602 {
00603     DWORD bytesNeeded, dataLen, lenBytes, i;
00604     const CRL_INFO *info = pvStructInfo;
00605     const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
00606     BOOL ret = TRUE;
00607 
00608     for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
00609     {
00610         DWORD size;
00611 
00612         ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
00613         if (ret)
00614             dataLen += size;
00615     }
00616     if (ret)
00617     {
00618         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
00619         bytesNeeded = 1 + lenBytes + dataLen;
00620         if (!pbEncoded)
00621             *pcbEncoded = bytesNeeded;
00622         else
00623         {
00624             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
00625              pcbEncoded, bytesNeeded)))
00626             {
00627                 BYTE *out;
00628 
00629                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00630                     pbEncoded = *(BYTE **)pbEncoded;
00631                 out = pbEncoded;
00632                 *out++ = ASN_SEQUENCEOF;
00633                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
00634                 out += lenBytes;
00635                 for (i = 0; i < info->cCRLEntry; i++)
00636                 {
00637                     DWORD size = dataLen;
00638 
00639                     ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
00640                     out += size;
00641                     dataLen -= size;
00642                 }
00643                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
00644                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
00645             }
00646         }
00647     }
00648     return ret;
00649 }
00650 
00651 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
00652  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00653  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00654 {
00655     const DWORD *ver = pvStructInfo;
00656     BOOL ret;
00657 
00658     /* CRL_V1 is not encoded */
00659     if (*ver == CRL_V1)
00660     {
00661         *pcbEncoded = 0;
00662         ret = TRUE;
00663     }
00664     else
00665         ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
00666          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
00667     return ret;
00668 }
00669 
00670 /* Like in Windows, this blithely ignores the validity of the passed-in
00671  * CRL_INFO, and just encodes it as-is.  The resulting encoded data may not
00672  * decode properly, see CRYPT_AsnDecodeCRLInfo.
00673  */
00674 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
00675  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00676  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00677 {
00678     BOOL ret;
00679 
00680     __TRY
00681     {
00682         const CRL_INFO *info = pvStructInfo;
00683         struct AsnEncodeSequenceItem items[7] = {
00684          { &info->dwVersion,          CRYPT_AsnEncodeCRLVersion, 0 },
00685          { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
00686          { &info->Issuer,             CRYPT_CopyEncodedBlob, 0 },
00687          { &info->ThisUpdate,         CRYPT_AsnEncodeChoiceOfTime, 0 },
00688          { 0 }
00689         };
00690         struct AsnConstructedItem constructed[1] = { { 0 } };
00691         DWORD cItem = 4, cConstructed = 0;
00692 
00693         if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
00694         {
00695             items[cItem].pvStructInfo = &info->NextUpdate;
00696             items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
00697             cItem++;
00698         }
00699         if (info->cCRLEntry)
00700         {
00701             items[cItem].pvStructInfo = info;
00702             items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
00703             cItem++;
00704         }
00705         if (info->cExtension)
00706         {
00707             constructed[cConstructed].tag = 0;
00708             constructed[cConstructed].pvStructInfo = &info->cExtension;
00709             constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
00710             items[cItem].pvStructInfo = &constructed[cConstructed];
00711             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
00712             cConstructed++;
00713             cItem++;
00714         }
00715 
00716         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
00717          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
00718     }
00719     __EXCEPT_PAGE_FAULT
00720     {
00721         SetLastError(STATUS_ACCESS_VIOLATION);
00722         ret = FALSE;
00723     }
00724     __ENDTRY
00725     return ret;
00726 }
00727 
00728 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
00729  DWORD *pcbEncoded)
00730 {
00731     BOOL ret;
00732     struct AsnEncodeSequenceItem items[3] = {
00733      { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
00734      { NULL, NULL, 0 },
00735      { NULL, NULL, 0 },
00736     };
00737     DWORD cItem = 1;
00738 
00739     TRACE("%p, %p, %d\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0);
00740 
00741     if (ext->fCritical)
00742     {
00743         items[cItem].pvStructInfo = &ext->fCritical;
00744         items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
00745         cItem++;
00746     }
00747     items[cItem].pvStructInfo = &ext->Value;
00748     items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
00749     cItem++;
00750 
00751     ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
00752      pbEncoded, pcbEncoded);
00753     TRACE("returning %d (%08x)\n", ret, GetLastError());
00754     return ret;
00755 }
00756 
00757 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
00758  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00759  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00760 {
00761     BOOL ret;
00762 
00763     __TRY
00764     {
00765         DWORD bytesNeeded, dataLen, lenBytes, i;
00766         const CERT_EXTENSIONS *exts = pvStructInfo;
00767 
00768         ret = TRUE;
00769         for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
00770         {
00771             DWORD size;
00772 
00773             ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
00774             if (ret)
00775                 dataLen += size;
00776         }
00777         if (ret)
00778         {
00779             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
00780             bytesNeeded = 1 + lenBytes + dataLen;
00781             if (!pbEncoded)
00782                 *pcbEncoded = bytesNeeded;
00783             else
00784             {
00785                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
00786                  pbEncoded, pcbEncoded, bytesNeeded)))
00787                 {
00788                     BYTE *out;
00789 
00790                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00791                         pbEncoded = *(BYTE **)pbEncoded;
00792                     out = pbEncoded;
00793                     *out++ = ASN_SEQUENCEOF;
00794                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
00795                     out += lenBytes;
00796                     for (i = 0; i < exts->cExtension; i++)
00797                     {
00798                         DWORD size = dataLen;
00799 
00800                         ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
00801                          out, &size);
00802                         out += size;
00803                         dataLen -= size;
00804                     }
00805                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
00806                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
00807                 }
00808             }
00809         }
00810     }
00811     __EXCEPT_PAGE_FAULT
00812     {
00813         SetLastError(STATUS_ACCESS_VIOLATION);
00814         ret = FALSE;
00815     }
00816     __ENDTRY
00817     return ret;
00818 }
00819 
00820 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
00821  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
00822  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
00823 {
00824     LPCSTR pszObjId = pvStructInfo;
00825     DWORD bytesNeeded = 0, lenBytes;
00826     BOOL ret = TRUE;
00827     int firstPos = 0;
00828     BYTE firstByte = 0;
00829 
00830     TRACE("%s\n", debugstr_a(pszObjId));
00831 
00832     if (pszObjId)
00833     {
00834         const char *ptr;
00835         int val1, val2;
00836 
00837         if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
00838         {
00839             SetLastError(CRYPT_E_ASN1_ERROR);
00840             return FALSE;
00841         }
00842         bytesNeeded++;
00843         firstByte = val1 * 40 + val2;
00844         ptr = pszObjId + firstPos;
00845         if (*ptr == '.')
00846         {
00847             ptr++;
00848             firstPos++;
00849         }
00850         while (ret && *ptr)
00851         {
00852             int pos;
00853 
00854             /* note I assume each component is at most 32-bits long in base 2 */
00855             if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
00856             {
00857                 if (val1 >= 0x10000000)
00858                     bytesNeeded += 5;
00859                 else if (val1 >= 0x200000)
00860                     bytesNeeded += 4;
00861                 else if (val1 >= 0x4000)
00862                     bytesNeeded += 3;
00863                 else if (val1 >= 0x80)
00864                     bytesNeeded += 2;
00865                 else
00866                     bytesNeeded += 1;
00867                 ptr += pos;
00868                 if (*ptr == '.')
00869                     ptr++;
00870             }
00871             else
00872             {
00873                 SetLastError(CRYPT_E_ASN1_ERROR);
00874                 return FALSE;
00875             }
00876         }
00877         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
00878     }
00879     else
00880         lenBytes = 1;
00881     bytesNeeded += 1 + lenBytes;
00882     if (pbEncoded)
00883     {
00884         if (*pcbEncoded < bytesNeeded)
00885         {
00886             SetLastError(ERROR_MORE_DATA);
00887             ret = FALSE;
00888         }
00889         else
00890         {
00891             *pbEncoded++ = ASN_OBJECTIDENTIFIER;
00892             CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
00893             pbEncoded += lenBytes;
00894             if (pszObjId)
00895             {
00896                 const char *ptr;
00897                 int val, pos;
00898 
00899                 *pbEncoded++ = firstByte;
00900                 ptr = pszObjId + firstPos;
00901                 while (ret && *ptr)
00902                 {
00903                     sscanf(ptr, "%d%n", &val, &pos);
00904                     {
00905                         unsigned char outBytes[5];
00906                         int numBytes, i;
00907 
00908                         if (val >= 0x10000000)
00909                             numBytes = 5;
00910                         else if (val >= 0x200000)
00911                             numBytes = 4;
00912                         else if (val >= 0x4000)
00913                             numBytes = 3;
00914                         else if (val >= 0x80)
00915                             numBytes = 2;
00916                         else
00917                             numBytes = 1;
00918                         for (i = numBytes; i > 0; i--)
00919                         {
00920                             outBytes[i - 1] = val & 0x7f;
00921                             val >>= 7;
00922                         }
00923                         for (i = 0; i < numBytes - 1; i++)
00924                             *pbEncoded++ = outBytes[i] | 0x80;
00925                         *pbEncoded++ = outBytes[i];
00926                         ptr += pos;
00927                         if (*ptr == '.')
00928                             ptr++;
00929                     }
00930                 }
00931             }
00932         }
00933     }
00934     *pcbEncoded = bytesNeeded;
00935     return ret;
00936 }
00937 
00938 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
00939  BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
00940  DWORD *pcbEncoded)
00941 {
00942     BOOL ret = TRUE;
00943     LPCSTR str = (LPCSTR)value->Value.pbData;
00944     DWORD bytesNeeded, lenBytes, encodedLen;
00945 
00946     encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
00947     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
00948     bytesNeeded = 1 + lenBytes + encodedLen;
00949     if (!pbEncoded)
00950         *pcbEncoded = bytesNeeded;
00951     else
00952     {
00953         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
00954          pbEncoded, pcbEncoded, bytesNeeded)))
00955         {
00956             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00957                 pbEncoded = *(BYTE **)pbEncoded;
00958             *pbEncoded++ = tag;
00959             CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
00960             pbEncoded += lenBytes;
00961             memcpy(pbEncoded, str, encodedLen);
00962         }
00963     }
00964     return ret;
00965 }
00966 
00967 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
00968  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
00969  DWORD *pcbEncoded)
00970 {
00971     BOOL ret = TRUE;
00972     LPCWSTR str = (LPCWSTR)value->Value.pbData;
00973     DWORD bytesNeeded, lenBytes, strLen;
00974 
00975     if (value->Value.cbData)
00976         strLen = value->Value.cbData / sizeof(WCHAR);
00977     else if (value->Value.pbData)
00978         strLen = lstrlenW(str);
00979     else
00980         strLen = 0;
00981     CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
00982     bytesNeeded = 1 + lenBytes + strLen * 2;
00983     if (!pbEncoded)
00984         *pcbEncoded = bytesNeeded;
00985     else
00986     {
00987         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
00988          pbEncoded, pcbEncoded, bytesNeeded)))
00989         {
00990             DWORD i;
00991 
00992             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
00993                 pbEncoded = *(BYTE **)pbEncoded;
00994             *pbEncoded++ = ASN_BMPSTRING;
00995             CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
00996             pbEncoded += lenBytes;
00997             for (i = 0; i < strLen; i++)
00998             {
00999                 *pbEncoded++ = (str[i] & 0xff00) >> 8;
01000                 *pbEncoded++ = str[i] & 0x00ff;
01001             }
01002         }
01003     }
01004     return ret;
01005 }
01006 
01007 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
01008  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
01009  DWORD *pcbEncoded)
01010 {
01011     BOOL ret = TRUE;
01012     LPCWSTR str = (LPCWSTR)value->Value.pbData;
01013     DWORD bytesNeeded, lenBytes, encodedLen, strLen;
01014 
01015     if (value->Value.cbData)
01016         strLen = value->Value.cbData / sizeof(WCHAR);
01017     else if (str)
01018         strLen = strlenW(str);
01019     else
01020         strLen = 0;
01021     encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
01022      NULL);
01023     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
01024     bytesNeeded = 1 + lenBytes + encodedLen;
01025     if (!pbEncoded)
01026         *pcbEncoded = bytesNeeded;
01027     else
01028     {
01029         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
01030          pbEncoded, pcbEncoded, bytesNeeded)))
01031         {
01032             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01033                 pbEncoded = *(BYTE **)pbEncoded;
01034             *pbEncoded++ = ASN_UTF8STRING;
01035             CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
01036             pbEncoded += lenBytes;
01037             WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
01038              bytesNeeded - lenBytes - 1, NULL, NULL);
01039         }
01040     }
01041     return ret;
01042 }
01043 
01044 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
01045  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01046  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01047 {
01048     BOOL ret = TRUE;
01049 
01050     __TRY
01051     {
01052         const CERT_NAME_VALUE *value = pvStructInfo;
01053 
01054         switch (value->dwValueType)
01055         {
01056         case CERT_RDN_ANY_TYPE:
01057             /* explicitly disallowed */
01058             SetLastError(E_INVALIDARG);
01059             ret = FALSE;
01060             break;
01061         case CERT_RDN_ENCODED_BLOB:
01062             ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
01063              &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01064             break;
01065         case CERT_RDN_OCTET_STRING:
01066             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
01067              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01068             break;
01069         case CERT_RDN_NUMERIC_STRING:
01070             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
01071              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01072             break;
01073         case CERT_RDN_PRINTABLE_STRING:
01074             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
01075              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01076             break;
01077         case CERT_RDN_TELETEX_STRING:
01078             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
01079              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01080             break;
01081         case CERT_RDN_VIDEOTEX_STRING:
01082             ret = CRYPT_AsnEncodeStringCoerce(value,
01083              ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01084             break;
01085         case CERT_RDN_IA5_STRING:
01086             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
01087              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01088             break;
01089         case CERT_RDN_GRAPHIC_STRING:
01090             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
01091              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01092             break;
01093         case CERT_RDN_VISIBLE_STRING:
01094             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
01095              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01096             break;
01097         case CERT_RDN_GENERAL_STRING:
01098             ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
01099              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01100             break;
01101         case CERT_RDN_UNIVERSAL_STRING:
01102             FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
01103             SetLastError(CRYPT_E_ASN1_CHOICE);
01104             ret = FALSE;
01105             break;
01106         case CERT_RDN_BMP_STRING:
01107             ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
01108              pbEncoded, pcbEncoded);
01109             break;
01110         case CERT_RDN_UTF8_STRING:
01111             ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
01112              pbEncoded, pcbEncoded);
01113             break;
01114         default:
01115             SetLastError(CRYPT_E_ASN1_CHOICE);
01116             ret = FALSE;
01117         }
01118     }
01119     __EXCEPT_PAGE_FAULT
01120     {
01121         SetLastError(STATUS_ACCESS_VIOLATION);
01122         ret = FALSE;
01123     }
01124     __ENDTRY
01125     return ret;
01126 }
01127 
01128 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
01129  const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
01130  BYTE *pbEncoded, DWORD *pcbEncoded)
01131 {
01132     DWORD bytesNeeded = 0, lenBytes, size;
01133     BOOL ret;
01134 
01135     ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
01136      0, NULL, NULL, &size);
01137     if (ret)
01138     {
01139         bytesNeeded += size;
01140         /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
01141          * with dwValueType, so "cast" it to get its encoded size
01142          */
01143         ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
01144          0, NULL, NULL, &size);
01145         if (ret)
01146         {
01147             bytesNeeded += size;
01148             CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
01149             bytesNeeded += 1 + lenBytes;
01150             if (pbEncoded)
01151             {
01152                 if (*pcbEncoded < bytesNeeded)
01153                 {
01154                     SetLastError(ERROR_MORE_DATA);
01155                     ret = FALSE;
01156                 }
01157                 else
01158                 {
01159                     *pbEncoded++ = ASN_SEQUENCE;
01160                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
01161                      &lenBytes);
01162                     pbEncoded += lenBytes;
01163                     size = bytesNeeded - 1 - lenBytes;
01164                     ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
01165                      attr->pszObjId, 0, NULL, pbEncoded, &size);
01166                     if (ret)
01167                     {
01168                         pbEncoded += size;
01169                         size = bytesNeeded - 1 - lenBytes - size;
01170                         ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
01171                          &attr->dwValueType, 0, NULL, pbEncoded, &size);
01172                         if (!ret)
01173                             *pcbEncoded = size;
01174                     }
01175                 }
01176             }
01177             if (ret)
01178                 *pcbEncoded = bytesNeeded;
01179         }
01180         else
01181         {
01182             /* Have to propagate index of failing character */
01183             *pcbEncoded = size;
01184         }
01185     }
01186     return ret;
01187 }
01188 
01189 static int BLOBComp(const void *l, const void *r)
01190 {
01191     const CRYPT_DER_BLOB *a = l, *b = r;
01192     int ret;
01193 
01194     if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
01195         ret = a->cbData - b->cbData;
01196     return ret;
01197 }
01198 
01199 /* This encodes a SET OF, which in DER must be lexicographically sorted.
01200  */
01201 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
01202  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01203  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01204 {
01205     const CRYPT_BLOB_ARRAY *set = pvStructInfo;
01206     DWORD bytesNeeded = 0, lenBytes, i;
01207     BOOL ret;
01208 
01209     for (i = 0; i < set->cBlob; i++)
01210         bytesNeeded += set->rgBlob[i].cbData;
01211     CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
01212     bytesNeeded += 1 + lenBytes;
01213     if (!pbEncoded)
01214     {
01215         *pcbEncoded = bytesNeeded;
01216         ret = TRUE;
01217     }
01218     else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
01219      pbEncoded, pcbEncoded, bytesNeeded)))
01220     {
01221         if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01222             pbEncoded = *(BYTE **)pbEncoded;
01223         qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
01224         *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
01225         CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
01226         pbEncoded += lenBytes;
01227         for (i = 0; i < set->cBlob; i++)
01228         {
01229             memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
01230             pbEncoded += set->rgBlob[i].cbData;
01231         }
01232     }
01233     return ret;
01234 }
01235 
01236 struct DERSetDescriptor
01237 {
01238     DWORD                   cItems;
01239     const void             *items;
01240     size_t                  itemSize;
01241     size_t                  itemOffset;
01242     CryptEncodeObjectExFunc encode;
01243 };
01244 
01245 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
01246  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01247  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01248 {
01249     const struct DERSetDescriptor *desc = pvStructInfo;
01250     CRYPT_BLOB_ARRAY setOf = { 0, NULL };
01251     BOOL ret = TRUE;
01252     DWORD i;
01253 
01254     if (desc->cItems)
01255     {
01256         setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
01257         if (!setOf.rgBlob)
01258             ret = FALSE;
01259         else
01260         {
01261             setOf.cBlob = desc->cItems;
01262             memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
01263         }
01264     }
01265     for (i = 0; ret && i < setOf.cBlob; i++)
01266     {
01267         ret = desc->encode(dwCertEncodingType, lpszStructType,
01268          (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
01269          0, NULL, NULL, &setOf.rgBlob[i].cbData);
01270         if (ret)
01271         {
01272             setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
01273             if (!setOf.rgBlob[i].pbData)
01274                 ret = FALSE;
01275             else
01276                 ret = desc->encode(dwCertEncodingType, lpszStructType,
01277                  (const BYTE *)desc->items + i * desc->itemSize +
01278                  desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
01279                  &setOf.rgBlob[i].cbData);
01280         }
01281         /* Some functions propagate their errors through the size */
01282         if (!ret)
01283             *pcbEncoded = setOf.rgBlob[i].cbData;
01284     }
01285     if (ret)
01286     {
01287         DWORD bytesNeeded = 0, lenBytes;
01288 
01289         for (i = 0; i < setOf.cBlob; i++)
01290             bytesNeeded += setOf.rgBlob[i].cbData;
01291         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
01292         bytesNeeded += 1 + lenBytes;
01293         if (!pbEncoded)
01294             *pcbEncoded = bytesNeeded;
01295         else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
01296          pbEncoded, pcbEncoded, bytesNeeded)))
01297         {
01298             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01299                 pbEncoded = *(BYTE **)pbEncoded;
01300             qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
01301              BLOBComp);
01302             *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
01303             CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
01304             pbEncoded += lenBytes;
01305             for (i = 0; i < setOf.cBlob; i++)
01306             {
01307                 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
01308                  setOf.rgBlob[i].cbData);
01309                 pbEncoded += setOf.rgBlob[i].cbData;
01310             }
01311         }
01312     }
01313     for (i = 0; i < setOf.cBlob; i++)
01314         CryptMemFree(setOf.rgBlob[i].pbData);
01315     CryptMemFree(setOf.rgBlob);
01316     return ret;
01317 }
01318 
01319 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
01320  CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
01321  DWORD *pcbEncoded)
01322 {
01323     BOOL ret;
01324     CRYPT_BLOB_ARRAY setOf = { 0, NULL };
01325 
01326     __TRY
01327     {
01328         DWORD i;
01329 
01330         ret = TRUE;
01331         if (rdn->cRDNAttr)
01332         {
01333             setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
01334              sizeof(CRYPT_DER_BLOB));
01335             if (!setOf.rgBlob)
01336                 ret = FALSE;
01337             else
01338             {
01339                 setOf.cBlob = rdn->cRDNAttr;
01340                 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
01341             }
01342         }
01343         for (i = 0; ret && i < rdn->cRDNAttr; i++)
01344         {
01345             setOf.rgBlob[i].cbData = 0;
01346             ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
01347              nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
01348             if (ret)
01349             {
01350                 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
01351                 if (!setOf.rgBlob[i].pbData)
01352                     ret = FALSE;
01353                 else
01354                     ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
01355                      &rdn->rgRDNAttr[i], nameValueEncodeFunc,
01356                      setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
01357             }
01358             if (!ret)
01359             {
01360                 /* Have to propagate index of failing character */
01361                 *pcbEncoded = setOf.rgBlob[i].cbData;
01362             }
01363         }
01364         if (ret)
01365             ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
01366              pbEncoded, pcbEncoded);
01367         for (i = 0; i < setOf.cBlob; i++)
01368             CryptMemFree(setOf.rgBlob[i].pbData);
01369     }
01370     __EXCEPT_PAGE_FAULT
01371     {
01372         SetLastError(STATUS_ACCESS_VIOLATION);
01373         ret = FALSE;
01374     }
01375     __ENDTRY
01376     CryptMemFree(setOf.rgBlob);
01377     return ret;
01378 }
01379 
01380 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
01381  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01382  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
01383 
01384 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
01385  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
01386  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
01387  DWORD *pcbEncoded)
01388 {
01389     const CERT_NAME_VALUE *value = pvStructInfo;
01390     BOOL ret;
01391 
01392     if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
01393         ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
01394          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01395     else
01396         ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
01397          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01398     return ret;
01399 }
01400 
01401 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
01402  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01403  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01404 {
01405     BOOL ret = TRUE;
01406 
01407     __TRY
01408     {
01409         const CERT_NAME_INFO *info = pvStructInfo;
01410         DWORD bytesNeeded = 0, lenBytes, size, i;
01411 
01412         TRACE("encoding name with %d RDNs\n", info->cRDN);
01413         ret = TRUE;
01414         for (i = 0; ret && i < info->cRDN; i++)
01415         {
01416             ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
01417              CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
01418             if (ret)
01419                 bytesNeeded += size;
01420             else
01421                 *pcbEncoded = size;
01422         }
01423         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
01424         bytesNeeded += 1 + lenBytes;
01425         if (ret)
01426         {
01427             if (!pbEncoded)
01428                 *pcbEncoded = bytesNeeded;
01429             else
01430             {
01431                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
01432                  pbEncoded, pcbEncoded, bytesNeeded)))
01433                 {
01434                     BYTE *out;
01435 
01436                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01437                         pbEncoded = *(BYTE **)pbEncoded;
01438                     out = pbEncoded;
01439                     *out++ = ASN_SEQUENCEOF;
01440                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
01441                     out += lenBytes;
01442                     for (i = 0; ret && i < info->cRDN; i++)
01443                     {
01444                         size = bytesNeeded;
01445                         ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
01446                          &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
01447                          out, &size);
01448                         if (ret)
01449                         {
01450                             out += size;
01451                             bytesNeeded -= size;
01452                         }
01453                         else
01454                             *pcbEncoded = size;
01455                     }
01456                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
01457                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
01458                 }
01459             }
01460         }
01461     }
01462     __EXCEPT_PAGE_FAULT
01463     {
01464         SetLastError(STATUS_ACCESS_VIOLATION);
01465         ret = FALSE;
01466     }
01467     __ENDTRY
01468     return ret;
01469 }
01470 
01471 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
01472  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01473  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01474 {
01475     const DWORD *ver = pvStructInfo;
01476     BOOL ret;
01477 
01478     /* CTL_V1 is not encoded */
01479     if (*ver == CTL_V1)
01480     {
01481         *pcbEncoded = 0;
01482         ret = TRUE;
01483     }
01484     else
01485         ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
01486          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01487     return ret;
01488 }
01489 
01490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
01491  * if they are empty and the OID is not empty (otherwise omits them.)
01492  */
01493 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
01494  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
01495  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
01496  DWORD *pcbEncoded)
01497 {
01498     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
01499     BOOL ret;
01500     struct AsnEncodeSequenceItem items[2] = {
01501      { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
01502     };
01503     DWORD cItem = 1;
01504 
01505     if (algo->pszObjId)
01506     {
01507         static const BYTE asn1Null[] = { ASN_NULL, 0 };
01508         static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
01509          (LPBYTE)asn1Null };
01510 
01511         if (algo->Parameters.cbData)
01512             items[cItem].pvStructInfo = &algo->Parameters;
01513         else
01514             items[cItem].pvStructInfo = &nullBlob;
01515         items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
01516         cItem++;
01517     }
01518     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
01519      dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01520     return ret;
01521 }
01522 
01523 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
01524  BYTE *pbEncoded, DWORD *pcbEncoded)
01525 {
01526     struct AsnEncodeSequenceItem items[2] = {
01527      { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
01528      { &entry->cAttribute,        CRYPT_AsnEncodePKCSAttributes, 0 },
01529     };
01530     BOOL ret;
01531 
01532     ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
01533      sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
01534     return ret;
01535 }
01536 
01537 struct CTLEntries
01538 {
01539     DWORD      cEntry;
01540     CTL_ENTRY *rgEntry;
01541 };
01542 
01543 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
01544  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01545  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01546 {
01547     BOOL ret;
01548     DWORD bytesNeeded, dataLen, lenBytes, i;
01549     const struct CTLEntries *entries = pvStructInfo;
01550 
01551     ret = TRUE;
01552     for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
01553     {
01554         DWORD size;
01555 
01556         ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
01557         if (ret)
01558             dataLen += size;
01559     }
01560     if (ret)
01561     {
01562         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
01563         bytesNeeded = 1 + lenBytes + dataLen;
01564         if (!pbEncoded)
01565             *pcbEncoded = bytesNeeded;
01566         else
01567         {
01568             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
01569              pbEncoded, pcbEncoded, bytesNeeded)))
01570             {
01571                 BYTE *out;
01572 
01573                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01574                     pbEncoded = *(BYTE **)pbEncoded;
01575                 out = pbEncoded;
01576                 *out++ = ASN_SEQUENCEOF;
01577                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
01578                 out += lenBytes;
01579                 for (i = 0; ret && i < entries->cEntry; i++)
01580                 {
01581                     DWORD size = dataLen;
01582 
01583                     ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
01584                      out, &size);
01585                     out += size;
01586                     dataLen -= size;
01587                 }
01588                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
01589                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
01590             }
01591         }
01592     }
01593     return ret;
01594 }
01595 
01596 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
01597  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01598  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01599 {
01600     BOOL ret = FALSE;
01601 
01602     __TRY
01603     {
01604         const CTL_INFO *info = pvStructInfo;
01605         struct AsnEncodeSequenceItem items[9] = {
01606          { &info->dwVersion,        CRYPT_AsnEncodeCTLVersion, 0 },
01607          { &info->SubjectUsage,     CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
01608         };
01609         struct AsnConstructedItem constructed = { 0 };
01610         DWORD cItem = 2;
01611 
01612         if (info->ListIdentifier.cbData)
01613         {
01614             items[cItem].pvStructInfo = &info->ListIdentifier;
01615             items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
01616             cItem++;
01617         }
01618         if (info->SequenceNumber.cbData)
01619         {
01620             items[cItem].pvStructInfo = &info->SequenceNumber;
01621             items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
01622             cItem++;
01623         }
01624         items[cItem].pvStructInfo = &info->ThisUpdate;
01625         items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
01626         cItem++;
01627         if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
01628         {
01629             items[cItem].pvStructInfo = &info->NextUpdate;
01630             items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
01631             cItem++;
01632         }
01633         items[cItem].pvStructInfo = &info->SubjectAlgorithm;
01634         items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
01635         cItem++;
01636         if (info->cCTLEntry)
01637         {
01638             items[cItem].pvStructInfo = &info->cCTLEntry;
01639             items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
01640             cItem++;
01641         }
01642         if (info->cExtension)
01643         {
01644             constructed.tag = 0;
01645             constructed.pvStructInfo = &info->cExtension;
01646             constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
01647             items[cItem].pvStructInfo = &constructed;
01648             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
01649             cItem++;
01650         }
01651         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
01652          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01653     }
01654     __EXCEPT_PAGE_FAULT
01655     {
01656         SetLastError(STATUS_ACCESS_VIOLATION);
01657     }
01658     __ENDTRY
01659     return ret;
01660 }
01661 
01662 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
01663  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01664  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01665 {
01666     BOOL ret = FALSE;
01667 
01668     __TRY
01669     {
01670         const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
01671 
01672         if (!capability->pszObjId)
01673             SetLastError(E_INVALIDARG);
01674         else
01675         {
01676             struct AsnEncodeSequenceItem items[] = {
01677              { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
01678              { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
01679             };
01680 
01681             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
01682              sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
01683              pcbEncoded);
01684         }
01685     }
01686     __EXCEPT_PAGE_FAULT
01687     {
01688         SetLastError(STATUS_ACCESS_VIOLATION);
01689     }
01690     __ENDTRY
01691     return ret;
01692 }
01693 
01694 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
01695  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01696  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01697 {
01698     BOOL ret = FALSE;
01699 
01700     __TRY
01701     {
01702         DWORD bytesNeeded, dataLen, lenBytes, i;
01703         const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
01704 
01705         ret = TRUE;
01706         for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
01707         {
01708             DWORD size;
01709 
01710             ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
01711              &capabilities->rgCapability[i], 0, NULL, NULL, &size);
01712             if (ret)
01713                 dataLen += size;
01714         }
01715         if (ret)
01716         {
01717             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
01718             bytesNeeded = 1 + lenBytes + dataLen;
01719             if (!pbEncoded)
01720                 *pcbEncoded = bytesNeeded;
01721             else
01722             {
01723                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
01724                  pbEncoded, pcbEncoded, bytesNeeded)))
01725                 {
01726                     BYTE *out;
01727 
01728                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01729                         pbEncoded = *(BYTE **)pbEncoded;
01730                     out = pbEncoded;
01731                     *out++ = ASN_SEQUENCEOF;
01732                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
01733                     out += lenBytes;
01734                     for (i = 0; i < capabilities->cCapability; i++)
01735                     {
01736                         DWORD size = dataLen;
01737 
01738                         ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
01739                          NULL, &capabilities->rgCapability[i], 0, NULL,
01740                          out, &size);
01741                         out += size;
01742                         dataLen -= size;
01743                     }
01744                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
01745                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
01746                 }
01747             }
01748         }
01749     }
01750     __EXCEPT_PAGE_FAULT
01751     {
01752         SetLastError(STATUS_ACCESS_VIOLATION);
01753     }
01754     __ENDTRY
01755     return ret;
01756 }
01757 
01758 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
01759  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01760  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01761 {
01762     const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
01763     DWORD bytesNeeded, dataLen, lenBytes, i;
01764     BOOL ret = TRUE;
01765 
01766     for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
01767     {
01768         DWORD size;
01769 
01770         ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
01771          &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
01772         if (ret)
01773             dataLen += size;
01774     }
01775     if (ret)
01776     {
01777         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
01778         bytesNeeded = 1 + lenBytes + dataLen;
01779         if (!pbEncoded)
01780             *pcbEncoded = bytesNeeded;
01781         else
01782         {
01783             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
01784              pcbEncoded, bytesNeeded)))
01785             {
01786                 BYTE *out;
01787 
01788                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
01789                     pbEncoded = *(BYTE **)pbEncoded;
01790                 out = pbEncoded;
01791                 *out++ = ASN_SEQUENCE;
01792                 CRYPT_EncodeLen(dataLen, out, &lenBytes);
01793                 out += lenBytes;
01794                 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
01795                 {
01796                     DWORD size = dataLen;
01797 
01798                     ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
01799                      &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
01800                     out += size;
01801                     dataLen -= size;
01802                 }
01803                 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
01804                     CRYPT_FreeSpace(pEncodePara, pbEncoded);
01805             }
01806         }
01807     }
01808     return ret;
01809 }
01810 
01811 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
01812  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01813  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01814 {
01815     const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
01816     BOOL ret;
01817     CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
01818      { 0, (LPBYTE)noticeRef->pszOrganization } };
01819     struct AsnEncodeSequenceItem items[] = {
01820      { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
01821      { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
01822     };
01823 
01824     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
01825      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
01826      pcbEncoded);
01827     return ret;
01828 }
01829 
01830 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
01831  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
01832  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
01833  DWORD *pcbEncoded)
01834 {
01835     BOOL ret = FALSE;
01836 
01837     __TRY
01838     {
01839         const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
01840         struct AsnEncodeSequenceItem items[2];
01841         CERT_NAME_VALUE displayTextValue;
01842         DWORD cItem = 0;
01843 
01844         if (notice->pNoticeReference)
01845         {
01846             items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
01847             items[cItem].pvStructInfo = notice->pNoticeReference;
01848             cItem++;
01849         }
01850         if (notice->pszDisplayText)
01851         {
01852             displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
01853             displayTextValue.Value.cbData = 0;
01854             displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
01855             items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
01856             items[cItem].pvStructInfo = &displayTextValue;
01857             cItem++;
01858         }
01859         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
01860          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01861     }
01862     __EXCEPT_PAGE_FAULT
01863     {
01864         SetLastError(STATUS_ACCESS_VIOLATION);
01865     }
01866     __ENDTRY
01867     return ret;
01868 }
01869 
01870 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
01871  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01872  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01873 {
01874     BOOL ret = FALSE;
01875 
01876     __TRY
01877     {
01878         const CRYPT_ATTRIBUTE *attr = pvStructInfo;
01879 
01880         if (!attr->pszObjId)
01881             SetLastError(E_INVALIDARG);
01882         else
01883         {
01884             struct AsnEncodeSequenceItem items[2] = {
01885              { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
01886              { &attr->cValue, CRYPT_DEREncodeSet, 0 },
01887             };
01888 
01889             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
01890              sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
01891              pcbEncoded);
01892         }
01893     }
01894     __EXCEPT_PAGE_FAULT
01895     {
01896         SetLastError(STATUS_ACCESS_VIOLATION);
01897     }
01898     __ENDTRY
01899     return ret;
01900 }
01901 
01902 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
01903  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01904  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01905 {
01906     BOOL ret = FALSE;
01907 
01908     __TRY
01909     {
01910         const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
01911         struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
01912          sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
01913 
01914         ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
01915          &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01916     }
01917     __EXCEPT_PAGE_FAULT
01918     {
01919         SetLastError(STATUS_ACCESS_VIOLATION);
01920     }
01921     __ENDTRY
01922     return ret;
01923 }
01924 
01925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
01926 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
01927  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
01928  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
01929  DWORD *pcbEncoded)
01930 {
01931     const CRYPT_CONTENT_INFO *info = pvStructInfo;
01932     struct AsnEncodeSequenceItem items[2] = {
01933      { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
01934      { NULL, NULL, 0 },
01935     };
01936     struct AsnConstructedItem constructed = { 0 };
01937     DWORD cItem = 1;
01938 
01939     if (info->Content.cbData)
01940     {
01941         constructed.tag = 0;
01942         constructed.pvStructInfo = &info->Content;
01943         constructed.encodeFunc = CRYPT_CopyEncodedBlob;
01944         items[cItem].pvStructInfo = &constructed;
01945         items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
01946         cItem++;
01947     }
01948     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
01949      cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
01950 }
01951 
01952 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
01953  void *pvData, DWORD *pcbData)
01954 {
01955     struct AsnEncodeSequenceItem items[] = {
01956      { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
01957      { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
01958        0 },
01959      { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
01960      { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
01961     };
01962 
01963     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
01964      sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
01965 }
01966 
01967 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
01968  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
01969  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
01970 {
01971     BOOL ret = FALSE;
01972 
01973     __TRY
01974     {
01975         const CRYPT_CONTENT_INFO *info = pvStructInfo;
01976 
01977         if (!info->pszObjId)
01978             SetLastError(E_INVALIDARG);
01979         else
01980             ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
01981              lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
01982              pcbEncoded);
01983     }
01984     __EXCEPT_PAGE_FAULT
01985     {
01986         SetLastError(STATUS_ACCESS_VIOLATION);
01987     }
01988     __ENDTRY
01989     return ret;
01990 }
01991 
01992 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
01993  BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
01994  DWORD *pcbEncoded)
01995 {
01996     BOOL ret = TRUE;
01997     LPCWSTR str = (LPCWSTR)value->Value.pbData;
01998     DWORD bytesNeeded, lenBytes, encodedLen;
01999 
02000     if (value->Value.cbData)
02001         encodedLen = value->Value.cbData / sizeof(WCHAR);
02002     else if (str)
02003         encodedLen = strlenW(str);
02004     else
02005         encodedLen = 0;
02006     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
02007     bytesNeeded = 1 + lenBytes + encodedLen;
02008     if (!pbEncoded)
02009         *pcbEncoded = bytesNeeded;
02010     else
02011     {
02012         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02013          pbEncoded, pcbEncoded, bytesNeeded)))
02014         {
02015             DWORD i;
02016 
02017             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02018                 pbEncoded = *(BYTE **)pbEncoded;
02019             *pbEncoded++ = tag;
02020             CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
02021             pbEncoded += lenBytes;
02022             for (i = 0; i < encodedLen; i++)
02023                 *pbEncoded++ = (BYTE)str[i];
02024         }
02025     }
02026     return ret;
02027 }
02028 
02029 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
02030  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
02031  DWORD *pcbEncoded)
02032 {
02033     BOOL ret = TRUE;
02034     LPCWSTR str = (LPCWSTR)value->Value.pbData;
02035     DWORD bytesNeeded, lenBytes, encodedLen;
02036 
02037     if (value->Value.cbData)
02038         encodedLen = value->Value.cbData / sizeof(WCHAR);
02039     else if (str)
02040         encodedLen = strlenW(str);
02041     else
02042         encodedLen = 0;
02043     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
02044     bytesNeeded = 1 + lenBytes + encodedLen;
02045     if (!pbEncoded)
02046         *pcbEncoded = bytesNeeded;
02047     else
02048     {
02049         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02050          pbEncoded, pcbEncoded, bytesNeeded)))
02051         {
02052             DWORD i;
02053             BYTE *ptr;
02054 
02055             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02056                 ptr = *(BYTE **)pbEncoded;
02057             else
02058                 ptr = pbEncoded;
02059             *ptr++ = ASN_NUMERICSTRING;
02060             CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
02061             ptr += lenBytes;
02062             for (i = 0; ret && i < encodedLen; i++)
02063             {
02064                 if (isdigitW(str[i]))
02065                     *ptr++ = (BYTE)str[i];
02066                 else
02067                 {
02068                     *pcbEncoded = i;
02069                     SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
02070                     ret = FALSE;
02071                 }
02072             }
02073             if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02074                 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
02075         }
02076     }
02077     return ret;
02078 }
02079 
02080 static inline int isprintableW(WCHAR wc)
02081 {
02082     return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
02083      wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
02084      wc == '/' || wc == ':' || wc == '=' || wc == '?';
02085 }
02086 
02087 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
02088  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
02089  DWORD *pcbEncoded)
02090 {
02091     BOOL ret = TRUE;
02092     LPCWSTR str = (LPCWSTR)value->Value.pbData;
02093     DWORD bytesNeeded, lenBytes, encodedLen;
02094 
02095     if (value->Value.cbData)
02096         encodedLen = value->Value.cbData / sizeof(WCHAR);
02097     else if (str)
02098         encodedLen = strlenW(str);
02099     else
02100         encodedLen = 0;
02101     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
02102     bytesNeeded = 1 + lenBytes + encodedLen;
02103     if (!pbEncoded)
02104         *pcbEncoded = bytesNeeded;
02105     else
02106     {
02107         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02108          pbEncoded, pcbEncoded, bytesNeeded)))
02109         {
02110             DWORD i;
02111             BYTE *ptr;
02112 
02113             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02114                 ptr = *(BYTE **)pbEncoded;
02115             else
02116                 ptr = pbEncoded;
02117             *ptr++ = ASN_PRINTABLESTRING;
02118             CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
02119             ptr += lenBytes;
02120             for (i = 0; ret && i < encodedLen; i++)
02121             {
02122                 if (isprintableW(str[i]))
02123                     *ptr++ = (BYTE)str[i];
02124                 else
02125                 {
02126                     *pcbEncoded = i;
02127                     SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
02128                     ret = FALSE;
02129                 }
02130             }
02131             if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02132                 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
02133         }
02134     }
02135     return ret;
02136 }
02137 
02138 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
02139  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
02140  DWORD *pcbEncoded)
02141 {
02142     BOOL ret = TRUE;
02143     LPCWSTR str = (LPCWSTR)value->Value.pbData;
02144     DWORD bytesNeeded, lenBytes, encodedLen;
02145 
02146     if (value->Value.cbData)
02147         encodedLen = value->Value.cbData / sizeof(WCHAR);
02148     else if (str)
02149         encodedLen = strlenW(str);
02150     else
02151         encodedLen = 0;
02152     CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
02153     bytesNeeded = 1 + lenBytes + encodedLen;
02154     if (!pbEncoded)
02155         *pcbEncoded = bytesNeeded;
02156     else
02157     {
02158         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02159          pbEncoded, pcbEncoded, bytesNeeded)))
02160         {
02161             DWORD i;
02162             BYTE *ptr;
02163 
02164             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02165                 ptr = *(BYTE **)pbEncoded;
02166             else
02167                 ptr = pbEncoded;
02168             *ptr++ = ASN_IA5STRING;
02169             CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
02170             ptr += lenBytes;
02171             for (i = 0; ret && i < encodedLen; i++)
02172             {
02173                 if (str[i] <= 0x7f)
02174                     *ptr++ = (BYTE)str[i];
02175                 else
02176                 {
02177                     *pcbEncoded = i;
02178                     SetLastError(CRYPT_E_INVALID_IA5_STRING);
02179                     ret = FALSE;
02180                 }
02181             }
02182             if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02183                 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
02184         }
02185     }
02186     return ret;
02187 }
02188 
02189 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
02190  DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
02191  DWORD *pcbEncoded)
02192 {
02193     BOOL ret = TRUE;
02194     LPCWSTR str = (LPCWSTR)value->Value.pbData;
02195     DWORD bytesNeeded, lenBytes, strLen;
02196 
02197     /* FIXME: doesn't handle composite characters */
02198     if (value->Value.cbData)
02199         strLen = value->Value.cbData / sizeof(WCHAR);
02200     else if (str)
02201         strLen = strlenW(str);
02202     else
02203         strLen = 0;
02204     CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
02205     bytesNeeded = 1 + lenBytes + strLen * 4;
02206     if (!pbEncoded)
02207         *pcbEncoded = bytesNeeded;
02208     else
02209     {
02210         if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02211          pbEncoded, pcbEncoded, bytesNeeded)))
02212         {
02213             DWORD i;
02214 
02215             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02216                 pbEncoded = *(BYTE **)pbEncoded;
02217             *pbEncoded++ = ASN_UNIVERSALSTRING;
02218             CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
02219             pbEncoded += lenBytes;
02220             for (i = 0; i < strLen; i++)
02221             {
02222                 *pbEncoded++ = 0;
02223                 *pbEncoded++ = 0;
02224                 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
02225                 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
02226             }
02227         }
02228     }
02229     return ret;
02230 }
02231 
02232 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
02233  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02234  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02235 {
02236     BOOL ret = FALSE;
02237 
02238     __TRY
02239     {
02240         const CERT_NAME_VALUE *value = pvStructInfo;
02241 
02242         switch (value->dwValueType)
02243         {
02244         case CERT_RDN_ANY_TYPE:
02245         case CERT_RDN_ENCODED_BLOB:
02246         case CERT_RDN_OCTET_STRING:
02247             SetLastError(CRYPT_E_NOT_CHAR_STRING);
02248             break;
02249         case CERT_RDN_NUMERIC_STRING:
02250             ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
02251              pbEncoded, pcbEncoded);
02252             break;
02253         case CERT_RDN_PRINTABLE_STRING:
02254             ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
02255              pbEncoded, pcbEncoded);
02256             break;
02257         case CERT_RDN_TELETEX_STRING:
02258             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
02259              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02260             break;
02261         case CERT_RDN_VIDEOTEX_STRING:
02262             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
02263              ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02264             break;
02265         case CERT_RDN_IA5_STRING:
02266             ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
02267              pbEncoded, pcbEncoded);
02268             break;
02269         case CERT_RDN_GRAPHIC_STRING:
02270             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
02271              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02272             break;
02273         case CERT_RDN_VISIBLE_STRING:
02274             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
02275              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02276             break;
02277         case CERT_RDN_GENERAL_STRING:
02278             ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
02279              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02280             break;
02281         case CERT_RDN_UNIVERSAL_STRING:
02282             ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
02283              pbEncoded, pcbEncoded);
02284             break;
02285         case CERT_RDN_BMP_STRING:
02286             ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
02287              pbEncoded, pcbEncoded);
02288             break;
02289         case CERT_RDN_UTF8_STRING:
02290             ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
02291              pbEncoded, pcbEncoded);
02292             break;
02293         default:
02294             SetLastError(CRYPT_E_ASN1_CHOICE);
02295         }
02296     }
02297     __EXCEPT_PAGE_FAULT
02298     {
02299         SetLastError(STATUS_ACCESS_VIOLATION);
02300     }
02301     __ENDTRY
02302     return ret;
02303 }
02304 
02305 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
02306  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02307  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02308 {
02309     BOOL ret;
02310 
02311     __TRY
02312     {
02313         const CERT_NAME_INFO *info = pvStructInfo;
02314         DWORD bytesNeeded = 0, lenBytes, size, i;
02315 
02316         TRACE("encoding name with %d RDNs\n", info->cRDN);
02317         ret = TRUE;
02318         for (i = 0; ret && i < info->cRDN; i++)
02319         {
02320             ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
02321              CRYPT_AsnEncodeNameValue, NULL, &size);
02322             if (ret)
02323                 bytesNeeded += size;
02324         }
02325         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
02326         bytesNeeded += 1 + lenBytes;
02327         if (ret)
02328         {
02329             if (!pbEncoded)
02330                 *pcbEncoded = bytesNeeded;
02331             else
02332             {
02333                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02334                  pbEncoded, pcbEncoded, bytesNeeded)))
02335                 {
02336                     BYTE *out;
02337 
02338                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02339                         pbEncoded = *(BYTE **)pbEncoded;
02340                     out = pbEncoded;
02341                     *out++ = ASN_SEQUENCEOF;
02342                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
02343                     out += lenBytes;
02344                     for (i = 0; ret && i < info->cRDN; i++)
02345                     {
02346                         size = bytesNeeded;
02347                         ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
02348                          &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
02349                         if (ret)
02350                         {
02351                             out += size;
02352                             bytesNeeded -= size;
02353                         }
02354                     }
02355                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02356                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
02357                 }
02358             }
02359         }
02360     }
02361     __EXCEPT_PAGE_FAULT
02362     {
02363         SetLastError(STATUS_ACCESS_VIOLATION);
02364         ret = FALSE;
02365     }
02366     __ENDTRY
02367     return ret;
02368 }
02369 
02370 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
02371  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02372  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02373 {
02374     BOOL val = *(const BOOL *)pvStructInfo, ret;
02375 
02376     TRACE("%d\n", val);
02377 
02378     if (!pbEncoded)
02379     {
02380         *pcbEncoded = 3;
02381         ret = TRUE;
02382     }
02383     else if (*pcbEncoded < 3)
02384     {
02385         *pcbEncoded = 3;
02386         SetLastError(ERROR_MORE_DATA);
02387         ret = FALSE;
02388     }
02389     else
02390     {
02391         *pcbEncoded = 3;
02392         *pbEncoded++ = ASN_BOOL;
02393         *pbEncoded++ = 1;
02394         *pbEncoded++ = val ? 0xff : 0;
02395         ret = TRUE;
02396     }
02397     TRACE("returning %d (%08x)\n", ret, GetLastError());
02398     return ret;
02399 }
02400 
02401 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
02402  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02403  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02404 {
02405     const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
02406     BOOL ret;
02407     DWORD dataLen;
02408     BYTE tag;
02409 
02410     ret = TRUE;
02411     switch (entry->dwAltNameChoice)
02412     {
02413     case CERT_ALT_NAME_RFC822_NAME:
02414     case CERT_ALT_NAME_DNS_NAME:
02415     case CERT_ALT_NAME_URL:
02416         tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
02417         if (entry->u.pwszURL)
02418         {
02419             DWORD i;
02420 
02421             /* Not + 1: don't encode the NULL-terminator */
02422             dataLen = lstrlenW(entry->u.pwszURL);
02423             for (i = 0; ret && i < dataLen; i++)
02424             {
02425                 if (entry->u.pwszURL[i] > 0x7f)
02426                 {
02427                     SetLastError(CRYPT_E_INVALID_IA5_STRING);
02428                     ret = FALSE;
02429                     *pcbEncoded = i;
02430                 }
02431             }
02432         }
02433         else
02434             dataLen = 0;
02435         break;
02436     case CERT_ALT_NAME_DIRECTORY_NAME:
02437         tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
02438         dataLen = entry->u.DirectoryName.cbData;
02439         break;
02440     case CERT_ALT_NAME_IP_ADDRESS:
02441         tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
02442         dataLen = entry->u.IPAddress.cbData;
02443         break;
02444     case CERT_ALT_NAME_REGISTERED_ID:
02445     {
02446         struct AsnEncodeTagSwappedItem swapped =
02447          { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
02448            CRYPT_AsnEncodeOid };
02449 
02450         return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
02451          pcbEncoded);
02452     }
02453     case CERT_ALT_NAME_OTHER_NAME:
02454         FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
02455         return FALSE;
02456     default:
02457         SetLastError(E_INVALIDARG);
02458         return FALSE;
02459     }
02460     if (ret)
02461     {
02462         DWORD bytesNeeded, lenBytes;
02463 
02464         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
02465         bytesNeeded = 1 + dataLen + lenBytes;
02466         if (!pbEncoded)
02467             *pcbEncoded = bytesNeeded;
02468         else if (*pcbEncoded < bytesNeeded)
02469         {
02470             SetLastError(ERROR_MORE_DATA);
02471             *pcbEncoded = bytesNeeded;
02472             ret = FALSE;
02473         }
02474         else
02475         {
02476             *pbEncoded++ = tag;
02477             CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
02478             pbEncoded += lenBytes;
02479             switch (entry->dwAltNameChoice)
02480             {
02481             case CERT_ALT_NAME_RFC822_NAME:
02482             case CERT_ALT_NAME_DNS_NAME:
02483             case CERT_ALT_NAME_URL:
02484             {
02485                 DWORD i;
02486 
02487                 for (i = 0; i < dataLen; i++)
02488                     *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
02489                 break;
02490             }
02491             case CERT_ALT_NAME_DIRECTORY_NAME:
02492                 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
02493                 break;
02494             case CERT_ALT_NAME_IP_ADDRESS:
02495                 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
02496                 break;
02497             }
02498             if (ret)
02499                 *pcbEncoded = bytesNeeded;
02500         }
02501     }
02502     TRACE("returning %d (%08x)\n", ret, GetLastError());
02503     return ret;
02504 }
02505 
02506 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
02507  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02508  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02509 {
02510     BOOL ret;
02511 
02512     __TRY
02513     {
02514         const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
02515         struct AsnEncodeSequenceItem items[3] = { { 0 } };
02516         struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
02517         struct AsnConstructedItem constructed = { 0 };
02518         DWORD cItem = 0, cSwapped = 0;
02519 
02520         if (info->KeyId.cbData)
02521         {
02522             swapped[cSwapped].tag = ASN_CONTEXT | 0;
02523             swapped[cSwapped].pvStructInfo = &info->KeyId;
02524             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
02525             items[cItem].pvStructInfo = &swapped[cSwapped];
02526             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
02527             cSwapped++;
02528             cItem++;
02529         }
02530         if (info->CertIssuer.cbData)
02531         {
02532             constructed.tag = 1;
02533             constructed.pvStructInfo = &info->CertIssuer;
02534             constructed.encodeFunc = CRYPT_CopyEncodedBlob;
02535             items[cItem].pvStructInfo = &constructed;
02536             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
02537             cItem++;
02538         }
02539         if (info->CertSerialNumber.cbData)
02540         {
02541             swapped[cSwapped].tag = ASN_CONTEXT | 2;
02542             swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
02543             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
02544             items[cItem].pvStructInfo = &swapped[cSwapped];
02545             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
02546             cSwapped++;
02547             cItem++;
02548         }
02549         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
02550          pEncodePara, pbEncoded, pcbEncoded);
02551     }
02552     __EXCEPT_PAGE_FAULT
02553     {
02554         SetLastError(STATUS_ACCESS_VIOLATION);
02555         ret = FALSE;
02556     }
02557     __ENDTRY
02558     return ret;
02559 }
02560 
02561 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
02562  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02563  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02564 {
02565     BOOL ret;
02566 
02567     __TRY
02568     {
02569         const CERT_ALT_NAME_INFO *info = pvStructInfo;
02570         DWORD bytesNeeded, dataLen, lenBytes, i;
02571 
02572         ret = TRUE;
02573         /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
02574          * can't encode an erroneous entry index if it's bigger than this.
02575          */
02576         for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
02577         {
02578             DWORD len;
02579 
02580             ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
02581              &info->rgAltEntry[i], 0, NULL, NULL, &len);
02582             if (ret)
02583                 dataLen += len;
02584             else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
02585             {
02586                 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
02587                  * the bad character, now set the index of the bad
02588                  * entry
02589                  */
02590                 *pcbEncoded = (BYTE)i <<
02591                  CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
02592             }
02593         }
02594         if (ret)
02595         {
02596             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
02597             bytesNeeded = 1 + lenBytes + dataLen;
02598             if (!pbEncoded)
02599             {
02600                 *pcbEncoded = bytesNeeded;
02601                 ret = TRUE;
02602             }
02603             else
02604             {
02605                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02606                  pbEncoded, pcbEncoded, bytesNeeded)))
02607                 {
02608                     BYTE *out;
02609 
02610                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02611                         pbEncoded = *(BYTE **)pbEncoded;
02612                     out = pbEncoded;
02613                     *out++ = ASN_SEQUENCEOF;
02614                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
02615                     out += lenBytes;
02616                     for (i = 0; ret && i < info->cAltEntry; i++)
02617                     {
02618                         DWORD len = dataLen;
02619 
02620                         ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
02621                          NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
02622                         if (ret)
02623                         {
02624                             out += len;
02625                             dataLen -= len;
02626                         }
02627                     }
02628                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02629                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
02630                 }
02631             }
02632         }
02633     }
02634     __EXCEPT_PAGE_FAULT
02635     {
02636         SetLastError(STATUS_ACCESS_VIOLATION);
02637         ret = FALSE;
02638     }
02639     __ENDTRY
02640     return ret;
02641 }
02642 
02643 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
02644  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02645  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02646 {
02647     BOOL ret;
02648 
02649     __TRY
02650     {
02651         const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
02652         struct AsnEncodeSequenceItem items[3] = { { 0 } };
02653         struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
02654         DWORD cItem = 0, cSwapped = 0;
02655 
02656         if (info->KeyId.cbData)
02657         {
02658             swapped[cSwapped].tag = ASN_CONTEXT | 0;
02659             swapped[cSwapped].pvStructInfo = &info->KeyId;
02660             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
02661             items[cItem].pvStructInfo = &swapped[cSwapped];
02662             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
02663             cSwapped++;
02664             cItem++;
02665         }
02666         if (info->AuthorityCertIssuer.cAltEntry)
02667         {
02668             swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
02669             swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
02670             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
02671             items[cItem].pvStructInfo = &swapped[cSwapped];
02672             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
02673             cSwapped++;
02674             cItem++;
02675         }
02676         if (info->AuthorityCertSerialNumber.cbData)
02677         {
02678             swapped[cSwapped].tag = ASN_CONTEXT | 2;
02679             swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
02680             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
02681             items[cItem].pvStructInfo = &swapped[cSwapped];
02682             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
02683             cSwapped++;
02684             cItem++;
02685         }
02686         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
02687          pEncodePara, pbEncoded, pcbEncoded);
02688     }
02689     __EXCEPT_PAGE_FAULT
02690     {
02691         SetLastError(STATUS_ACCESS_VIOLATION);
02692         ret = FALSE;
02693     }
02694     __ENDTRY
02695     return ret;
02696 }
02697 
02698 static BOOL CRYPT_AsnEncodeAccessDescription(
02699  const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
02700 {
02701     struct AsnEncodeSequenceItem items[] = {
02702      { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
02703      { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
02704     };
02705 
02706     if (!descr->pszAccessMethod)
02707     {
02708         SetLastError(E_INVALIDARG);
02709         return FALSE;
02710     }
02711     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
02712      sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
02713 }
02714 
02715 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
02716  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02717  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02718 {
02719     BOOL ret;
02720 
02721     __TRY
02722     {
02723         DWORD bytesNeeded, dataLen, lenBytes, i;
02724         const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
02725 
02726         ret = TRUE;
02727         for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
02728         {
02729             DWORD size;
02730 
02731             ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
02732              &size);
02733             if (ret)
02734                 dataLen += size;
02735         }
02736         if (ret)
02737         {
02738             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
02739             bytesNeeded = 1 + lenBytes + dataLen;
02740             if (!pbEncoded)
02741                 *pcbEncoded = bytesNeeded;
02742             else
02743             {
02744                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02745                  pbEncoded, pcbEncoded, bytesNeeded)))
02746                 {
02747                     BYTE *out;
02748 
02749                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02750                         pbEncoded = *(BYTE **)pbEncoded;
02751                     out = pbEncoded;
02752                     *out++ = ASN_SEQUENCEOF;
02753                     CRYPT_EncodeLen(dataLen, out, &lenBytes);
02754                     out += lenBytes;
02755                     for (i = 0; i < info->cAccDescr; i++)
02756                     {
02757                         DWORD size = dataLen;
02758 
02759                         ret = CRYPT_AsnEncodeAccessDescription(
02760                          &info->rgAccDescr[i], out, &size);
02761                         out += size;
02762                         dataLen -= size;
02763                     }
02764                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02765                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
02766                 }
02767             }
02768         }
02769     }
02770     __EXCEPT_PAGE_FAULT
02771     {
02772         SetLastError(STATUS_ACCESS_VIOLATION);
02773         ret = FALSE;
02774     }
02775     __ENDTRY
02776     return ret;
02777 }
02778 
02779 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
02780  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02781  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02782 {
02783     BOOL ret;
02784 
02785     __TRY
02786     {
02787         const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
02788         struct AsnEncodeSequenceItem items[3] = {
02789          { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
02790          { 0 }
02791         };
02792         DWORD cItem = 1;
02793 
02794         if (info->fPathLenConstraint)
02795         {
02796             items[cItem].pvStructInfo = &info->dwPathLenConstraint;
02797             items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
02798             cItem++;
02799         }
02800         if (info->cSubtreesConstraint)
02801         {
02802             items[cItem].pvStructInfo = &info->cSubtreesConstraint;
02803             items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
02804             cItem++;
02805         }
02806         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
02807          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02808     }
02809     __EXCEPT_PAGE_FAULT
02810     {
02811         SetLastError(STATUS_ACCESS_VIOLATION);
02812         ret = FALSE;
02813     }
02814     __ENDTRY
02815     return ret;
02816 }
02817 
02818 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
02819  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02820  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02821 {
02822     BOOL ret;
02823 
02824     __TRY
02825     {
02826         const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
02827         struct AsnEncodeSequenceItem items[2] = { { 0 } };
02828         DWORD cItem = 0;
02829 
02830         if (info->fCA)
02831         {
02832             items[cItem].pvStructInfo = &info->fCA;
02833             items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
02834             cItem++;
02835         }
02836         if (info->fPathLenConstraint)
02837         {
02838             items[cItem].pvStructInfo = &info->dwPathLenConstraint;
02839             items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
02840             cItem++;
02841         }
02842         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
02843          dwFlags, pEncodePara, pbEncoded, pcbEncoded);
02844     }
02845     __EXCEPT_PAGE_FAULT
02846     {
02847         SetLastError(STATUS_ACCESS_VIOLATION);
02848         ret = FALSE;
02849     }
02850     __ENDTRY
02851     return ret;
02852 }
02853 
02854 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
02855  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02856  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02857 {
02858     const CERT_POLICY_INFO *info = pvStructInfo;
02859     BOOL ret;
02860 
02861     if (!info->cPolicyQualifier)
02862     {
02863         *pcbEncoded = 0;
02864         ret = TRUE;
02865     }
02866     else
02867     {
02868         struct AsnEncodeSequenceItem items[2] = {
02869          { NULL, CRYPT_AsnEncodeOid, 0 },
02870          { NULL, CRYPT_CopyEncodedBlob, 0 },
02871         };
02872         DWORD bytesNeeded = 0, lenBytes, size, i;
02873 
02874         ret = TRUE;
02875         for (i = 0; ret && i < info->cPolicyQualifier; i++)
02876         {
02877             items[0].pvStructInfo =
02878              info->rgPolicyQualifier[i].pszPolicyQualifierId;
02879             items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
02880             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
02881              sizeof(items) / sizeof(items[0]),
02882              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
02883             if (ret)
02884                 bytesNeeded += size;
02885         }
02886         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
02887         bytesNeeded += 1 + lenBytes;
02888         if (ret)
02889         {
02890             if (!pbEncoded)
02891                 *pcbEncoded = bytesNeeded;
02892             else
02893             {
02894                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02895                  pbEncoded, pcbEncoded, bytesNeeded)))
02896                 {
02897                     BYTE *out;
02898 
02899                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02900                         pbEncoded = *(BYTE **)pbEncoded;
02901                     out = pbEncoded;
02902                     *out++ = ASN_SEQUENCEOF;
02903                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
02904                     out += lenBytes;
02905                     for (i = 0; ret && i < info->cPolicyQualifier; i++)
02906                     {
02907                         items[0].pvStructInfo =
02908                          info->rgPolicyQualifier[i].pszPolicyQualifierId;
02909                         items[1].pvStructInfo =
02910                          &info->rgPolicyQualifier[i].Qualifier;
02911                         size = bytesNeeded;
02912                         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
02913                          sizeof(items) / sizeof(items[0]),
02914                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
02915                         if (ret)
02916                         {
02917                             out += size;
02918                             bytesNeeded -= size;
02919                         }
02920                     }
02921                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
02922                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
02923                 }
02924             }
02925         }
02926     }
02927     return ret;
02928 }
02929 
02930 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
02931  const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
02932  DWORD *pcbEncoded)
02933 {
02934     struct AsnEncodeSequenceItem items[2] = {
02935      { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
02936      { info,                      CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
02937     };
02938     BOOL ret;
02939 
02940     if (!info->pszPolicyIdentifier)
02941     {
02942         SetLastError(E_INVALIDARG);
02943         return FALSE;
02944     }
02945     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
02946      sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
02947     return ret;
02948 }
02949 
02950 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
02951  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
02952  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
02953 {
02954     BOOL ret = FALSE;
02955 
02956     __TRY
02957     {
02958         const CERT_POLICIES_INFO *info = pvStructInfo;
02959         DWORD bytesNeeded = 0, lenBytes, size, i;
02960 
02961         ret = TRUE;
02962         for (i = 0; ret && i < info->cPolicyInfo; i++)
02963         {
02964             ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
02965              &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
02966              &size);
02967             if (ret)
02968                 bytesNeeded += size;
02969         }
02970         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
02971         bytesNeeded += 1 + lenBytes;
02972         if (ret)
02973         {
02974             if (!pbEncoded)
02975                 *pcbEncoded = bytesNeeded;
02976             else
02977             {
02978                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
02979                  pbEncoded, pcbEncoded, bytesNeeded)))
02980                 {
02981                     BYTE *out;
02982 
02983                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
02984                         pbEncoded = *(BYTE **)pbEncoded;
02985                     out = pbEncoded;
02986                     *out++ = ASN_SEQUENCEOF;
02987                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
02988                     out += lenBytes;
02989                     for (i = 0; ret && i < info->cPolicyInfo; i++)
02990                     {
02991                         size = bytesNeeded;
02992                         ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
02993                          &info->rgPolicyInfo[i],
02994                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
02995                         if (ret)
02996                         {
02997                             out += size;
02998                             bytesNeeded -= size;
02999                         }
03000                     }
03001                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
03002                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
03003                 }
03004             }
03005         }
03006     }
03007     __EXCEPT_PAGE_FAULT
03008     {
03009         SetLastError(STATUS_ACCESS_VIOLATION);
03010     }
03011     __ENDTRY
03012     return ret;
03013 }
03014 
03015 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
03016  const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
03017  DWORD *pcbEncoded)
03018 {
03019     struct AsnEncodeSequenceItem items[] = {
03020      { mapping->pszIssuerDomainPolicy,  CRYPT_AsnEncodeOid, 0 },
03021      { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
03022     };
03023 
03024     if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
03025     {
03026         SetLastError(E_INVALIDARG);
03027         return FALSE;
03028     }
03029     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
03030      sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
03031 }
03032 
03033 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
03034  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03035  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03036 {
03037     BOOL ret = FALSE;
03038 
03039     __TRY
03040     {
03041         const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
03042         DWORD bytesNeeded = 0, lenBytes, size, i;
03043 
03044         ret = TRUE;
03045         for (i = 0; ret && i < info->cPolicyMapping; i++)
03046         {
03047             ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
03048              &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
03049              NULL, &size);
03050             if (ret)
03051                 bytesNeeded += size;
03052         }
03053         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
03054         bytesNeeded += 1 + lenBytes;
03055         if (ret)
03056         {
03057             if (!pbEncoded)
03058                 *pcbEncoded = bytesNeeded;
03059             else
03060             {
03061                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
03062                  pbEncoded, pcbEncoded, bytesNeeded)))
03063                 {
03064                     BYTE *out;
03065 
03066                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03067                         pbEncoded = *(BYTE **)pbEncoded;
03068                     out = pbEncoded;
03069                     *out++ = ASN_SEQUENCEOF;
03070                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
03071                     out += lenBytes;
03072                     for (i = 0; ret && i < info->cPolicyMapping; i++)
03073                     {
03074                         size = bytesNeeded;
03075                         ret = CRYPT_AsnEncodeCertPolicyMapping(
03076                          dwCertEncodingType, &info->rgPolicyMapping[i],
03077                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
03078                         if (ret)
03079                         {
03080                             out += size;
03081                             bytesNeeded -= size;
03082                         }
03083                     }
03084                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
03085                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
03086                 }
03087             }
03088         }
03089     }
03090     __EXCEPT_PAGE_FAULT
03091     {
03092         SetLastError(STATUS_ACCESS_VIOLATION);
03093     }
03094     __ENDTRY
03095     return ret;
03096 }
03097 
03098 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
03099  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
03100  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
03101  DWORD *pcbEncoded)
03102 {
03103     BOOL ret = FALSE;
03104 
03105     __TRY
03106     {
03107         const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
03108         struct AsnEncodeSequenceItem items[2];
03109         struct AsnEncodeTagSwappedItem swapped[2];
03110         DWORD cItem = 0, cSwapped = 0;
03111 
03112         if (info->fRequireExplicitPolicy)
03113         {
03114             swapped[cSwapped].tag = ASN_CONTEXT | 0;
03115             swapped[cSwapped].pvStructInfo =
03116              &info->dwRequireExplicitPolicySkipCerts;
03117             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
03118             items[cItem].pvStructInfo = &swapped[cSwapped];
03119             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03120             cSwapped++;
03121             cItem++;
03122         }
03123         if (info->fInhibitPolicyMapping)
03124         {
03125             swapped[cSwapped].tag = ASN_CONTEXT | 1;
03126             swapped[cSwapped].pvStructInfo =
03127              &info->dwInhibitPolicyMappingSkipCerts;
03128             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
03129             items[cItem].pvStructInfo = &swapped[cSwapped];
03130             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03131             cSwapped++;
03132             cItem++;
03133         }
03134         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
03135          dwFlags, NULL, pbEncoded, pcbEncoded);
03136     }
03137     __EXCEPT_PAGE_FAULT
03138     {
03139         SetLastError(STATUS_ACCESS_VIOLATION);
03140     }
03141     __ENDTRY
03142     return ret;
03143 }
03144 
03145 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
03146  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03147  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03148 {
03149     BOOL ret;
03150 
03151     __TRY
03152     {
03153         const BLOBHEADER *hdr = pvStructInfo;
03154 
03155         if (hdr->bType != PUBLICKEYBLOB)
03156         {
03157             SetLastError(E_INVALIDARG);
03158             ret = FALSE;
03159         }
03160         else
03161         {
03162             const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
03163              ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
03164             CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
03165              (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
03166             struct AsnEncodeSequenceItem items[] = { 
03167              { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
03168              { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
03169             };
03170 
03171             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
03172              sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
03173              pcbEncoded);
03174         }
03175     }
03176     __EXCEPT_PAGE_FAULT
03177     {
03178         SetLastError(STATUS_ACCESS_VIOLATION);
03179         ret = FALSE;
03180     }
03181     __ENDTRY
03182     return ret;
03183 }
03184 
03185 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
03186  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03187  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03188 {
03189     BOOL ret;
03190 
03191     __TRY
03192     {
03193         const CRYPT_DATA_BLOB *blob = pvStructInfo;
03194         DWORD bytesNeeded, lenBytes;
03195 
03196         TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
03197          dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0);
03198 
03199         CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
03200         bytesNeeded = 1 + lenBytes + blob->cbData;
03201         if (!pbEncoded)
03202         {
03203             *pcbEncoded = bytesNeeded;
03204             ret = TRUE;
03205         }
03206         else
03207         {
03208             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
03209              pcbEncoded, bytesNeeded)))
03210             {
03211                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03212                     pbEncoded = *(BYTE **)pbEncoded;
03213                 *pbEncoded++ = ASN_OCTETSTRING;
03214                 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
03215                 pbEncoded += lenBytes;
03216                 if (blob->cbData)
03217                     memcpy(pbEncoded, blob->pbData, blob->cbData);
03218             }
03219         }
03220     }
03221     __EXCEPT_PAGE_FAULT
03222     {
03223         SetLastError(STATUS_ACCESS_VIOLATION);
03224         ret = FALSE;
03225     }
03226     __ENDTRY
03227     TRACE("returning %d (%08x)\n", ret, GetLastError());
03228     return ret;
03229 }
03230 
03231 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
03232  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03233  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03234 {
03235     BOOL ret;
03236 
03237     __TRY
03238     {
03239         const CRYPT_BIT_BLOB *blob = pvStructInfo;
03240         DWORD bytesNeeded, lenBytes, dataBytes;
03241         BYTE unusedBits;
03242 
03243         /* yep, MS allows cUnusedBits to be >= 8 */
03244         if (!blob->cUnusedBits)
03245         {
03246             dataBytes = blob->cbData;
03247             unusedBits = 0;
03248         }
03249         else if (blob->cbData * 8 > blob->cUnusedBits)
03250         {
03251             dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
03252             unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
03253              blob->cUnusedBits;
03254         }
03255         else
03256         {
03257             dataBytes = 0;
03258             unusedBits = 0;
03259         }
03260         CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
03261         bytesNeeded = 1 + lenBytes + dataBytes + 1;
03262         if (!pbEncoded)
03263         {
03264             *pcbEncoded = bytesNeeded;
03265             ret = TRUE;
03266         }
03267         else
03268         {
03269             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
03270              pcbEncoded, bytesNeeded)))
03271             {
03272                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03273                     pbEncoded = *(BYTE **)pbEncoded;
03274                 *pbEncoded++ = ASN_BITSTRING;
03275                 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
03276                 pbEncoded += lenBytes;
03277                 *pbEncoded++ = unusedBits;
03278                 if (dataBytes)
03279                 {
03280                     BYTE mask = 0xff << unusedBits;
03281 
03282                     if (dataBytes > 1)
03283                     {
03284                         memcpy(pbEncoded, blob->pbData, dataBytes - 1);
03285                         pbEncoded += dataBytes - 1;
03286                     }
03287                     *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
03288                 }
03289             }
03290         }
03291     }
03292     __EXCEPT_PAGE_FAULT
03293     {
03294         SetLastError(STATUS_ACCESS_VIOLATION);
03295         ret = FALSE;
03296     }
03297     __ENDTRY
03298     return ret;
03299 }
03300 
03301 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
03302  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03303  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03304 {
03305     BOOL ret;
03306 
03307     __TRY
03308     {
03309         const CRYPT_BIT_BLOB *blob = pvStructInfo;
03310         CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
03311 
03312         ret = TRUE;
03313         if (newBlob.cbData)
03314         {
03315             newBlob.pbData = CryptMemAlloc(newBlob.cbData);
03316             if (newBlob.pbData)
03317             {
03318                 DWORD i;
03319 
03320                 for (i = 0; i < newBlob.cbData; i++)
03321                     newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
03322             }
03323             else
03324                 ret = FALSE;
03325         }
03326         if (ret)
03327             ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
03328              &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
03329         CryptMemFree(newBlob.pbData);
03330     }
03331     __EXCEPT_PAGE_FAULT
03332     {
03333         SetLastError(STATUS_ACCESS_VIOLATION);
03334         ret = FALSE;
03335     }
03336     __ENDTRY
03337     return ret;
03338 }
03339 
03340 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
03341  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03342  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03343 {
03344     CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
03345 
03346     return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
03347      &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
03348 }
03349 
03350 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
03351  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03352  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03353 {
03354     BOOL ret;
03355 
03356     __TRY
03357     {
03358         DWORD significantBytes, lenBytes, bytesNeeded;
03359         BYTE padByte = 0;
03360         BOOL pad = FALSE;
03361         const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
03362 
03363         significantBytes = blob->cbData;
03364         if (significantBytes)
03365         {
03366             if (blob->pbData[significantBytes - 1] & 0x80)
03367             {
03368                 /* negative, lop off leading (little-endian) 0xffs */
03369                 for (; significantBytes > 0 &&
03370                  blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
03371                     ;
03372                 if (blob->pbData[significantBytes - 1] < 0x80)
03373                 {
03374                     padByte = 0xff;
03375                     pad = TRUE;
03376                 }
03377             }
03378             else
03379             {
03380                 /* positive, lop off leading (little-endian) zeroes */
03381                 for (; significantBytes > 0 &&
03382                  !blob->pbData[significantBytes - 1]; significantBytes--)
03383                     ;
03384                 if (significantBytes == 0)
03385                     significantBytes = 1;
03386                 if (blob->pbData[significantBytes - 1] > 0x7f)
03387                 {
03388                     padByte = 0;
03389                     pad = TRUE;
03390                 }
03391             }
03392         }
03393         if (pad)
03394             CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
03395         else
03396             CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
03397         bytesNeeded = 1 + lenBytes + significantBytes;
03398         if (pad)
03399             bytesNeeded++;
03400         if (!pbEncoded)
03401         {
03402             *pcbEncoded = bytesNeeded;
03403             ret = TRUE;
03404         }
03405         else
03406         {
03407             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
03408              pcbEncoded, bytesNeeded)))
03409             {
03410                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03411                     pbEncoded = *(BYTE **)pbEncoded;
03412                 *pbEncoded++ = ASN_INTEGER;
03413                 if (pad)
03414                 {
03415                     CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
03416                     pbEncoded += lenBytes;
03417                     *pbEncoded++ = padByte;
03418                 }
03419                 else
03420                 {
03421                     CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
03422                     pbEncoded += lenBytes;
03423                 }
03424                 for (; significantBytes > 0; significantBytes--)
03425                     *(pbEncoded++) = blob->pbData[significantBytes - 1];
03426             }
03427         }
03428     }
03429     __EXCEPT_PAGE_FAULT
03430     {
03431         SetLastError(STATUS_ACCESS_VIOLATION);
03432         ret = FALSE;
03433     }
03434     __ENDTRY
03435     return ret;
03436 }
03437 
03438 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
03439  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03440  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03441 {
03442     BOOL ret;
03443 
03444     __TRY
03445     {
03446         DWORD significantBytes, lenBytes, bytesNeeded;
03447         BOOL pad = FALSE;
03448         const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
03449 
03450         significantBytes = blob->cbData;
03451         if (significantBytes)
03452         {
03453             /* positive, lop off leading (little-endian) zeroes */
03454             for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
03455              significantBytes--)
03456                 ;
03457             if (significantBytes == 0)
03458                 significantBytes = 1;
03459             if (blob->pbData[significantBytes - 1] > 0x7f)
03460                 pad = TRUE;
03461         }
03462         if (pad)
03463             CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
03464         else
03465             CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
03466         bytesNeeded = 1 + lenBytes + significantBytes;
03467         if (pad)
03468             bytesNeeded++;
03469         if (!pbEncoded)
03470         {
03471             *pcbEncoded = bytesNeeded;
03472             ret = TRUE;
03473         }
03474         else
03475         {
03476             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
03477              pcbEncoded, bytesNeeded)))
03478             {
03479                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03480                     pbEncoded = *(BYTE **)pbEncoded;
03481                 *pbEncoded++ = ASN_INTEGER;
03482                 if (pad)
03483                 {
03484                     CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
03485                     pbEncoded += lenBytes;
03486                     *pbEncoded++ = 0;
03487                 }
03488                 else
03489                 {
03490                     CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
03491                     pbEncoded += lenBytes;
03492                 }
03493                 for (; significantBytes > 0; significantBytes--)
03494                     *(pbEncoded++) = blob->pbData[significantBytes - 1];
03495             }
03496         }
03497     }
03498     __EXCEPT_PAGE_FAULT
03499     {
03500         SetLastError(STATUS_ACCESS_VIOLATION);
03501         ret = FALSE;
03502     }
03503     __ENDTRY
03504     return ret;
03505 }
03506 
03507 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
03508  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03509  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03510 {
03511     CRYPT_INTEGER_BLOB blob;
03512     BOOL ret;
03513 
03514     /* Encode as an unsigned integer, then change the tag to enumerated */
03515     blob.cbData = sizeof(DWORD);
03516     blob.pbData = (BYTE *)pvStructInfo;
03517     ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
03518      X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
03519     if (ret && pbEncoded)
03520     {
03521         if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03522             pbEncoded = *(BYTE **)pbEncoded;
03523         pbEncoded[0] = ASN_ENUMERATED;
03524     }
03525     return ret;
03526 }
03527 
03528 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
03529  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03530  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03531 {
03532     BOOL ret;
03533 
03534     __TRY
03535     {
03536         SYSTEMTIME sysTime;
03537         /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0.  I use a
03538          * temporary buffer because the output buffer is not NULL-terminated.
03539          */
03540         char buf[16];
03541         static const DWORD bytesNeeded = sizeof(buf) - 1;
03542 
03543         if (!pbEncoded)
03544         {
03545             *pcbEncoded = bytesNeeded;
03546             ret = TRUE;
03547         }
03548         else
03549         {
03550             /* Sanity check the year, this is a two-digit year format */
03551             ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
03552             if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
03553             {
03554                 SetLastError(CRYPT_E_BAD_ENCODE);
03555                 ret = FALSE;
03556             }
03557             if (ret)
03558             {
03559                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
03560                  pbEncoded, pcbEncoded, bytesNeeded)))
03561                 {
03562                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03563                         pbEncoded = *(BYTE **)pbEncoded;
03564                     buf[0] = ASN_UTCTIME;
03565                     buf[1] = bytesNeeded - 2;
03566                     snprintf(buf + 2, sizeof(buf) - 2,
03567                      "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
03568                      sysTime.wYear - 2000 : sysTime.wYear - 1900,
03569                      sysTime.wMonth, sysTime.wDay, sysTime.wHour,
03570                      sysTime.wMinute, sysTime.wSecond);
03571                     memcpy(pbEncoded, buf, bytesNeeded);
03572                 }
03573             }
03574         }
03575     }
03576     __EXCEPT_PAGE_FAULT
03577     {
03578         SetLastError(STATUS_ACCESS_VIOLATION);
03579         ret = FALSE;
03580     }
03581     __ENDTRY
03582     return ret;
03583 }
03584 
03585 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
03586  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03587  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03588 {
03589     BOOL ret;
03590 
03591     __TRY
03592     {
03593         SYSTEMTIME sysTime;
03594         /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0.  I use a
03595          * temporary buffer because the output buffer is not NULL-terminated.
03596          */
03597         char buf[18];
03598         static const DWORD bytesNeeded = sizeof(buf) - 1;
03599 
03600         if (!pbEncoded)
03601         {
03602             *pcbEncoded = bytesNeeded;
03603             ret = TRUE;
03604         }
03605         else
03606         {
03607             ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
03608             if (ret)
03609                 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
03610                  pcbEncoded, bytesNeeded);
03611             if (ret)
03612             {
03613                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03614                     pbEncoded = *(BYTE **)pbEncoded;
03615                 buf[0] = ASN_GENERALTIME;
03616                 buf[1] = bytesNeeded - 2;
03617                 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
03618                  sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
03619                  sysTime.wMinute, sysTime.wSecond);
03620                 memcpy(pbEncoded, buf, bytesNeeded);
03621             }
03622         }
03623     }
03624     __EXCEPT_PAGE_FAULT
03625     {
03626         SetLastError(STATUS_ACCESS_VIOLATION);
03627         ret = FALSE;
03628     }
03629     __ENDTRY
03630     return ret;
03631 }
03632 
03633 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
03634  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03635  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03636 {
03637     BOOL ret;
03638 
03639     __TRY
03640     {
03641         SYSTEMTIME sysTime;
03642 
03643         /* Check the year, if it's in the UTCTime range call that encode func */
03644         if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
03645             return FALSE;
03646         if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
03647             ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
03648              pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
03649         else
03650             ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
03651              lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
03652              pcbEncoded);
03653     }
03654     __EXCEPT_PAGE_FAULT
03655     {
03656         SetLastError(STATUS_ACCESS_VIOLATION);
03657         ret = FALSE;
03658     }
03659     __ENDTRY
03660     return ret;
03661 }
03662 
03663 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
03664  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03665  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03666 {
03667     BOOL ret;
03668 
03669     __TRY
03670     {
03671         DWORD bytesNeeded, dataLen, lenBytes, i;
03672         const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
03673 
03674         for (i = 0, dataLen = 0; i < seq->cValue; i++)
03675             dataLen += seq->rgValue[i].cbData;
03676         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
03677         bytesNeeded = 1 + lenBytes + dataLen;
03678         if (!pbEncoded)
03679         {
03680             *pcbEncoded = bytesNeeded;
03681             ret = TRUE;
03682         }
03683         else
03684         {
03685             if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
03686              pcbEncoded, bytesNeeded)))
03687             {
03688                 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03689                     pbEncoded = *(BYTE **)pbEncoded;
03690                 *pbEncoded++ = ASN_SEQUENCEOF;
03691                 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
03692                 pbEncoded += lenBytes;
03693                 for (i = 0; i < seq->cValue; i++)
03694                 {
03695                     memcpy(pbEncoded, seq->rgValue[i].pbData,
03696                      seq->rgValue[i].cbData);
03697                     pbEncoded += seq->rgValue[i].cbData;
03698                 }
03699             }
03700         }
03701     }
03702     __EXCEPT_PAGE_FAULT
03703     {
03704         SetLastError(STATUS_ACCESS_VIOLATION);
03705         ret = FALSE;
03706     }
03707     __ENDTRY
03708     return ret;
03709 }
03710 
03711 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
03712  BYTE *pbEncoded, DWORD *pcbEncoded)
03713 {
03714     BOOL ret = TRUE;
03715     struct AsnEncodeSequenceItem items[3] = { { 0 } };
03716     struct AsnConstructedItem constructed = { 0 };
03717     struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
03718     DWORD cItem = 0, cSwapped = 0;
03719 
03720     switch (distPoint->DistPointName.dwDistPointNameChoice)
03721     {
03722     case CRL_DIST_POINT_NO_NAME:
03723         /* do nothing */
03724         break;
03725     case CRL_DIST_POINT_FULL_NAME:
03726         swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
03727         swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
03728         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
03729         constructed.tag = 0;
03730         constructed.pvStructInfo = &swapped[cSwapped];
03731         constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
03732         items[cItem].pvStructInfo = &constructed;
03733         items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
03734         cSwapped++;
03735         cItem++;
03736         break;
03737     case CRL_DIST_POINT_ISSUER_RDN_NAME:
03738         FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
03739         ret = FALSE;
03740         break;
03741     default:
03742         ret = FALSE;
03743     }
03744     if (ret && distPoint->ReasonFlags.cbData)
03745     {
03746         swapped[cSwapped].tag = ASN_CONTEXT | 1;
03747         swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
03748         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
03749         items[cItem].pvStructInfo = &swapped[cSwapped];
03750         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03751         cSwapped++;
03752         cItem++;
03753     }
03754     if (ret && distPoint->CRLIssuer.cAltEntry)
03755     {
03756         swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
03757         swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
03758         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
03759         items[cItem].pvStructInfo = &swapped[cSwapped];
03760         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03761         cSwapped++;
03762         cItem++;
03763     }
03764     if (ret)
03765         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
03766          pbEncoded, pcbEncoded);
03767     return ret;
03768 }
03769 
03770 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
03771  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03772  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03773 {
03774     BOOL ret;
03775 
03776     __TRY
03777     {
03778         const CRL_DIST_POINTS_INFO *info = pvStructInfo;
03779 
03780         if (!info->cDistPoint)
03781         {
03782             SetLastError(E_INVALIDARG);
03783             ret = FALSE;
03784         }
03785         else
03786         {
03787             DWORD bytesNeeded, dataLen, lenBytes, i;
03788 
03789             ret = TRUE;
03790             for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
03791             {
03792                 DWORD len;
03793 
03794                 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
03795                  &len);
03796                 if (ret)
03797                     dataLen += len;
03798                 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
03799                 {
03800                     /* Have to propagate index of failing character */
03801                     *pcbEncoded = len;
03802                 }
03803             }
03804             if (ret)
03805             {
03806                 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
03807                 bytesNeeded = 1 + lenBytes + dataLen;
03808                 if (!pbEncoded)
03809                 {
03810                     *pcbEncoded = bytesNeeded;
03811                     ret = TRUE;
03812                 }
03813                 else
03814                 {
03815                     if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
03816                      pbEncoded, pcbEncoded, bytesNeeded)))
03817                     {
03818                         BYTE *out;
03819 
03820                         if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03821                             pbEncoded = *(BYTE **)pbEncoded;
03822                         out = pbEncoded;
03823                         *out++ = ASN_SEQUENCEOF;
03824                         CRYPT_EncodeLen(dataLen, out, &lenBytes);
03825                         out += lenBytes;
03826                         for (i = 0; ret && i < info->cDistPoint; i++)
03827                         {
03828                             DWORD len = dataLen;
03829 
03830                             ret = CRYPT_AsnEncodeDistPoint(
03831                              &info->rgDistPoint[i], out, &len);
03832                             if (ret)
03833                             {
03834                                 out += len;
03835                                 dataLen -= len;
03836                             }
03837                         }
03838                         if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
03839                             CRYPT_FreeSpace(pEncodePara, pbEncoded);
03840                     }
03841                 }
03842             }
03843         }
03844     }
03845     __EXCEPT_PAGE_FAULT
03846     {
03847         SetLastError(STATUS_ACCESS_VIOLATION);
03848         ret = FALSE;
03849     }
03850     __ENDTRY
03851     return ret;
03852 }
03853 
03854 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
03855  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03856  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03857 {
03858     BOOL ret;
03859 
03860     __TRY
03861     {
03862         const CERT_ENHKEY_USAGE *usage = pvStructInfo;
03863         DWORD bytesNeeded = 0, lenBytes, size, i;
03864 
03865         ret = TRUE;
03866         for (i = 0; ret && i < usage->cUsageIdentifier; i++)
03867         {
03868             ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
03869              usage->rgpszUsageIdentifier[i],
03870              dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
03871             if (ret)
03872                 bytesNeeded += size;
03873         }
03874         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
03875         bytesNeeded += 1 + lenBytes;
03876         if (ret)
03877         {
03878             if (!pbEncoded)
03879                 *pcbEncoded = bytesNeeded;
03880             else
03881             {
03882                 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
03883                  pbEncoded, pcbEncoded, bytesNeeded)))
03884                 {
03885                     BYTE *out;
03886 
03887                     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
03888                         pbEncoded = *(BYTE **)pbEncoded;
03889                     out = pbEncoded;
03890                     *out++ = ASN_SEQUENCEOF;
03891                     CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
03892                     out += lenBytes;
03893                     for (i = 0; ret && i < usage->cUsageIdentifier; i++)
03894                     {
03895                         size = bytesNeeded;
03896                         ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
03897                          usage->rgpszUsageIdentifier[i],
03898                          dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
03899                         if (ret)
03900                         {
03901                             out += size;
03902                             bytesNeeded -= size;
03903                         }
03904                     }
03905                     if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
03906                         CRYPT_FreeSpace(pEncodePara, pbEncoded);
03907                 }
03908             }
03909         }
03910     }
03911     __EXCEPT_PAGE_FAULT
03912     {
03913         SetLastError(STATUS_ACCESS_VIOLATION);
03914         ret = FALSE;
03915     }
03916     __ENDTRY
03917     return ret;
03918 }
03919 
03920 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
03921  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
03922  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
03923 {
03924     BOOL ret;
03925 
03926     __TRY
03927     {
03928         const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
03929         struct AsnEncodeSequenceItem items[6] = { { 0 } };
03930         struct AsnConstructedItem constructed = { 0 };
03931         struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
03932         DWORD cItem = 0, cSwapped = 0;
03933 
03934         ret = TRUE;
03935         switch (point->DistPointName.dwDistPointNameChoice)
03936         {
03937         case CRL_DIST_POINT_NO_NAME:
03938             /* do nothing */
03939             break;
03940         case CRL_DIST_POINT_FULL_NAME:
03941             swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
03942             swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
03943             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
03944             constructed.tag = 0;
03945             constructed.pvStructInfo = &swapped[cSwapped];
03946             constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
03947             items[cItem].pvStructInfo = &constructed;
03948             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
03949             cSwapped++;
03950             cItem++;
03951             break;
03952         default:
03953             SetLastError(E_INVALIDARG);
03954             ret = FALSE;
03955         }
03956         if (ret && point->fOnlyContainsUserCerts)
03957         {
03958             swapped[cSwapped].tag = ASN_CONTEXT | 1;
03959             swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
03960             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
03961             items[cItem].pvStructInfo = &swapped[cSwapped];
03962             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03963             cSwapped++;
03964             cItem++;
03965         }
03966         if (ret && point->fOnlyContainsCACerts)
03967         {
03968             swapped[cSwapped].tag = ASN_CONTEXT | 2;
03969             swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
03970             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
03971             items[cItem].pvStructInfo = &swapped[cSwapped];
03972             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03973             cSwapped++;
03974             cItem++;
03975         }
03976         if (ret && point->OnlySomeReasonFlags.cbData)
03977         {
03978             swapped[cSwapped].tag = ASN_CONTEXT | 3;
03979             swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
03980             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
03981             items[cItem].pvStructInfo = &swapped[cSwapped];
03982             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03983             cSwapped++;
03984             cItem++;
03985         }
03986         if (ret && point->fIndirectCRL)
03987         {
03988             swapped[cSwapped].tag = ASN_CONTEXT | 4;
03989             swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
03990             swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
03991             items[cItem].pvStructInfo = &swapped[cSwapped];
03992             items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
03993             cSwapped++;
03994             cItem++;
03995         }
03996         if (ret)
03997             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
03998              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
03999     }
04000     __EXCEPT_PAGE_FAULT
04001     {
04002         SetLastError(STATUS_ACCESS_VIOLATION);
04003         ret = FALSE;
04004     }
04005     __ENDTRY
04006     return ret;
04007 }
04008 
04009 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
04010  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
04011  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
04012 {
04013     BOOL ret;
04014     const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
04015     struct AsnEncodeSequenceItem items[3] = {
04016      { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
04017      { 0 }
04018     };
04019     struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
04020     DWORD cItem = 1, cSwapped = 0;
04021 
04022     if (subtree->dwMinimum)
04023     {
04024         swapped[cSwapped].tag = ASN_CONTEXT | 0;
04025         swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
04026         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
04027         items[cItem].pvStructInfo = &swapped[cSwapped];
04028         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04029         cSwapped++;
04030         cItem++;
04031     }
04032     if (subtree->fMaximum)
04033     {
04034         swapped[cSwapped].tag = ASN_CONTEXT | 1;
04035         swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
04036         swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
04037         items[cItem].pvStructInfo = &swapped[cSwapped];
04038         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04039         cSwapped++;
04040         cItem++;
04041     }
04042     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
04043      pEncodePara, pbEncoded, pcbEncoded);
04044     return ret;
04045 }
04046 
04047 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
04048  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
04049  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
04050 {
04051     BOOL ret = FALSE;
04052     CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
04053 
04054     TRACE("%p\n", pvStructInfo);
04055 
04056     __TRY
04057     {
04058         const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
04059         struct AsnEncodeSequenceItem items[2] = { { 0 } };
04060         struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
04061         DWORD i, cItem = 0, cSwapped = 0;
04062 
04063         ret = TRUE;
04064         if (constraints->cPermittedSubtree)
04065         {
04066             permitted.rgBlob = CryptMemAlloc(
04067              constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
04068             if (permitted.rgBlob)
04069             {
04070                 permitted.cBlob = constraints->cPermittedSubtree;
04071                 memset(permitted.rgBlob, 0,
04072                  permitted.cBlob * sizeof(CRYPT_DER_BLOB));
04073                 for (i = 0; ret && i < permitted.cBlob; i++)
04074                     ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
04075                      NULL, &constraints->rgPermittedSubtree[i],
04076                      CRYPT_ENCODE_ALLOC_FLAG, NULL,
04077                      (BYTE *)&permitted.rgBlob[i].pbData,
04078                      &permitted.rgBlob[i].cbData);
04079                 if (ret)
04080                 {
04081                     swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
04082                     swapped[cSwapped].pvStructInfo = &permitted;
04083                     swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
04084                     items[cItem].pvStructInfo = &swapped[cSwapped];
04085                     items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04086                     cSwapped++;
04087                     cItem++;
04088                 }
04089             }
04090             else
04091                 ret = FALSE;
04092         }
04093         if (constraints->cExcludedSubtree)
04094         {
04095             excluded.rgBlob = CryptMemAlloc(
04096              constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
04097             if (excluded.rgBlob)
04098             {
04099                 excluded.cBlob = constraints->cExcludedSubtree;
04100                 memset(excluded.rgBlob, 0,
04101                  excluded.cBlob * sizeof(CRYPT_DER_BLOB));
04102                 for (i = 0; ret && i < excluded.cBlob; i++)
04103                     ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
04104                      NULL, &constraints->rgExcludedSubtree[i],
04105                      CRYPT_ENCODE_ALLOC_FLAG, NULL,
04106                      (BYTE *)&excluded.rgBlob[i].pbData,
04107                      &excluded.rgBlob[i].cbData);
04108                 if (ret)
04109                 {
04110                     swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
04111                     swapped[cSwapped].pvStructInfo = &excluded;
04112                     swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
04113                     items[cItem].pvStructInfo = &swapped[cSwapped];
04114                     items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04115                     cSwapped++;
04116                     cItem++;
04117                 }
04118             }
04119             else
04120                 ret = FALSE;
04121         }
04122         if (ret)
04123             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
04124              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
04125         for (i = 0; i < permitted.cBlob; i++)
04126             LocalFree(permitted.rgBlob[i].pbData);
04127         for (i = 0; i < excluded.cBlob; i++)
04128             LocalFree(excluded.rgBlob[i].pbData);
04129     }
04130     __EXCEPT_PAGE_FAULT
04131     {
04132         SetLastError(STATUS_ACCESS_VIOLATION);
04133     }
04134     __ENDTRY
04135     CryptMemFree(permitted.rgBlob);
04136     CryptMemFree(excluded.rgBlob);
04137     TRACE("returning %d\n", ret);
04138     return ret;
04139 }
04140 
04141 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
04142  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
04143  DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
04144  DWORD *pcbEncoded)
04145 {
04146     BOOL ret;
04147     const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
04148     struct AsnEncodeSequenceItem items[] = {
04149      { &issuerSerial->Issuer,       CRYPT_CopyEncodedBlob, 0 },
04150      { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
04151     };
04152 
04153     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
04154      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
04155      pcbEncoded);
04156     return ret;
04157 }
04158 
04159 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
04160  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
04161  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
04162 {
04163     BOOL ret = FALSE;
04164 
04165     if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
04166     {
04167         SetLastError(E_INVALIDARG);
04168         return FALSE;
04169     }
04170 
04171     __TRY
04172     {
04173         const CMSG_SIGNER_INFO *info = pvStructInfo;
04174 
04175         if (!info->Issuer.cbData)
04176             SetLastError(E_INVALIDARG);
04177         else
04178         {
04179             struct AsnEncodeSequenceItem items[7] = {
04180              { &info->dwVersion,     CRYPT_AsnEncodeInt, 0 },
04181              { &info->Issuer,        CRYPT_AsnEncodeIssuerSerialNumber, 0 },
04182              { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
04183                0 },
04184             };
04185             struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
04186             DWORD cItem = 3, cSwapped = 0;
04187 
04188             if (info->AuthAttrs.cAttr)
04189             {
04190                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
04191                 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
04192                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
04193                 items[cItem].pvStructInfo = &swapped[cSwapped];
04194                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04195                 cSwapped++;
04196                 cItem++;
04197             }
04198             items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
04199             items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
04200             cItem++;
04201             items[cItem].pvStructInfo = &info->EncryptedHash;
04202             items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
04203             cItem++;
04204             if (info->UnauthAttrs.cAttr)
04205             {
04206                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
04207                 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
04208                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
04209                 items[cItem].pvStructInfo = &swapped[cSwapped];
04210                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04211                 cSwapped++;
04212                 cItem++;
04213             }
04214             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
04215              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
04216         }
04217     }
04218     __EXCEPT_PAGE_FAULT
04219     {
04220         SetLastError(STATUS_ACCESS_VIOLATION);
04221     }
04222     __ENDTRY
04223     return ret;
04224 }
04225 
04226 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
04227  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
04228  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
04229 {
04230     BOOL ret = FALSE;
04231 
04232     if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
04233     {
04234         SetLastError(E_INVALIDARG);
04235         return FALSE;
04236     }
04237 
04238     __TRY
04239     {
04240         const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
04241 
04242         if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
04243          info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
04244             SetLastError(E_INVALIDARG);
04245         else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
04246          !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
04247             SetLastError(E_INVALIDARG);
04248         else
04249         {
04250             struct AsnEncodeSequenceItem items[7] = {
04251              { &info->dwVersion,     CRYPT_AsnEncodeInt, 0 },
04252             };
04253             struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
04254             DWORD cItem = 1, cSwapped = 0;
04255 
04256             if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
04257             {
04258                 items[cItem].pvStructInfo =
04259                  &info->SignerId.u.IssuerSerialNumber.Issuer;
04260                 items[cItem].encodeFunc =
04261                  CRYPT_AsnEncodeIssuerSerialNumber;
04262                 cItem++;
04263             }
04264             else
04265             {
04266                 swapped[cSwapped].tag = ASN_CONTEXT | 0;
04267                 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
04268                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
04269                 items[cItem].pvStructInfo = &swapped[cSwapped];
04270                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04271                 cSwapped++;
04272                 cItem++;
04273             }
04274             items[cItem].pvStructInfo = &info->HashAlgorithm;
04275             items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
04276             cItem++;
04277             if (info->AuthAttrs.cAttr)
04278             {
04279                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
04280                 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
04281                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
04282                 items[cItem].pvStructInfo = &swapped[cSwapped];
04283                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04284                 cSwapped++;
04285                 cItem++;
04286             }
04287             items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
04288             items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
04289             cItem++;
04290             items[cItem].pvStructInfo = &info->EncryptedHash;
04291             items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
04292             cItem++;
04293             if (info->UnauthAttrs.cAttr)
04294             {
04295                 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
04296                 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
04297                 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
04298                 items[cItem].pvStructInfo = &swapped[cSwapped];
04299                 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04300                 cSwapped++;
04301                 cItem++;
04302             }
04303             ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
04304              dwFlags, pEncodePara, pbEncoded, pcbEncoded);
04305         }
04306     }
04307     __EXCEPT_PAGE_FAULT
04308     {
04309         SetLastError(STATUS_ACCESS_VIOLATION);
04310     }
04311     __ENDTRY
04312     return ret;
04313 }
04314 
04315 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
04316  DWORD *pcbData)
04317 {
04318     struct AsnEncodeSequenceItem items[7] = {
04319      { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
04320     };
04321     struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
04322     struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
04323     struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
04324     DWORD cItem = 1, cSwapped = 0;
04325     BOOL ret = TRUE;
04326 
04327     if (signedInfo->cSignerInfo)
04328     {
04329         digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
04330         digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
04331         digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
04332         digestAlgorithmsSet.itemOffset =
04333          offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
04334         digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
04335         items[cItem].pvStructInfo = &digestAlgorithmsSet;
04336         items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
04337         cItem++;
04338     }
04339     items[cItem].pvStructInfo = &signedInfo->content;
04340     items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
04341     cItem++;
04342     if (signedInfo->cCertEncoded)
04343     {
04344         certSet.cItems = signedInfo->cCertEncoded;
04345         certSet.items = signedInfo->rgCertEncoded;
04346         certSet.itemSize = sizeof(CERT_BLOB);
04347         certSet.itemOffset = 0;
04348         certSet.encode = CRYPT_CopyEncodedBlob;
04349         swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
04350         swapped[cSwapped].pvStructInfo = &certSet;
04351         swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
04352         items[cItem].pvStructInfo = &swapped[cSwapped];
04353         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04354         cSwapped++;
04355         cItem++;
04356     }
04357     if (signedInfo->cCrlEncoded)
04358     {
04359         crlSet.cItems = signedInfo->cCrlEncoded;
04360         crlSet.items = signedInfo->rgCrlEncoded;
04361         crlSet.itemSize = sizeof(CRL_BLOB);
04362         crlSet.itemOffset = 0;
04363         crlSet.encode = CRYPT_CopyEncodedBlob;
04364         swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
04365         swapped[cSwapped].pvStructInfo = &crlSet;
04366         swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
04367         items[cItem].pvStructInfo = &swapped[cSwapped];
04368         items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
04369         cSwapped++;
04370         cItem++;
04371     }
04372     if (ret && signedInfo->cSignerInfo)
04373     {
04374         signerSet.cItems = signedInfo->cSignerInfo;
04375         signerSet.items = signedInfo->rgSignerInfo;
04376         signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
04377         signerSet.itemOffset = 0;
04378         signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
04379         items[cItem].pvStructInfo = &signerSet;
04380         items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
04381         cItem++;
04382     }
04383     if (ret)
04384         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
04385          items, cItem, 0, NULL, pvData, pcbData);
04386 
04387     return ret;
04388 }
04389 
04390 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
04391  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
04392  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
04393 {
04394     const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
04395     struct AsnEncodeSequenceItem items[] = {
04396      { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
04397      { &info->RecipientId.u.IssuerSerialNumber,
04398        CRYPT_AsnEncodeIssuerSerialNumber, 0 },
04399      { &info->KeyEncryptionAlgorithm,
04400        CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
04401      { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
04402     };
04403 
04404     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
04405      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
04406      pcbEncoded);
04407 }
04408 
04409 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
04410  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
04411  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
04412 {
04413     const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
04414     struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
04415      &info->encryptedContent, CRYPT_AsnEncodeOctets };
04416     struct AsnEncodeSequenceItem items[] = {
04417      { info->contentType, CRYPT_AsnEncodeOid, 0 },
04418      { &info->contentEncryptionAlgorithm,
04419        CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
04420      { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
04421     };
04422 
04423     return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
04424      sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
04425      pcbEncoded);
04426 }
04427 
04428 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
04429  void *pvData, DWORD *pcbData)
04430 {
04431     struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
04432      envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
04433      CRYPT_AsnEncodeRecipientInfo };
04434     struct AsnEncodeSequenceItem items[] = {
04435      { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
04436      { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
04437      { &envelopedData->encryptedContentInfo,
04438        CRYPT_AsnEncodeEncryptedContentInfo, 0 },
04439     };
04440 
04441     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
04442      sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
04443 }
04444 
04445 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
04446  LPCSTR lpszStructType)
04447 {
04448     CryptEncodeObjectExFunc encodeFunc = NULL;
04449 
04450     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
04451      && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
04452     {
04453         SetLastError(ERROR_FILE_NOT_FOUND);
04454         return NULL;
04455     }
04456 
04457     if (IS_INTOID(lpszStructType))
04458     {
04459         switch (LOWORD(lpszStructType))
04460         {
04461         case LOWORD(X509_CERT):
04462             encodeFunc = CRYPT_AsnEncodeCert;
04463             break;
04464         case LOWORD(X509_CERT_TO_BE_SIGNED):
04465             encodeFunc = CRYPT_AsnEncodeCertInfo;
04466             break;
04467         case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
04468             encodeFunc = CRYPT_AsnEncodeCRLInfo;
04469             break;
04470         case LOWORD(X509_EXTENSIONS):
04471             encodeFunc = CRYPT_AsnEncodeExtensions;
04472             break;
04473         case LOWORD(X509_NAME_VALUE):
04474             encodeFunc = CRYPT_AsnEncodeNameValue;
04475             break;
04476         case LOWORD(X509_NAME):
04477             encodeFunc = CRYPT_AsnEncodeName;
04478             break;
04479         case LOWORD(X509_PUBLIC_KEY_INFO):
04480             encodeFunc = CRYPT_AsnEncodePubKeyInfo;
04481             break;
04482         case LOWORD(X509_AUTHORITY_KEY_ID):
04483             encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
04484             break;
04485         case LOWORD(X509_ALTERNATE_NAME):
04486             encodeFunc = CRYPT_AsnEncodeAltName;
04487             break;
04488         case LOWORD(X509_BASIC_CONSTRAINTS):
04489             encodeFunc = CRYPT_AsnEncodeBasicConstraints;
04490             break;
04491         case LOWORD(X509_BASIC_CONSTRAINTS2):
04492             encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
04493             break;
04494         case LOWORD(X509_CERT_POLICIES):
04495             encodeFunc = CRYPT_AsnEncodeCertPolicies;
04496             break;
04497         case LOWORD(RSA_CSP_PUBLICKEYBLOB):
04498             encodeFunc = CRYPT_AsnEncodeRsaPubKey;
04499             break;
04500         case LOWORD(X509_UNICODE_NAME):
04501             encodeFunc = CRYPT_AsnEncodeUnicodeName;
04502             break;
04503         case LOWORD(PKCS_CONTENT_INFO):
04504             encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
04505             break;
04506         case LOWORD(PKCS_ATTRIBUTE):
04507             encodeFunc = CRYPT_AsnEncodePKCSAttribute;
04508             break;
04509         case LOWORD(X509_UNICODE_NAME_VALUE):
04510             encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
04511             break;
04512         case LOWORD(X509_OCTET_STRING):
04513             encodeFunc = CRYPT_AsnEncodeOctets;
04514             break;
04515         case LOWORD(X509_BITS):
04516         case LOWORD(X509_KEY_USAGE):
04517             encodeFunc = CRYPT_AsnEncodeBits;
04518             break;
04519         case LOWORD(X509_INTEGER):
04520             encodeFunc = CRYPT_AsnEncodeInt;
04521             break;
04522         case LOWORD(X509_MULTI_BYTE_INTEGER):
04523             encodeFunc = CRYPT_AsnEncodeInteger;
04524             break;
04525         case LOWORD(X509_MULTI_BYTE_UINT):
04526             encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
04527             break;
04528         case LOWORD(X509_ENUMERATED):
04529             encodeFunc = CRYPT_AsnEncodeEnumerated;
04530             break;
04531         case LOWORD(X509_CHOICE_OF_TIME):
04532             encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
04533             break;
04534         case LOWORD(X509_AUTHORITY_KEY_ID2):
04535             encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
04536             break;
04537         case LOWORD(X509_AUTHORITY_INFO_ACCESS):
04538             encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
04539             break;
04540         case LOWORD(X509_SEQUENCE_OF_ANY):
04541             encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
04542             break;
04543         case LOWORD(PKCS_UTC_TIME):
04544             encodeFunc = CRYPT_AsnEncodeUtcTime;
04545             break;
04546         case LOWORD(X509_CRL_DIST_POINTS):
04547             encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
04548             break;
04549         case LOWORD(X509_ENHANCED_KEY_USAGE):
04550             encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
04551             break;
04552         case LOWORD(PKCS_CTL):
04553             encodeFunc = CRYPT_AsnEncodeCTL;
04554             break;
04555         case LOWORD(PKCS_SMIME_CAPABILITIES):
04556             encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
04557             break;
04558         case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
04559             encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
04560             break;
04561         case LOWORD(PKCS_ATTRIBUTES):
04562             encodeFunc = CRYPT_AsnEncodePKCSAttributes;
04563             break;
04564         case LOWORD(X509_ISSUING_DIST_POINT):
04565             encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
04566             break;
04567         case LOWORD(X509_NAME_CONSTRAINTS):
04568             encodeFunc = CRYPT_AsnEncodeNameConstraints;
04569             break;
04570         case LOWORD(X509_POLICY_MAPPINGS):
04571             encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
04572             break;
04573         case LOWORD(X509_POLICY_CONSTRAINTS):
04574             encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
04575             break;
04576         case LOWORD(PKCS7_SIGNER_INFO):
04577             encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
04578             break;
04579         case LOWORD(CMS_SIGNER_INFO):
04580             encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
04581             break;
04582         }
04583     }
04584     else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
04585         encodeFunc = CRYPT_AsnEncodeExtensions;
04586     else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
04587         encodeFunc = CRYPT_AsnEncodeUtcTime;
04588     else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
04589         encodeFunc = CRYPT_AsnEncodeUtcTime;
04590     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
04591         encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
04592     else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
04593         encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
04594     else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
04595         encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
04596     else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
04597         encodeFunc = CRYPT_AsnEncodeEnumerated;
04598     else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
04599         encodeFunc = CRYPT_AsnEncodeBits;
04600     else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
04601         encodeFunc = CRYPT_AsnEncodeOctets;
04602     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
04603         encodeFunc = CRYPT_AsnEncodeBasicConstraints;
04604     else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
04605         encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
04606     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
04607         encodeFunc = CRYPT_AsnEncodeAltName;
04608     else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
04609         encodeFunc = CRYPT_AsnEncodeAltName;
04610     else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
04611         encodeFunc = CRYPT_AsnEncodeAltName;
04612     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
04613         encodeFunc = CRYPT_AsnEncodeAltName;
04614     else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
04615         encodeFunc = CRYPT_AsnEncodeAltName;
04616     else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
04617         encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
04618     else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
04619         encodeFunc = CRYPT_AsnEncodeCertPolicies;
04620     else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
04621         encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
04622     else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
04623         encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
04624     else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
04625         encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
04626     else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
04627         encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
04628     else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
04629         encodeFunc = CRYPT_AsnEncodeNameConstraints;
04630     else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
04631         encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
04632     else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
04633         encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
04634     else if (!strcmp(lpszStructType, szOID_CTL))
04635         encodeFunc = CRYPT_AsnEncodeCTL;
04636     return encodeFunc;
04637 }
04638 
04639 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
04640  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
04641 {
04642     static HCRYPTOIDFUNCSET set = NULL;
04643     CryptEncodeObjectFunc encodeFunc = NULL;
04644 
04645     if (!set)
04646         set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
04647     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
04648      (void **)&encodeFunc, hFunc);
04649     return encodeFunc;
04650 }
04651 
04652 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
04653  LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
04654 {
04655     static HCRYPTOIDFUNCSET set = NULL;
04656     CryptEncodeObjectExFunc encodeFunc = NULL;
04657 
04658     if (!set)
04659         set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
04660     CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
04661      (void **)&encodeFunc, hFunc);
04662     return encodeFunc;
04663 }
04664 
04665 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
04666  const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
04667 {
04668     BOOL ret = FALSE;
04669     HCRYPTOIDFUNCADDR hFunc = NULL;
04670     CryptEncodeObjectFunc pCryptEncodeObject = NULL;
04671     CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
04672 
04673     TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
04674      debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
04675      pcbEncoded);
04676 
04677     if (!pbEncoded && !pcbEncoded)
04678     {
04679         SetLastError(ERROR_INVALID_PARAMETER);
04680         return FALSE;
04681     }
04682 
04683     if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
04684      lpszStructType)))
04685     {
04686         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
04687          debugstr_a(lpszStructType));
04688         pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
04689          lpszStructType, &hFunc);
04690         if (!pCryptEncodeObject)
04691             pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
04692              lpszStructType, &hFunc);
04693     }
04694     if (pCryptEncodeObject)
04695         ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
04696          pvStructInfo, pbEncoded, pcbEncoded);
04697     else if (pCryptEncodeObjectEx)
04698         ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
04699          pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
04700     if (hFunc)
04701         CryptFreeOIDFunctionAddress(hFunc, 0);
04702     TRACE_(crypt)("returning %d\n", ret);
04703     return ret;
04704 }
04705 
04706 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
04707  const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
04708  void *pvEncoded, DWORD *pcbEncoded)
04709 {
04710     BOOL ret = FALSE;
04711     HCRYPTOIDFUNCADDR hFunc = NULL;
04712     CryptEncodeObjectExFunc encodeFunc = NULL;
04713 
04714     TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
04715      debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
04716      pvEncoded, pcbEncoded);
04717 
04718     if (!pvEncoded && !pcbEncoded)
04719     {
04720         SetLastError(ERROR_INVALID_PARAMETER);
04721         return FALSE;
04722     }
04723 
04724     SetLastError(NOERROR);
04725     if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
04726         if (!pvEncoded) {
04727             SetLastError(ERROR_INVALID_PARAMETER);
04728             return FALSE;
04729         }
04730         *(BYTE **)pvEncoded = NULL;
04731     }
04732     encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
04733     if (!encodeFunc)
04734     {
04735         TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
04736          debugstr_a(lpszStructType));
04737         encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
04738          &hFunc);
04739     }
04740     if (encodeFunc)
04741         ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
04742          dwFlags, pEncodePara, pvEncoded, pcbEncoded);
04743     else
04744     {
04745         CryptEncodeObjectFunc pCryptEncodeObject =
04746          CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
04747 
04748         if (pCryptEncodeObject)
04749         {
04750             if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
04751             {
04752                 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
04753                  pvStructInfo, NULL, pcbEncoded);
04754                 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
04755                  pvEncoded, pcbEncoded, *pcbEncoded)))
04756                     ret = pCryptEncodeObject(dwCertEncodingType,
04757                      lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
04758                      pcbEncoded);
04759             }
04760             else
04761                 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
04762                  pvStructInfo, pvEncoded, pcbEncoded);
04763         }
04764     }
04765     if (hFunc)
04766         CryptFreeOIDFunctionAddress(hFunc, 0);
04767     TRACE_(crypt)("returning %d\n", ret);
04768     return ret;
04769 }
04770 
04771 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
04772  LPCWSTR szPassword, DWORD dwFlags)
04773 {
04774     return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
04775 }
04776 
04777 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
04778  LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
04779 {
04780     FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
04781      pvReserved, dwFlags);
04782     return FALSE;
04783 }
04784 
04785 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
04786  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
04787 {
04788     return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
04789      NULL, 0, NULL, pInfo, pcbInfo);
04790 }
04791 
04792 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
04793  DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
04794  DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
04795 {
04796     BOOL ret;
04797     HCRYPTKEY key;
04798     static CHAR oid[] = szOID_RSA_RSA;
04799 
04800     TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
04801      dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
04802      pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
04803 
04804     if (!pszPublicKeyObjId)
04805         pszPublicKeyObjId = oid;
04806     if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
04807     {
04808         DWORD keySize = 0;
04809 
04810         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
04811         if (ret)
04812         {
04813             LPBYTE pubKey = CryptMemAlloc(keySize);
04814 
04815             if (pubKey)
04816             {
04817                 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
04818                  &keySize);
04819                 if (ret)
04820                 {
04821                     DWORD encodedLen = 0;
04822 
04823                     ret = CryptEncodeObject(dwCertEncodingType,
04824                      RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
04825                     if (ret)
04826                     {
04827                         DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
04828                          strlen(pszPublicKeyObjId) + 1 + encodedLen;
04829 
04830                         if (!pInfo)
04831                             *pcbInfo = sizeNeeded;
04832                         else if (*pcbInfo < sizeNeeded)
04833                         {
04834                             SetLastError(ERROR_MORE_DATA);
04835                             *pcbInfo = sizeNeeded;
04836                             ret = FALSE;
04837                         }
04838                         else
04839                         {
04840                             *pcbInfo = sizeNeeded;
04841                             pInfo->Algorithm.pszObjId = (char *)pInfo +
04842                              sizeof(CERT_PUBLIC_KEY_INFO);
04843                             lstrcpyA(pInfo->Algorithm.pszObjId,
04844                              pszPublicKeyObjId);
04845                             pInfo->Algorithm.Parameters.cbData = 0;
04846                             pInfo->Algorithm.Parameters.pbData = NULL;
04847                             pInfo->PublicKey.pbData =
04848                              (BYTE *)pInfo->Algorithm.pszObjId
04849                              + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
04850                             pInfo->PublicKey.cbData = encodedLen;
04851                             pInfo->PublicKey.cUnusedBits = 0;
04852                             ret = CryptEncodeObject(dwCertEncodingType,
04853                              RSA_CSP_PUBLICKEYBLOB, pubKey,
04854                              pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
04855                         }
04856                     }
04857                 }
04858                 CryptMemFree(pubKey);
04859             }
04860             else
04861                 ret = FALSE;
04862         }
04863         CryptDestroyKey(key);
04864     }
04865     return ret;
04866 }
04867 
04868 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
04869  DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
04870  DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
04871 
04872 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
04873  DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
04874  void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
04875 {
04876     static HCRYPTOIDFUNCSET set = NULL;
04877     BOOL ret;
04878     ExportPublicKeyInfoExFunc exportFunc = NULL;
04879     HCRYPTOIDFUNCADDR hFunc = NULL;
04880 
04881     TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
04882      dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
04883      pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
04884 
04885     if (!hCryptProv)
04886     {
04887         SetLastError(ERROR_INVALID_PARAMETER);
04888         return FALSE;
04889     }
04890 
04891     if (pszPublicKeyObjId)
04892     {
04893         if (!set)
04894             set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
04895              0);
04896         CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
04897          0, (void **)&exportFunc, &hFunc);
04898     }
04899     if (!exportFunc)
04900         exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
04901     ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
04902      pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
04903     if (hFunc)
04904         CryptFreeOIDFunctionAddress(hFunc, 0);
04905     return ret;
04906 }
04907 
04908 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
04909  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
04910 {
04911     return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
04912      0, 0, NULL, phKey);
04913 }
04914 
04915 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
04916  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
04917  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
04918 {
04919     BOOL ret;
04920     DWORD pubKeySize = 0;
04921 
04922     TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
04923      dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
04924 
04925     ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
04926      pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
04927     if (ret)
04928     {
04929         LPBYTE pubKey = CryptMemAlloc(pubKeySize);
04930 
04931         if (pubKey)
04932         {
04933             ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
04934              pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
04935              &pubKeySize);
04936             if (ret)
04937             {
04938                 if(aiKeyAlg)
04939                   ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
04940                 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
04941                  phKey);
04942             }
04943             CryptMemFree(pubKey);
04944         }
04945         else
04946             ret = FALSE;
04947     }
04948     return ret;
04949 }
04950 
04951 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
04952  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
04953  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
04954 
04955 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
04956  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
04957  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
04958 {
04959     static HCRYPTOIDFUNCSET set = NULL;
04960     BOOL ret;
04961     ImportPublicKeyInfoExFunc importFunc = NULL;
04962     HCRYPTOIDFUNCADDR hFunc = NULL;
04963 
04964     TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
04965      dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
04966 
04967     if (!set)
04968         set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
04969     CryptGetOIDFunctionAddress(set, dwCertEncodingType,
04970      pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
04971     if (!importFunc)
04972         importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
04973     ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
04974      pvAuxInfo, phKey);
04975     if (hFunc)
04976         CryptFreeOIDFunctionAddress(hFunc, 0);
04977     return ret;
04978 }

Generated on Sun May 27 2012 04:23:14 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.