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

asn.c
Go to the documentation of this file.
00001 /* wintrust asn functions
00002  *
00003  * Copyright 2007 Juan Lang
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00018  *
00019  */
00020 
00021 #include "config.h"
00022 #include "wine/port.h"
00023 
00024 #include <stdarg.h>
00025 #include <stdio.h>
00026 #include <assert.h>
00027 #define NONAMELESSUNION
00028 #include "windef.h"
00029 #include "winbase.h"
00030 #include "winerror.h"
00031 #include "wincrypt.h"
00032 #include "wintrust.h"
00033 #include "snmp.h"
00034 #include "winternl.h"
00035 #include "wine/debug.h"
00036 #include "wine/exception.h"
00037 
00038 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
00039 
00040 #ifdef WORDS_BIGENDIAN
00041 
00042 #define hton16(x) (x)
00043 #define n16toh(x) (x)
00044 
00045 #else
00046 
00047 #define hton16(x) RtlUshortByteSwap(x)
00048 #define n16toh(x) RtlUshortByteSwap(x)
00049 
00050 #endif
00051 
00052 #define ASN_BOOL            (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
00053 #define ASN_BITSTRING       (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
00054 #define ASN_BMPSTRING       (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
00055 
00056 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
00057 {
00058     DWORD bytesNeeded, significantBytes = 0;
00059 
00060     if (len <= 0x7f)
00061         bytesNeeded = 1;
00062     else
00063     {
00064         DWORD temp;
00065 
00066         for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
00067          temp <<= 8, significantBytes--)
00068             ;
00069         bytesNeeded = significantBytes + 1;
00070     }
00071     if (!pbEncoded)
00072     {
00073         *pcbEncoded = bytesNeeded;
00074         return TRUE;
00075     }
00076     if (*pcbEncoded < bytesNeeded)
00077     {
00078         SetLastError(ERROR_MORE_DATA);
00079         return FALSE;
00080     }
00081     if (len <= 0x7f)
00082         *pbEncoded = (BYTE)len;
00083     else
00084     {
00085         DWORD i;
00086 
00087         *pbEncoded++ = significantBytes | 0x80;
00088         for (i = 0; i < significantBytes; i++)
00089         {
00090             *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
00091             len >>= 8;
00092         }
00093     }
00094     *pcbEncoded = bytesNeeded;
00095     return TRUE;
00096 }
00097 
00098 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
00099  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00100  DWORD *pcbEncoded)
00101 {
00102     BOOL ret = TRUE;
00103     const CRYPT_DATA_BLOB *blob = pvStructInfo;
00104     DWORD bytesNeeded, lenBytes;
00105 
00106     TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
00107      *pcbEncoded);
00108 
00109     CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
00110     bytesNeeded = 1 + lenBytes + blob->cbData;
00111     if (!pbEncoded)
00112         *pcbEncoded = bytesNeeded;
00113     else if (*pcbEncoded < bytesNeeded)
00114     {
00115         *pcbEncoded = bytesNeeded;
00116         SetLastError(ERROR_MORE_DATA);
00117         ret = FALSE;
00118     }
00119     else
00120     {
00121         *pbEncoded++ = ASN_OCTETSTRING;
00122         CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
00123         pbEncoded += lenBytes;
00124         if (blob->cbData)
00125             memcpy(pbEncoded, blob->pbData, blob->cbData);
00126     }
00127     TRACE("returning %d\n", ret);
00128     return ret;
00129 }
00130 
00131 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
00132  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00133  DWORD *pcbEncoded)
00134 {
00135     BOOL ret = FALSE;
00136 
00137     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
00138      debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
00139      pcbEncoded);
00140 
00141     __TRY
00142     {
00143         const SPC_LINK *link = pvStructInfo;
00144         DWORD bytesNeeded, lenBytes;
00145 
00146         switch (link->dwLinkChoice)
00147         {
00148         case SPC_FILE_LINK_CHOICE:
00149         {
00150             DWORD fileNameLen, fileNameLenBytes;
00151             LPWSTR ptr;
00152 
00153             fileNameLen = link->u.pwszFile ?
00154              lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
00155             CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
00156             CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
00157              &lenBytes);
00158             bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
00159             if (!pbEncoded)
00160             {
00161                 *pcbEncoded = bytesNeeded;
00162                 ret = TRUE;
00163             }
00164             else if (*pcbEncoded < bytesNeeded)
00165             {
00166                 SetLastError(ERROR_MORE_DATA);
00167                 *pcbEncoded = bytesNeeded;
00168             }
00169             else
00170             {
00171                 *pcbEncoded = bytesNeeded;
00172                 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
00173                 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
00174                  &lenBytes);
00175                 pbEncoded += lenBytes;
00176                 *pbEncoded++ = ASN_CONTEXT;
00177                 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
00178                 pbEncoded += fileNameLenBytes;
00179                 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
00180                 {
00181                     *(WCHAR *)pbEncoded = hton16(*ptr);
00182                     pbEncoded += sizeof(WCHAR);
00183                 }
00184                 ret = TRUE;
00185             }
00186             break;
00187         }
00188         case SPC_MONIKER_LINK_CHOICE:
00189         {
00190             DWORD classIdLenBytes, dataLenBytes, dataLen;
00191             CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
00192              (BYTE *)link->u.Moniker.ClassId };
00193 
00194             CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
00195             CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
00196              &dataLenBytes);
00197             dataLen = 2 + classIdLenBytes + classId.cbData +
00198              dataLenBytes + link->u.Moniker.SerializedData.cbData;
00199             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
00200             bytesNeeded = 1 + dataLen + lenBytes;
00201             if (!pbEncoded)
00202             {
00203                 *pcbEncoded = bytesNeeded;
00204                 ret = TRUE;
00205             }
00206             else if (*pcbEncoded < bytesNeeded)
00207             {
00208                 SetLastError(ERROR_MORE_DATA);
00209                 *pcbEncoded = bytesNeeded;
00210             }
00211             else
00212             {
00213                 DWORD size;
00214 
00215                 *pcbEncoded = bytesNeeded;
00216                 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
00217                 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
00218                 pbEncoded += lenBytes;
00219                 size = 1 + classIdLenBytes + classId.cbData;
00220                 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
00221                  pbEncoded, &size);
00222                 pbEncoded += size;
00223                 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
00224                 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
00225                  &link->u.Moniker.SerializedData, pbEncoded, &size);
00226                 pbEncoded += size;
00227                 ret = TRUE;
00228             }
00229             break;
00230         }
00231         case SPC_URL_LINK_CHOICE:
00232         {
00233             LPWSTR ptr;
00234             DWORD urlLen;
00235 
00236             /* Check for invalid characters in URL */
00237             ret = TRUE;
00238             urlLen = 0;
00239             for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
00240                 if (*ptr > 0x7f)
00241                 {
00242                     *pcbEncoded = 0;
00243                     SetLastError(CRYPT_E_INVALID_IA5_STRING);
00244                     ret = FALSE;
00245                 }
00246                 else
00247                     urlLen++;
00248             if (ret)
00249             {
00250                 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
00251                 bytesNeeded = 1 + lenBytes + urlLen;
00252                 if (!pbEncoded)
00253                     *pcbEncoded = bytesNeeded;
00254                 else if (*pcbEncoded < bytesNeeded)
00255                 {
00256                     SetLastError(ERROR_MORE_DATA);
00257                     *pcbEncoded = bytesNeeded;
00258                     ret = FALSE;
00259                 }
00260                 else
00261                 {
00262                     *pcbEncoded = bytesNeeded;
00263                     *pbEncoded++ = ASN_CONTEXT;
00264                     CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
00265                     pbEncoded += lenBytes;
00266                     for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
00267                         *pbEncoded++ = (BYTE)*ptr;
00268                 }
00269             }
00270             break;
00271         }
00272         default:
00273             SetLastError(E_INVALIDARG);
00274         }
00275     }
00276     __EXCEPT_PAGE_FAULT
00277     {
00278         SetLastError(STATUS_ACCESS_VIOLATION);
00279     }
00280     __ENDTRY
00281     TRACE("returning %d\n", ret);
00282     return ret;
00283 }
00284 
00285 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
00286  BYTE *, DWORD *);
00287 
00288 struct AsnEncodeSequenceItem
00289 {
00290     const void           *pvStructInfo;
00291     CryptEncodeObjectFunc encodeFunc;
00292     DWORD                 size; /* used during encoding, not for your use */
00293 };
00294 
00295 static BOOL CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
00296  struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
00297  DWORD *pcbEncoded)
00298 {
00299     BOOL ret;
00300     DWORD i, dataLen = 0;
00301 
00302     TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
00303     for (i = 0, ret = TRUE; ret && i < cItem; i++)
00304     {
00305         ret = items[i].encodeFunc(dwCertEncodingType, NULL,
00306          items[i].pvStructInfo, NULL, &items[i].size);
00307         /* Some functions propagate their errors through the size */
00308         if (!ret)
00309             *pcbEncoded = items[i].size;
00310         dataLen += items[i].size;
00311     }
00312     if (ret)
00313     {
00314         DWORD lenBytes, bytesNeeded;
00315 
00316         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
00317         bytesNeeded = 1 + lenBytes + dataLen;
00318         if (!pbEncoded)
00319             *pcbEncoded = bytesNeeded;
00320         else if (*pcbEncoded < bytesNeeded)
00321         {
00322             *pcbEncoded = bytesNeeded;
00323             SetLastError(ERROR_MORE_DATA);
00324             ret = FALSE;
00325         }
00326         else
00327         {
00328             *pcbEncoded = bytesNeeded;
00329             *pbEncoded++ = ASN_SEQUENCE;
00330             CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
00331             pbEncoded += lenBytes;
00332             for (i = 0; ret && i < cItem; i++)
00333             {
00334                 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
00335                  items[i].pvStructInfo, pbEncoded, &items[i].size);
00336                 /* Some functions propagate their errors through the size */
00337                 if (!ret)
00338                     *pcbEncoded = items[i].size;
00339                 pbEncoded += items[i].size;
00340             }
00341         }
00342     }
00343     TRACE("returning %d\n", ret);
00344     return ret;
00345 }
00346 
00347 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
00348  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00349  DWORD *pcbEncoded)
00350 {
00351     BOOL ret = FALSE;
00352 
00353     __TRY
00354     {
00355         const CRYPT_BIT_BLOB *blob = pvStructInfo;
00356         DWORD bytesNeeded, lenBytes, dataBytes;
00357         BYTE unusedBits;
00358 
00359         /* yep, MS allows cUnusedBits to be >= 8 */
00360         if (!blob->cUnusedBits)
00361         {
00362             dataBytes = blob->cbData;
00363             unusedBits = 0;
00364         }
00365         else if (blob->cbData * 8 > blob->cUnusedBits)
00366         {
00367             dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
00368             unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
00369              blob->cUnusedBits;
00370         }
00371         else
00372         {
00373             dataBytes = 0;
00374             unusedBits = 0;
00375         }
00376         CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
00377         bytesNeeded = 1 + lenBytes + dataBytes + 1;
00378         if (!pbEncoded)
00379         {
00380             *pcbEncoded = bytesNeeded;
00381             ret = TRUE;
00382         }
00383         else if (*pcbEncoded < bytesNeeded)
00384         {
00385             *pcbEncoded = bytesNeeded;
00386             SetLastError(ERROR_MORE_DATA);
00387         }
00388         else
00389         {
00390             ret = TRUE;
00391             *pcbEncoded = bytesNeeded;
00392             *pbEncoded++ = ASN_BITSTRING;
00393             CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
00394             pbEncoded += lenBytes;
00395             *pbEncoded++ = unusedBits;
00396             if (dataBytes)
00397             {
00398                 BYTE mask = 0xff << unusedBits;
00399 
00400                 if (dataBytes > 1)
00401                 {
00402                     memcpy(pbEncoded, blob->pbData, dataBytes - 1);
00403                     pbEncoded += dataBytes - 1;
00404                 }
00405                 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
00406             }
00407         }
00408     }
00409     __EXCEPT_PAGE_FAULT
00410     {
00411         SetLastError(STATUS_ACCESS_VIOLATION);
00412     }
00413     __ENDTRY
00414     return ret;
00415 }
00416 
00417 struct AsnConstructedItem
00418 {
00419     BYTE                  tag;
00420     const void           *pvStructInfo;
00421     CryptEncodeObjectFunc encodeFunc;
00422 };
00423 
00424 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
00425  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00426  DWORD *pcbEncoded)
00427 {
00428     BOOL ret;
00429     const struct AsnConstructedItem *item = pvStructInfo;
00430     DWORD len;
00431 
00432     if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
00433      item->pvStructInfo, NULL, &len)))
00434     {
00435         DWORD dataLen, bytesNeeded;
00436 
00437         CRYPT_EncodeLen(len, NULL, &dataLen);
00438         bytesNeeded = 1 + dataLen + len;
00439         if (!pbEncoded)
00440             *pcbEncoded = bytesNeeded;
00441         else if (*pcbEncoded < bytesNeeded)
00442         {
00443             *pcbEncoded = bytesNeeded;
00444             SetLastError(ERROR_MORE_DATA);
00445             ret = FALSE;
00446         }
00447         else
00448         {
00449             *pcbEncoded = bytesNeeded;
00450             *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
00451             CRYPT_EncodeLen(len, pbEncoded, &dataLen);
00452             pbEncoded += dataLen;
00453             ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
00454              item->pvStructInfo, pbEncoded, &len);
00455             if (!ret)
00456             {
00457                 /* Some functions propagate their errors through the size */
00458                 *pcbEncoded = len;
00459             }
00460         }
00461     }
00462     else
00463     {
00464         /* Some functions propagate their errors through the size */
00465         *pcbEncoded = len;
00466     }
00467     return ret;
00468 }
00469 
00470 
00471 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
00472  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00473  DWORD *pcbEncoded)
00474 {
00475     const SPC_PE_IMAGE_DATA *imageData = pvStructInfo;
00476     BOOL ret = FALSE;
00477 
00478     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
00479      debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
00480      pcbEncoded);
00481 
00482     __TRY
00483     {
00484         struct AsnEncodeSequenceItem items[2] = {
00485          { 0 }
00486         };
00487         struct AsnConstructedItem constructed = { 0, imageData->pFile,
00488          WVTAsn1SpcLinkEncode };
00489         DWORD cItem = 0;
00490 
00491         if (imageData->Flags.cbData)
00492         {
00493             items[cItem].pvStructInfo = &imageData->Flags;
00494             items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
00495             cItem++;
00496         }
00497         if (imageData->pFile)
00498         {
00499             items[cItem].pvStructInfo = &constructed;
00500             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
00501             cItem++;
00502         }
00503 
00504         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
00505          pbEncoded, pcbEncoded);
00506     }
00507     __EXCEPT_PAGE_FAULT
00508     {
00509         SetLastError(STATUS_ACCESS_VIOLATION);
00510     }
00511     __ENDTRY
00512     TRACE("returning %d\n", ret);
00513     return ret;
00514 }
00515 
00516 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
00517  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00518  DWORD *pcbEncoded)
00519 {
00520     LPCSTR pszObjId = pvStructInfo;
00521     DWORD bytesNeeded = 0, lenBytes;
00522     BOOL ret = TRUE;
00523     int firstPos = 0;
00524     BYTE firstByte = 0;
00525 
00526     TRACE("%s\n", debugstr_a(pszObjId));
00527 
00528     if (pszObjId)
00529     {
00530         const char *ptr;
00531         int val1, val2;
00532 
00533         if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
00534         {
00535             SetLastError(CRYPT_E_ASN1_ERROR);
00536             return FALSE;
00537         }
00538         bytesNeeded++;
00539         firstByte = val1 * 40 + val2;
00540         ptr = pszObjId + firstPos;
00541         if (*ptr == '.')
00542         {
00543             ptr++;
00544             firstPos++;
00545         }
00546         while (ret && *ptr)
00547         {
00548             int pos;
00549 
00550             /* note I assume each component is at most 32-bits long in base 2 */
00551             if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
00552             {
00553                 if (val1 >= 0x10000000)
00554                     bytesNeeded += 5;
00555                 else if (val1 >= 0x200000)
00556                     bytesNeeded += 4;
00557                 else if (val1 >= 0x4000)
00558                     bytesNeeded += 3;
00559                 else if (val1 >= 0x80)
00560                     bytesNeeded += 2;
00561                 else
00562                     bytesNeeded += 1;
00563                 ptr += pos;
00564                 if (*ptr == '.')
00565                     ptr++;
00566             }
00567             else
00568             {
00569                 SetLastError(CRYPT_E_ASN1_ERROR);
00570                 return FALSE;
00571             }
00572         }
00573         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
00574     }
00575     else
00576         lenBytes = 1;
00577     bytesNeeded += 1 + lenBytes;
00578     if (pbEncoded)
00579     {
00580         if (*pcbEncoded < bytesNeeded)
00581         {
00582             SetLastError(ERROR_MORE_DATA);
00583             ret = FALSE;
00584         }
00585         else
00586         {
00587             *pbEncoded++ = ASN_OBJECTIDENTIFIER;
00588             CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
00589             pbEncoded += lenBytes;
00590             if (pszObjId)
00591             {
00592                 const char *ptr;
00593                 int val, pos;
00594 
00595                 *pbEncoded++ = firstByte;
00596                 ptr = pszObjId + firstPos;
00597                 while (ret && *ptr)
00598                 {
00599                     sscanf(ptr, "%d%n", &val, &pos);
00600                     {
00601                         unsigned char outBytes[5];
00602                         int numBytes, i;
00603 
00604                         if (val >= 0x10000000)
00605                             numBytes = 5;
00606                         else if (val >= 0x200000)
00607                             numBytes = 4;
00608                         else if (val >= 0x4000)
00609                             numBytes = 3;
00610                         else if (val >= 0x80)
00611                             numBytes = 2;
00612                         else
00613                             numBytes = 1;
00614                         for (i = numBytes; i > 0; i--)
00615                         {
00616                             outBytes[i - 1] = val & 0x7f;
00617                             val >>= 7;
00618                         }
00619                         for (i = 0; i < numBytes - 1; i++)
00620                             *pbEncoded++ = outBytes[i] | 0x80;
00621                         *pbEncoded++ = outBytes[i];
00622                         ptr += pos;
00623                         if (*ptr == '.')
00624                             ptr++;
00625                     }
00626                 }
00627             }
00628         }
00629     }
00630     *pcbEncoded = bytesNeeded;
00631     return ret;
00632 }
00633 
00634 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
00635  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00636  DWORD *pcbEncoded)
00637 {
00638     const CRYPT_DER_BLOB *blob = pvStructInfo;
00639     BOOL ret = TRUE;
00640 
00641     if (!pbEncoded)
00642         *pcbEncoded = blob->cbData;
00643     else if (*pcbEncoded < blob->cbData)
00644     {
00645         *pcbEncoded = blob->cbData;
00646         SetLastError(ERROR_MORE_DATA);
00647         ret = FALSE;
00648     }
00649     else
00650     {
00651         if (blob->cbData)
00652             memcpy(pbEncoded, blob->pbData, blob->cbData);
00653         *pcbEncoded = blob->cbData;
00654     }
00655     return ret;
00656 }
00657 
00658 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
00659  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
00660  BYTE *pbEncoded, DWORD *pcbEncoded)
00661 {
00662     const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
00663     static const BYTE asn1Null[] = { ASN_NULL, 0 };
00664     static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
00665      (LPBYTE)asn1Null };
00666     BOOL ret;
00667     struct AsnEncodeSequenceItem items[2] = {
00668      { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
00669      { NULL,           CRYPT_CopyEncodedBlob, 0 },
00670     };
00671 
00672     if (algo->Parameters.cbData)
00673         items[1].pvStructInfo = &algo->Parameters;
00674     else
00675         items[1].pvStructInfo = &nullBlob;
00676     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
00677      sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
00678     return ret;
00679 }
00680 
00681 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
00682  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00683  DWORD *pcbEncoded)
00684 {
00685     const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo;
00686     struct AsnEncodeSequenceItem items[] = {
00687      { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
00688      { &typeValue->Value,    CRYPT_CopyEncodedBlob, 0 },
00689     };
00690 
00691     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
00692      items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
00693 }
00694 
00695 struct SPCDigest
00696 {
00697     CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
00698     CRYPT_HASH_BLOB            Digest;
00699 };
00700 
00701 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
00702  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00703  DWORD *pcbEncoded)
00704 {
00705     const struct SPCDigest *digest = pvStructInfo;
00706     struct AsnEncodeSequenceItem items[] = {
00707      { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
00708      { &digest->Digest,          CRYPT_CopyEncodedBlob, 0 },
00709     };
00710 
00711     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
00712      items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
00713 }
00714 
00715 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
00716  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00717  DWORD *pcbEncoded)
00718 {
00719     BOOL ret = FALSE;
00720 
00721     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
00722      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
00723 
00724     __TRY
00725     {
00726         const SPC_INDIRECT_DATA_CONTENT *data = pvStructInfo;
00727         struct AsnEncodeSequenceItem items[] = {
00728          { &data->Data,            CRYPT_AsnEncodeAttributeTypeValue, 0 },
00729          { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
00730         };
00731 
00732         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
00733          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
00734     }
00735     __EXCEPT_PAGE_FAULT
00736     {
00737         SetLastError(STATUS_ACCESS_VIOLATION);
00738     }
00739     __ENDTRY
00740     return ret;
00741 }
00742 
00743 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
00744  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00745  DWORD *pcbEncoded)
00746 {
00747     BOOL ret = TRUE;
00748     LPCWSTR str = pvStructInfo;
00749     DWORD bytesNeeded, lenBytes, strLen;
00750 
00751     if (str)
00752         strLen = lstrlenW(str);
00753     else
00754         strLen = 0;
00755     CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
00756     bytesNeeded = 1 + lenBytes + strLen * 2;
00757     if (!pbEncoded)
00758         *pcbEncoded = bytesNeeded;
00759     else if (*pcbEncoded < bytesNeeded)
00760     {
00761         *pcbEncoded = bytesNeeded;
00762         SetLastError(ERROR_MORE_DATA);
00763         ret = FALSE;
00764     }
00765     else
00766     {
00767         DWORD i;
00768 
00769         *pcbEncoded = bytesNeeded;
00770         *pbEncoded++ = ASN_BMPSTRING;
00771         CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
00772         pbEncoded += lenBytes;
00773         for (i = 0; i < strLen; i++)
00774         {
00775             *pbEncoded++ = (str[i] & 0xff00) >> 8;
00776             *pbEncoded++ = str[i] & 0x00ff;
00777         }
00778     }
00779     return ret;
00780 }
00781 
00782 struct AsnEncodeTagSwappedItem
00783 {
00784     BYTE                  tag;
00785     const void           *pvStructInfo;
00786     CryptEncodeObjectFunc encodeFunc;
00787 };
00788 
00789 /* Sort of a wacky hack, it encodes something using the struct
00790  * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
00791  * given in the struct AsnEncodeTagSwappedItem.
00792  */
00793 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
00794  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00795  DWORD *pcbEncoded)
00796 {
00797     BOOL ret;
00798     const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
00799 
00800     ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
00801      item->pvStructInfo, pbEncoded, pcbEncoded);
00802     if (ret && pbEncoded)
00803         *pbEncoded = item->tag;
00804     return ret;
00805 }
00806 
00807 BOOL WINAPI WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType,
00808  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00809  DWORD *pcbEncoded)
00810 {
00811     BOOL ret = FALSE;
00812 
00813     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
00814      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
00815 
00816     __TRY
00817     {
00818         const SPC_SP_OPUS_INFO *info = pvStructInfo;
00819 
00820         if (info->pMoreInfo &&
00821          info->pMoreInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
00822          info->pMoreInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
00823          info->pMoreInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
00824             SetLastError(E_INVALIDARG);
00825         else if (info->pPublisherInfo &&
00826          info->pPublisherInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
00827          info->pPublisherInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
00828          info->pPublisherInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
00829             SetLastError(E_INVALIDARG);
00830         else
00831         {
00832             struct AsnEncodeSequenceItem items[3] = { { 0 } };
00833             struct AsnConstructedItem constructed[3] = { { 0 } };
00834             struct AsnEncodeTagSwappedItem swapped;
00835             DWORD cItem = 0, cConstructed = 0;
00836 
00837             if (info->pwszProgramName)
00838             {
00839                 swapped.tag = ASN_CONTEXT;
00840                 swapped.pvStructInfo = info->pwszProgramName;
00841                 swapped.encodeFunc = CRYPT_AsnEncodeBMPString;
00842                 constructed[cConstructed].tag = 0;
00843                 constructed[cConstructed].pvStructInfo = &swapped;
00844                 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeSwapTag;
00845                 items[cItem].pvStructInfo = &constructed[cConstructed];
00846                 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
00847                 cConstructed++;
00848                 cItem++;
00849             }
00850             if (info->pMoreInfo)
00851             {
00852                 constructed[cConstructed].tag = 1;
00853                 constructed[cConstructed].pvStructInfo = info->pMoreInfo;
00854                 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
00855                 items[cItem].pvStructInfo = &constructed[cConstructed];
00856                 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
00857                 cConstructed++;
00858                 cItem++;
00859             }
00860             if (info->pPublisherInfo)
00861             {
00862                 constructed[cConstructed].tag = 2;
00863                 constructed[cConstructed].pvStructInfo = info->pPublisherInfo;
00864                 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
00865                 items[cItem].pvStructInfo = &constructed[cConstructed];
00866                 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
00867                 cConstructed++;
00868                 cItem++;
00869             }
00870             ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
00871              items, cItem, pbEncoded, pcbEncoded);
00872         }
00873     }
00874     __EXCEPT_PAGE_FAULT
00875     {
00876         SetLastError(STATUS_ACCESS_VIOLATION);
00877     }
00878     __ENDTRY
00879     return ret;
00880 }
00881 
00882 static BOOL CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
00883  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00884  DWORD *pcbEncoded)
00885 {
00886     BOOL ret;
00887 
00888     __TRY
00889     {
00890         DWORD significantBytes, lenBytes, bytesNeeded;
00891         BYTE padByte = 0;
00892         BOOL pad = FALSE;
00893         const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
00894 
00895         significantBytes = blob->cbData;
00896         if (significantBytes)
00897         {
00898             if (blob->pbData[significantBytes - 1] & 0x80)
00899             {
00900                 /* negative, lop off leading (little-endian) 0xffs */
00901                 for (; significantBytes > 0 &&
00902                  blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
00903                     ;
00904                 if (blob->pbData[significantBytes - 1] < 0x80)
00905                 {
00906                     padByte = 0xff;
00907                     pad = TRUE;
00908                 }
00909             }
00910             else
00911             {
00912                 /* positive, lop off leading (little-endian) zeroes */
00913                 for (; significantBytes > 0 &&
00914                  !blob->pbData[significantBytes - 1]; significantBytes--)
00915                     ;
00916                 if (significantBytes == 0)
00917                     significantBytes = 1;
00918                 if (blob->pbData[significantBytes - 1] > 0x7f)
00919                 {
00920                     padByte = 0;
00921                     pad = TRUE;
00922                 }
00923             }
00924         }
00925         if (pad)
00926             CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
00927         else
00928             CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
00929         bytesNeeded = 1 + lenBytes + significantBytes;
00930         if (pad)
00931             bytesNeeded++;
00932         if (!pbEncoded)
00933         {
00934             *pcbEncoded = bytesNeeded;
00935             ret = TRUE;
00936         }
00937         else if (*pcbEncoded < bytesNeeded)
00938         {
00939             *pcbEncoded = bytesNeeded;
00940             SetLastError(ERROR_MORE_DATA);
00941             ret = FALSE;
00942         }
00943         else
00944         {
00945             *pcbEncoded = bytesNeeded;
00946             *pbEncoded++ = ASN_INTEGER;
00947             if (pad)
00948             {
00949                 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
00950                 pbEncoded += lenBytes;
00951                 *pbEncoded++ = padByte;
00952             }
00953             else
00954             {
00955                 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
00956                 pbEncoded += lenBytes;
00957             }
00958             for (; significantBytes > 0; significantBytes--)
00959                 *(pbEncoded++) = blob->pbData[significantBytes - 1];
00960             ret = TRUE;
00961         }
00962     }
00963     __EXCEPT_PAGE_FAULT
00964     {
00965         SetLastError(STATUS_ACCESS_VIOLATION);
00966         ret = FALSE;
00967     }
00968     __ENDTRY
00969     return ret;
00970 }
00971 
00972 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
00973  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00974  DWORD *pcbEncoded)
00975 {
00976     CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
00977 
00978     return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
00979      &blob, pbEncoded, pcbEncoded);
00980 }
00981 
00982 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
00983  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
00984  DWORD *pcbEncoded)
00985 {
00986     BOOL ret = FALSE;
00987 
00988     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
00989      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
00990 
00991     __TRY
00992     {
00993         const CAT_MEMBERINFO *info = pvStructInfo;
00994         struct AsnEncodeSequenceItem items[] = {
00995          { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
00996          { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
00997         };
00998 
00999         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
01000          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
01001     }
01002     __EXCEPT_PAGE_FAULT
01003     {
01004         SetLastError(STATUS_ACCESS_VIOLATION);
01005     }
01006     __ENDTRY
01007     return ret;
01008 }
01009 
01010 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
01011  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
01012  DWORD *pcbEncoded)
01013 {
01014     BOOL ret = FALSE;
01015 
01016     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
01017      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
01018 
01019     __TRY
01020     {
01021         const CAT_NAMEVALUE *value = pvStructInfo;
01022         struct AsnEncodeSequenceItem items[] = {
01023          { value->pwszTag,   CRYPT_AsnEncodeBMPString, 0 },
01024          { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
01025          { &value->Value,    CRYPT_AsnEncodeOctets, 0 },
01026         };
01027 
01028         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
01029          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
01030     }
01031     __EXCEPT_PAGE_FAULT
01032     {
01033         SetLastError(STATUS_ACCESS_VIOLATION);
01034     }
01035     __ENDTRY
01036     return ret;
01037 }
01038 
01039 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
01040  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
01041  DWORD *pcbEncoded)
01042 {
01043     BOOL val = *(const BOOL *)pvStructInfo, ret;
01044 
01045     TRACE("%d\n", val);
01046 
01047     if (!pbEncoded)
01048     {
01049         *pcbEncoded = 3;
01050         ret = TRUE;
01051     }
01052     else if (*pcbEncoded < 3)
01053     {
01054         *pcbEncoded = 3;
01055         SetLastError(ERROR_MORE_DATA);
01056         ret = FALSE;
01057     }
01058     else
01059     {
01060         *pcbEncoded = 3;
01061         *pbEncoded++ = ASN_BOOL;
01062         *pbEncoded++ = 1;
01063         *pbEncoded++ = val ? 0xff : 0;
01064         ret = TRUE;
01065     }
01066     TRACE("returning %d (%08x)\n", ret, GetLastError());
01067     return ret;
01068 }
01069 
01070 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType,
01071  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
01072  DWORD *pcbEncoded)
01073 {
01074     BOOL ret = FALSE;
01075 
01076     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
01077      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
01078 
01079     __TRY
01080     {
01081         const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo;
01082         struct AsnEncodeSequenceItem items[] = {
01083          { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 },
01084          { &criteria->fMeetsCriteria,          CRYPT_AsnEncodeBool, 0 },
01085         };
01086 
01087         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
01088          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
01089     }
01090     __EXCEPT_PAGE_FAULT
01091     {
01092         SetLastError(STATUS_ACCESS_VIOLATION);
01093     }
01094     __ENDTRY
01095     return ret;
01096 }
01097 
01098 /* Gets the number of length bytes from the given (leading) length byte */
01099 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
01100 
01101 /* Helper function to get the encoded length of the data starting at pbEncoded,
01102  * where pbEncoded[0] is the tag.  If the data are too short to contain a
01103  * length or if the length is too large for cbEncoded, sets an appropriate
01104  * error code and returns FALSE.
01105  */
01106 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
01107 {
01108     BOOL ret;
01109 
01110     if (cbEncoded <= 1)
01111     {
01112         SetLastError(CRYPT_E_ASN1_CORRUPT);
01113         ret = FALSE;
01114     }
01115     else if (pbEncoded[1] <= 0x7f)
01116     {
01117         if (pbEncoded[1] + 1 > cbEncoded)
01118         {
01119             SetLastError(CRYPT_E_ASN1_EOD);
01120             ret = FALSE;
01121         }
01122         else
01123         {
01124             *len = pbEncoded[1];
01125             ret = TRUE;
01126         }
01127     }
01128     else if (pbEncoded[1] == 0x80)
01129     {
01130         FIXME("unimplemented for indefinite-length encoding\n");
01131         SetLastError(CRYPT_E_ASN1_CORRUPT);
01132         ret = FALSE;
01133     }
01134     else
01135     {
01136         BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
01137 
01138         if (lenLen > sizeof(DWORD) + 1)
01139         {
01140             SetLastError(CRYPT_E_ASN1_LARGE);
01141             ret = FALSE;
01142         }
01143         else if (lenLen + 2 > cbEncoded)
01144         {
01145             SetLastError(CRYPT_E_ASN1_CORRUPT);
01146             ret = FALSE;
01147         }
01148         else
01149         {
01150             DWORD out = 0;
01151 
01152             pbEncoded += 2;
01153             while (--lenLen)
01154             {
01155                 out <<= 8;
01156                 out |= *pbEncoded++;
01157             }
01158             if (out + lenLen + 1 > cbEncoded)
01159             {
01160                 SetLastError(CRYPT_E_ASN1_EOD);
01161                 ret = FALSE;
01162             }
01163             else
01164             {
01165                 *len = out;
01166                 ret = TRUE;
01167             }
01168         }
01169     }
01170     return ret;
01171 }
01172 
01173 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
01174  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01175  void *pvStructInfo, DWORD *pcbStructInfo)
01176 {
01177     BOOL ret;
01178     DWORD bytesNeeded, dataLen;
01179 
01180     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01181      pvStructInfo, *pcbStructInfo);
01182 
01183     if (!cbEncoded)
01184     {
01185         SetLastError(CRYPT_E_ASN1_CORRUPT);
01186         ret = FALSE;
01187     }
01188     else if (pbEncoded[0] != ASN_OCTETSTRING)
01189     {
01190         SetLastError(CRYPT_E_ASN1_BADTAG);
01191         ret = FALSE;
01192     }
01193     else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01194     {
01195         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
01196             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
01197         else
01198             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
01199         if (!pvStructInfo)
01200             *pcbStructInfo = bytesNeeded;
01201         else if (*pcbStructInfo < bytesNeeded)
01202         {
01203             SetLastError(ERROR_MORE_DATA);
01204             *pcbStructInfo = bytesNeeded;
01205             ret = FALSE;
01206         }
01207         else
01208         {
01209             CRYPT_DATA_BLOB *blob;
01210             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01211 
01212             blob = pvStructInfo;
01213             blob->cbData = dataLen;
01214             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
01215                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
01216             else
01217             {
01218                 assert(blob->pbData);
01219                 if (blob->cbData)
01220                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
01221                      blob->cbData);
01222             }
01223         }
01224     }
01225     return ret;
01226 }
01227 
01228 static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
01229  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01230  void *pvStructInfo, DWORD *pcbStructInfo)
01231 {
01232     BOOL ret = FALSE;
01233     DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
01234 
01235     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01236      pvStructInfo, *pcbStructInfo);
01237 
01238     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01239     {
01240         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01241         DWORD realDataLen;
01242 
01243         switch (pbEncoded[0])
01244         {
01245         case ASN_CONTEXT:
01246             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
01247             if (!pvStructInfo)
01248                 *pcbStructInfo = bytesNeeded;
01249             else if (*pcbStructInfo < bytesNeeded)
01250             {
01251                 *pcbStructInfo = bytesNeeded;
01252                 SetLastError(ERROR_MORE_DATA);
01253                 ret = FALSE;
01254             }
01255             else
01256             {
01257                 PSPC_LINK link = pvStructInfo;
01258                 DWORD i;
01259 
01260                 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
01261                 for (i = 0; i < dataLen; i++)
01262                     link->u.pwszUrl[i] =
01263                      *(pbEncoded + 1 + lenBytes + i);
01264                 link->u.pwszUrl[i] = '\0';
01265                 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
01266             }
01267             break;
01268         case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
01269         {
01270             CRYPT_DATA_BLOB classId;
01271             DWORD size = sizeof(classId);
01272 
01273             if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
01274              pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
01275              CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
01276             {
01277                 if (classId.cbData != sizeof(SPC_UUID))
01278                 {
01279                     SetLastError(CRYPT_E_BAD_ENCODE);
01280                     ret = FALSE;
01281                 }
01282                 else
01283                 {
01284                     CRYPT_DATA_BLOB data;
01285 
01286                     /* The tag length for the classId must be 1 since the
01287                      * length is correct.
01288                      */
01289                     size = sizeof(data);
01290                     if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
01291                      pbEncoded + 3 + lenBytes + classId.cbData,
01292                      cbEncoded - 3 - lenBytes - classId.cbData,
01293                      CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
01294                     {
01295                         bytesNeeded += data.cbData;
01296                         if (!pvStructInfo)
01297                             *pcbStructInfo = bytesNeeded;
01298                         else if (*pcbStructInfo < bytesNeeded)
01299                         {
01300                             *pcbStructInfo = bytesNeeded;
01301                             SetLastError(ERROR_MORE_DATA);
01302                             ret = FALSE;
01303                         }
01304                         else
01305                         {
01306                             PSPC_LINK link = pvStructInfo;
01307 
01308                             link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
01309                             /* pwszFile pointer was set by caller, copy it
01310                              * before overwriting it
01311                              */
01312                             link->u.Moniker.SerializedData.pbData =
01313                              (BYTE *)link->u.pwszFile;
01314                             memcpy(link->u.Moniker.ClassId, classId.pbData,
01315                              classId.cbData);
01316                             memcpy(link->u.Moniker.SerializedData.pbData,
01317                              data.pbData, data.cbData);
01318                             link->u.Moniker.SerializedData.cbData = data.cbData;
01319                         }
01320                     }
01321                 }
01322             }
01323             break;
01324         }
01325         case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
01326             if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
01327                 SetLastError(CRYPT_E_ASN1_BADTAG);
01328             else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
01329              &realDataLen)))
01330             {
01331                 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
01332 
01333                 bytesNeeded += realDataLen + sizeof(WCHAR);
01334                 if (!pvStructInfo)
01335                     *pcbStructInfo = bytesNeeded;
01336                 else if (*pcbStructInfo < bytesNeeded)
01337                 {
01338                     *pcbStructInfo = bytesNeeded;
01339                     SetLastError(ERROR_MORE_DATA);
01340                     ret = FALSE;
01341                 }
01342                 else
01343                 {
01344                     PSPC_LINK link = pvStructInfo;
01345                     DWORD i;
01346                     const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
01347 
01348                     link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
01349                     for (i = 0; i < dataLen / sizeof(WCHAR); i++)
01350                         link->u.pwszFile[i] =
01351                          hton16(*(const WORD *)(ptr + i * sizeof(WCHAR)));
01352                     link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
01353                     TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
01354                 }
01355             }
01356             else
01357             {
01358                 bytesNeeded += sizeof(WCHAR);
01359                 if (!pvStructInfo)
01360                     *pcbStructInfo = bytesNeeded;
01361                 else if (*pcbStructInfo < bytesNeeded)
01362                 {
01363                     *pcbStructInfo = bytesNeeded;
01364                     SetLastError(ERROR_MORE_DATA);
01365                     ret = FALSE;
01366                 }
01367                 else
01368                 {
01369                     PSPC_LINK link = pvStructInfo;
01370 
01371                     link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
01372                     link->u.pwszFile[0] = '\0';
01373                     ret = TRUE;
01374                 }
01375             }
01376             break;
01377         default:
01378             SetLastError(CRYPT_E_ASN1_BADTAG);
01379         }
01380     }
01381     TRACE("returning %d\n", ret);
01382     return ret;
01383 }
01384 
01385 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
01386  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01387  void *pvStructInfo, DWORD *pcbStructInfo)
01388 {
01389     BOOL ret = FALSE;
01390 
01391     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01392      pvStructInfo, *pcbStructInfo);
01393 
01394     __TRY
01395     {
01396         DWORD bytesNeeded;
01397 
01398         ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
01399          lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
01400         if (ret)
01401         {
01402             if (!pvStructInfo)
01403                 *pcbStructInfo = bytesNeeded;
01404             else if (*pcbStructInfo < bytesNeeded)
01405             {
01406                 *pcbStructInfo = bytesNeeded;
01407                 SetLastError(ERROR_MORE_DATA);
01408                 ret = FALSE;
01409             }
01410             else
01411             {
01412                 SPC_LINK *link = pvStructInfo;
01413 
01414                 link->u.pwszFile =
01415                  (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
01416                 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
01417                  lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
01418                  pcbStructInfo);
01419             }
01420         }
01421     }
01422     __EXCEPT_PAGE_FAULT
01423     {
01424         SetLastError(STATUS_ACCESS_VIOLATION);
01425     }
01426     __ENDTRY
01427     TRACE("returning %d\n", ret);
01428     return ret;
01429 }
01430 
01431 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
01432  DWORD, DWORD, void *, DWORD *);
01433 
01434 /* tag:
01435  *     The expected tag of the item.  If tag is 0, decodeFunc is called
01436  *     regardless of the tag value seen.
01437  * offset:
01438  *     A sequence is decoded into a struct.  The offset member is the
01439  *     offset of this item within that struct.
01440  * decodeFunc:
01441  *     The decoder function to use.  If this is NULL, then the member isn't
01442  *     decoded, but minSize space is reserved for it.
01443  * minSize:
01444  *     The minimum amount of space occupied after decoding.  You must set this.
01445  * optional:
01446  *     If true, and the tag doesn't match the expected tag for this item,
01447  *     or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
01448  *     filled with 0 for this member.
01449  * hasPointer, pointerOffset:
01450  *     If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
01451  *     the offset within the struct of the data pointer (or to the
01452  *     first data pointer, if more than one exist).
01453  * size:
01454  *     Used by CRYPT_AsnDecodeSequence, not for your use.
01455  */
01456 struct AsnDecodeSequenceItem
01457 {
01458     BYTE                  tag;
01459     DWORD                 offset;
01460     CryptDecodeObjectFunc decodeFunc;
01461     DWORD                 minSize;
01462     BOOL                  optional;
01463     BOOL                  hasPointer;
01464     DWORD                 pointerOffset;
01465     DWORD                 size;
01466 };
01467 
01468 /* Align up to a DWORD_PTR boundary
01469  */
01470 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1))
01471 
01472 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
01473 #define MEMBERSIZE(s, member, nextmember) \
01474     (offsetof(s, nextmember) - offsetof(s, member))
01475 
01476 
01477 /* Decodes the items in a sequence, where the items are described in items,
01478  * the encoded data are in pbEncoded with length cbEncoded.  Decodes into
01479  * pvStructInfo.  nextData is a pointer to the memory location at which the
01480  * first decoded item with a dynamic pointer should point.
01481  * Upon decoding, *cbDecoded is the total number of bytes decoded.
01482  */
01483 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
01484  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
01485  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
01486  DWORD *cbDecoded)
01487 {
01488     BOOL ret;
01489     DWORD i, decoded = 0;
01490     const BYTE *ptr = pbEncoded;
01491 
01492     TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
01493      cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
01494 
01495     for (i = 0, ret = TRUE; ret && i < cItem; i++)
01496     {
01497         if (cbEncoded - (ptr - pbEncoded) != 0)
01498         {
01499             DWORD nextItemLen;
01500 
01501             if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
01502              &nextItemLen)))
01503             {
01504                 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
01505 
01506                 if (ptr[0] == items[i].tag || !items[i].tag)
01507                 {
01508                     if (nextData && pvStructInfo && items[i].hasPointer)
01509                     {
01510                         TRACE("Setting next pointer to %p\n",
01511                          nextData);
01512                         *(BYTE **)((BYTE *)pvStructInfo +
01513                          items[i].pointerOffset) = nextData;
01514                     }
01515                     if (items[i].decodeFunc)
01516                     {
01517                         if (pvStructInfo)
01518                             TRACE("decoding item %d\n", i);
01519                         else
01520                             TRACE("sizing item %d\n", i);
01521                         ret = items[i].decodeFunc(dwCertEncodingType,
01522                          NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
01523                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
01524                          pvStructInfo ?  (BYTE *)pvStructInfo + items[i].offset
01525                          : NULL, &items[i].size);
01526                         if (ret)
01527                         {
01528                             if (items[i].size < items[i].minSize)
01529                                 items[i].size = items[i].minSize;
01530                             else if (items[i].size > items[i].minSize)
01531                             {
01532                                 /* Account for alignment padding */
01533                                 items[i].size = ALIGN_DWORD_PTR(items[i].size);
01534                             }
01535                             TRACE("item %d size: %d\n", i, items[i].size);
01536                             if (nextData && items[i].hasPointer &&
01537                              items[i].size > items[i].minSize)
01538                                 nextData += items[i].size - items[i].minSize;
01539                             ptr += 1 + nextItemLenBytes + nextItemLen;
01540                             decoded += 1 + nextItemLenBytes + nextItemLen;
01541                             TRACE("item %d: decoded %d bytes\n", i,
01542                              1 + nextItemLenBytes + nextItemLen);
01543                         }
01544                         else if (items[i].optional &&
01545                          GetLastError() == CRYPT_E_ASN1_BADTAG)
01546                         {
01547                             TRACE("skipping optional item %d\n", i);
01548                             items[i].size = items[i].minSize;
01549                             SetLastError(NOERROR);
01550                             ret = TRUE;
01551                         }
01552                         else
01553                             TRACE("item %d failed: %08x\n", i,
01554                              GetLastError());
01555                     }
01556                     else
01557                     {
01558                         TRACE("item %d: decoded %d bytes\n", i,
01559                          1 + nextItemLenBytes + nextItemLen);
01560                         ptr += 1 + nextItemLenBytes + nextItemLen;
01561                         decoded += 1 + nextItemLenBytes + nextItemLen;
01562                         items[i].size = items[i].minSize;
01563                     }
01564                 }
01565                 else if (items[i].optional)
01566                 {
01567                     TRACE("skipping optional item %d\n", i);
01568                     items[i].size = items[i].minSize;
01569                 }
01570                 else
01571                 {
01572                     TRACE("item %d: tag %02x doesn't match expected %02x\n",
01573                      i, ptr[0], items[i].tag);
01574                     SetLastError(CRYPT_E_ASN1_BADTAG);
01575                     ret = FALSE;
01576                 }
01577             }
01578         }
01579         else if (items[i].optional)
01580         {
01581             TRACE("missing optional item %d, skipping\n", i);
01582             items[i].size = items[i].minSize;
01583         }
01584         else
01585         {
01586             TRACE("not enough bytes for item %d, failing\n", i);
01587             SetLastError(CRYPT_E_ASN1_CORRUPT);
01588             ret = FALSE;
01589         }
01590     }
01591     if (ret)
01592         *cbDecoded = decoded;
01593     TRACE("returning %d\n", ret);
01594     return ret;
01595 }
01596 
01597 /* This decodes an arbitrary sequence into a contiguous block of memory
01598  * (basically, a struct.)  Each element being decoded is described by a struct
01599  * AsnDecodeSequenceItem, see above.
01600  * startingPointer is an optional pointer to the first place where dynamic
01601  * data will be stored.  If you know the starting offset, you may pass it
01602  * here.  Otherwise, pass NULL, and one will be inferred from the items.
01603  */
01604 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
01605  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
01606  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
01607  void *startingPointer)
01608 {
01609     BOOL ret;
01610 
01611     TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
01612      cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
01613 
01614     if (pbEncoded[0] == ASN_SEQUENCE)
01615     {
01616         DWORD dataLen;
01617 
01618         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01619         {
01620             DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
01621             const BYTE *ptr = pbEncoded + 1 + lenBytes;
01622 
01623             cbEncoded -= 1 + lenBytes;
01624             if (cbEncoded < dataLen)
01625             {
01626                 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
01627                  cbEncoded);
01628                 SetLastError(CRYPT_E_ASN1_CORRUPT);
01629                 ret = FALSE;
01630             }
01631             else
01632                 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
01633                  cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
01634             if (ret && cbDecoded != dataLen)
01635             {
01636                 TRACE("expected %d decoded, got %d, failing\n", dataLen,
01637                  cbDecoded);
01638                 SetLastError(CRYPT_E_ASN1_CORRUPT);
01639                 ret = FALSE;
01640             }
01641             if (ret)
01642             {
01643                 DWORD i, bytesNeeded = 0, structSize = 0;
01644 
01645                 for (i = 0; i < cItem; i++)
01646                 {
01647                     bytesNeeded += items[i].size;
01648                     structSize += items[i].minSize;
01649                 }
01650                 if (!pvStructInfo)
01651                     *pcbStructInfo = bytesNeeded;
01652                 else if (*pcbStructInfo < bytesNeeded)
01653                 {
01654                     SetLastError(ERROR_MORE_DATA);
01655                     *pcbStructInfo = bytesNeeded;
01656                     ret = FALSE;
01657                 }
01658                 else
01659                 {
01660                     BYTE *nextData;
01661 
01662                     *pcbStructInfo = bytesNeeded;
01663                     if (startingPointer)
01664                         nextData = startingPointer;
01665                     else
01666                         nextData = (BYTE *)pvStructInfo + structSize;
01667                     memset(pvStructInfo, 0, structSize);
01668                     ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
01669                      ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
01670                      &cbDecoded);
01671                 }
01672             }
01673         }
01674     }
01675     else
01676     {
01677         SetLastError(CRYPT_E_ASN1_BADTAG);
01678         ret = FALSE;
01679     }
01680     TRACE("returning %d (%08x)\n", ret, GetLastError());
01681     return ret;
01682 }
01683 
01684 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
01685  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01686  void *pvStructInfo, DWORD *pcbStructInfo)
01687 {
01688     BOOL ret;
01689 
01690     TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
01691      pvStructInfo, *pcbStructInfo);
01692 
01693     if (pbEncoded[0] == ASN_BITSTRING)
01694     {
01695         DWORD bytesNeeded, dataLen;
01696 
01697         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01698         {
01699             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
01700                 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
01701             else
01702                 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
01703             if (!pvStructInfo)
01704                 *pcbStructInfo = bytesNeeded;
01705             else if (*pcbStructInfo < bytesNeeded)
01706             {
01707                 *pcbStructInfo = bytesNeeded;
01708                 SetLastError(ERROR_MORE_DATA);
01709                 ret = FALSE;
01710             }
01711             else
01712             {
01713                 CRYPT_BIT_BLOB *blob;
01714 
01715                 blob = pvStructInfo;
01716                 blob->cbData = dataLen - 1;
01717                 blob->cUnusedBits = *(pbEncoded + 1 +
01718                  GET_LEN_BYTES(pbEncoded[1]));
01719                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
01720                 {
01721                     blob->pbData = (BYTE *)pbEncoded + 2 +
01722                      GET_LEN_BYTES(pbEncoded[1]);
01723                 }
01724                 else
01725                 {
01726                     assert(blob->pbData);
01727                     if (blob->cbData)
01728                     {
01729                         BYTE mask = 0xff << blob->cUnusedBits;
01730 
01731                         memcpy(blob->pbData, pbEncoded + 2 +
01732                          GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
01733                         blob->pbData[blob->cbData - 1] &= mask;
01734                     }
01735                 }
01736             }
01737         }
01738     }
01739     else
01740     {
01741         SetLastError(CRYPT_E_ASN1_BADTAG);
01742         ret = FALSE;
01743     }
01744     TRACE("returning %d (%08x)\n", ret, GetLastError());
01745     return ret;
01746 }
01747 
01748 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
01749  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01750  void *pvStructInfo, DWORD *pcbStructInfo)
01751 {
01752     BOOL ret = FALSE;
01753     DWORD dataLen;
01754 
01755     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01756     {
01757         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01758         DWORD size;
01759         SPC_LINK **pLink = pvStructInfo;
01760 
01761         ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
01762          pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
01763         if (ret)
01764         {
01765             if (!pvStructInfo)
01766                 *pcbStructInfo = size + sizeof(PSPC_LINK);
01767             else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
01768             {
01769                 *pcbStructInfo = size + sizeof(PSPC_LINK);
01770                 SetLastError(ERROR_MORE_DATA);
01771                 ret = FALSE;
01772             }
01773             else
01774             {
01775                 *pcbStructInfo = size + sizeof(PSPC_LINK);
01776                 /* Set imageData's pointer if necessary */
01777                 if (size > sizeof(SPC_LINK))
01778                 {
01779                     (*pLink)->u.pwszUrl =
01780                      (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
01781                 }
01782                 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
01783                  lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
01784                  *pLink, pcbStructInfo);
01785             }
01786         }
01787     }
01788     return ret;
01789 }
01790 
01791 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
01792  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01793  void *pvStructInfo, DWORD *pcbStructInfo)
01794 {
01795     BOOL ret = FALSE;
01796 
01797     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01798      pvStructInfo, *pcbStructInfo);
01799 
01800     __TRY
01801     {
01802         struct AsnDecodeSequenceItem items[] = {
01803          { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
01804            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
01805            offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
01806          { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
01807            CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
01808            offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
01809         };
01810 
01811         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
01812          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
01813          pvStructInfo, pcbStructInfo, NULL);
01814     }
01815     __EXCEPT_PAGE_FAULT
01816     {
01817         SetLastError(STATUS_ACCESS_VIOLATION);
01818     }
01819     __ENDTRY
01820     TRACE("returning %d\n", ret);
01821     return ret;
01822 }
01823 
01824 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
01825  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01826  void *pvStructInfo, DWORD *pcbStructInfo)
01827 {
01828     BOOL ret = TRUE;
01829     DWORD dataLen;
01830 
01831     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01832      pvStructInfo, *pcbStructInfo);
01833 
01834     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
01835     {
01836         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
01837         DWORD bytesNeeded = sizeof(LPSTR);
01838 
01839         if (dataLen)
01840         {
01841             /* The largest possible string for the first two components
01842              * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
01843              */
01844             char firstTwo[6];
01845             const BYTE *ptr;
01846 
01847             snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
01848              pbEncoded[1 + lenBytes] / 40,
01849              pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
01850              * 40);
01851             bytesNeeded += strlen(firstTwo) + 1;
01852             for (ptr = pbEncoded + 2 + lenBytes; ret &&
01853              ptr - pbEncoded - 1 - lenBytes < dataLen; )
01854             {
01855                 /* large enough for ".4000000" */
01856                 char str[9];
01857                 int val = 0;
01858 
01859                 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
01860                  (*ptr & 0x80))
01861                 {
01862                     val <<= 7;
01863                     val |= *ptr & 0x7f;
01864                     ptr++;
01865                 }
01866                 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
01867                  (*ptr & 0x80))
01868                 {
01869                     SetLastError(CRYPT_E_ASN1_CORRUPT);
01870                     ret = FALSE;
01871                 }
01872                 else
01873                 {
01874                     val <<= 7;
01875                     val |= *ptr++;
01876                     snprintf(str, sizeof(str), ".%d", val);
01877                     bytesNeeded += strlen(str);
01878                 }
01879             }
01880         }
01881         if (!pvStructInfo)
01882             *pcbStructInfo = bytesNeeded;
01883         else if (*pcbStructInfo < bytesNeeded)
01884         {
01885             *pcbStructInfo = bytesNeeded;
01886             SetLastError(ERROR_MORE_DATA);
01887             ret = FALSE;
01888         }
01889         else
01890         {
01891             if (dataLen)
01892             {
01893                 const BYTE *ptr;
01894                 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
01895 
01896                 *pszObjId = 0;
01897                 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
01898                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
01899                  40) * 40);
01900                 pszObjId += strlen(pszObjId);
01901                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
01902                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
01903                 {
01904                     int val = 0;
01905 
01906                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
01907                      (*ptr & 0x80))
01908                     {
01909                         val <<= 7;
01910                         val |= *ptr & 0x7f;
01911                         ptr++;
01912                     }
01913                     val <<= 7;
01914                     val |= *ptr++;
01915                     sprintf(pszObjId, ".%d", val);
01916                     pszObjId += strlen(pszObjId);
01917                 }
01918             }
01919             else
01920                 *(LPSTR *)pvStructInfo = NULL;
01921             *pcbStructInfo = bytesNeeded;
01922         }
01923     }
01924     return ret;
01925 }
01926 
01927 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
01928  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01929  void *pvStructInfo, DWORD *pcbStructInfo)
01930 {
01931     BOOL ret = FALSE;
01932 
01933     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01934      pvStructInfo, *pcbStructInfo);
01935 
01936     if (!cbEncoded)
01937         SetLastError(CRYPT_E_ASN1_CORRUPT);
01938     else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
01939         ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
01940          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
01941     else
01942         SetLastError(CRYPT_E_ASN1_BADTAG);
01943     return ret;
01944 }
01945 
01946 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
01947  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01948  void *pvStructInfo, DWORD *pcbStructInfo)
01949 {
01950     BOOL ret = TRUE;
01951     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
01952 
01953     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01954      pvStructInfo, *pcbStructInfo);
01955 
01956     if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
01957         bytesNeeded += cbEncoded;
01958     if (!pvStructInfo)
01959         *pcbStructInfo = bytesNeeded;
01960     else if (*pcbStructInfo < bytesNeeded)
01961     {
01962         SetLastError(ERROR_MORE_DATA);
01963         *pcbStructInfo = bytesNeeded;
01964         ret = FALSE;
01965     }
01966     else
01967     {
01968         PCRYPT_OBJID_BLOB blob = pvStructInfo;
01969 
01970         *pcbStructInfo = bytesNeeded;
01971         blob->cbData = cbEncoded;
01972         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
01973             blob->pbData = (LPBYTE)pbEncoded;
01974         else
01975         {
01976             assert(blob->pbData);
01977             memcpy(blob->pbData, pbEncoded, blob->cbData);
01978         }
01979     }
01980     return ret;
01981 }
01982 
01983 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
01984  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
01985  void *pvStructInfo, DWORD *pcbStructInfo)
01986 {
01987     CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo;
01988     struct AsnDecodeSequenceItem items[] = {
01989      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
01990        CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
01991        offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
01992      { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
01993        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
01994        offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
01995     };
01996 
01997     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
01998      pvStructInfo, *pcbStructInfo);
01999 
02000     return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02001      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02002      pvStructInfo, pcbStructInfo,
02003      typeValue ? typeValue->pszObjId : NULL);
02004 }
02005 
02006 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
02007  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02008  void *pvStructInfo, DWORD *pcbStructInfo)
02009 {
02010     CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
02011     BOOL ret = TRUE;
02012     struct AsnDecodeSequenceItem items[] = {
02013      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
02014        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
02015        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
02016      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
02017        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
02018        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
02019     };
02020 
02021     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02022      pvStructInfo, *pcbStructInfo);
02023 
02024     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02025      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02026      pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
02027     if (ret && pvStructInfo)
02028     {
02029         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
02030          debugstr_a(algo->pszObjId));
02031     }
02032     return ret;
02033 }
02034 
02035 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
02036  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02037  void *pvStructInfo, DWORD *pcbStructInfo)
02038 {
02039     struct SPCDigest *digest = pvStructInfo;
02040     struct AsnDecodeSequenceItem items[] = {
02041      { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
02042        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
02043        FALSE, TRUE,
02044        offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
02045      { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
02046        CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
02047        FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
02048     };
02049 
02050     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02051      pvStructInfo, *pcbStructInfo);
02052 
02053     return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02054      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02055      pvStructInfo, pcbStructInfo,
02056      digest ? digest->DigestAlgorithm.pszObjId : NULL);
02057 }
02058 
02059 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
02060  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02061  void *pvStructInfo, DWORD *pcbStructInfo)
02062 {
02063     BOOL ret = FALSE;
02064 
02065     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02066      pvStructInfo, *pcbStructInfo);
02067 
02068     __TRY
02069     {
02070         struct AsnDecodeSequenceItem items[] = {
02071          { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
02072            CRYPT_AsnDecodeAttributeTypeValue,
02073            sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
02074            offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
02075          { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
02076            CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
02077            FALSE, TRUE,
02078            offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
02079         };
02080 
02081         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02082          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02083          pvStructInfo, pcbStructInfo, NULL);
02084     }
02085     __EXCEPT_PAGE_FAULT
02086     {
02087         SetLastError(STATUS_ACCESS_VIOLATION);
02088     }
02089     __ENDTRY
02090     TRACE("returning %d\n", ret);
02091     return ret;
02092 }
02093 
02094 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
02095  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02096  void *pvStructInfo, DWORD *pcbStructInfo)
02097 {
02098     BOOL ret;
02099     DWORD bytesNeeded, dataLen;
02100 
02101     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
02102     {
02103         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02104 
02105         bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
02106         if (!pvStructInfo)
02107             *pcbStructInfo = bytesNeeded;
02108         else if (*pcbStructInfo < bytesNeeded)
02109         {
02110             *pcbStructInfo = bytesNeeded;
02111             SetLastError(ERROR_MORE_DATA);
02112             ret = FALSE;
02113         }
02114         else
02115         {
02116             LPWSTR str;
02117             DWORD i;
02118 
02119             *pcbStructInfo = bytesNeeded;
02120             assert(pvStructInfo);
02121             str = *(LPWSTR *)pvStructInfo;
02122             for (i = 0; i < dataLen / 2; i++)
02123                 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
02124                  pbEncoded[1 + lenBytes + 2 * i + 1];
02125             /* Decoded string is always NULL-terminated */
02126             str[i] = '\0';
02127         }
02128     }
02129     return ret;
02130 }
02131 
02132 static BOOL WINAPI CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType,
02133  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02134  void *pvStructInfo, DWORD *pcbStructInfo)
02135 {
02136     BOOL ret = FALSE;
02137     DWORD dataLen;
02138 
02139     TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
02140      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
02141 
02142     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
02143     {
02144         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02145 
02146         ret = CRYPT_AsnDecodeBMPString(dwCertEncodingType, lpszStructType,
02147          pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo,
02148          pcbStructInfo);
02149     }
02150     return ret;
02151 }
02152 
02153 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
02154  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02155  void *pvStructInfo, DWORD *pcbStructInfo)
02156 {
02157     BOOL ret = FALSE;
02158 
02159     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02160      pvStructInfo, *pcbStructInfo);
02161 
02162     __TRY
02163     {
02164         struct AsnDecodeSequenceItem items[] = {
02165          { ASN_CONSTRUCTOR | ASN_CONTEXT,
02166            offsetof(SPC_SP_OPUS_INFO, pwszProgramName),
02167            CRYPT_AsnDecodeProgramName, sizeof(LPCWSTR), TRUE, TRUE,
02168            offsetof(SPC_SP_OPUS_INFO, pwszProgramName), 0 },
02169          { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
02170            offsetof(SPC_SP_OPUS_INFO, pMoreInfo),
02171            CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
02172            offsetof(SPC_SP_OPUS_INFO, pMoreInfo), 0 },
02173          { ASN_CONSTRUCTOR | ASN_CONTEXT | 2,
02174            offsetof(SPC_SP_OPUS_INFO, pPublisherInfo),
02175            CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
02176            offsetof(SPC_SP_OPUS_INFO, pPublisherInfo), 0 },
02177         };
02178 
02179         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02180          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02181          pvStructInfo, pcbStructInfo, NULL);
02182     }
02183     __EXCEPT_PAGE_FAULT
02184     {
02185         SetLastError(STATUS_ACCESS_VIOLATION);
02186     }
02187     __ENDTRY
02188     TRACE("returning %d\n", ret);
02189     return ret;
02190 }
02191 
02192 /* Ignores tag.  Only allows integers 4 bytes or smaller in size. */
02193 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
02194  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02195  void *pvStructInfo, DWORD *pcbStructInfo)
02196 {
02197     BOOL ret;
02198     DWORD dataLen;
02199 
02200     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
02201     {
02202         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
02203 
02204         if (dataLen > sizeof(int))
02205         {
02206             SetLastError(CRYPT_E_ASN1_LARGE);
02207             ret = FALSE;
02208         }
02209         else if (!pvStructInfo)
02210             *pcbStructInfo = sizeof(int);
02211         else if (*pcbStructInfo < sizeof(int))
02212         {
02213             *pcbStructInfo = sizeof(int);
02214             SetLastError(ERROR_MORE_DATA);
02215             ret = FALSE;
02216         }
02217         else
02218         {
02219             int val;
02220             DWORD i;
02221 
02222             *pcbStructInfo = sizeof(int);
02223             if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
02224             {
02225                 /* initialize to a negative value to sign-extend */
02226                 val = -1;
02227             }
02228             else
02229                 val = 0;
02230             for (i = 0; i < dataLen; i++)
02231             {
02232                 val <<= 8;
02233                 val |= pbEncoded[1 + lenBytes + i];
02234             }
02235             memcpy(pvStructInfo, &val, sizeof(int));
02236         }
02237     }
02238     return ret;
02239 }
02240 
02241 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
02242  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02243  void *pvStructInfo, DWORD *pcbStructInfo)
02244 {
02245     BOOL ret = FALSE;
02246 
02247     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02248      pvStructInfo, *pcbStructInfo);
02249 
02250     __TRY
02251     {
02252         struct AsnDecodeSequenceItem items[] = {
02253          { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
02254            CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
02255            offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
02256          { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
02257            CRYPT_AsnDecodeInt, FINALMEMBERSIZE(CAT_MEMBERINFO, dwCertVersion),
02258            FALSE, FALSE, 0, 0 },
02259         };
02260 
02261         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02262          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02263          pvStructInfo, pcbStructInfo, NULL);
02264     }
02265     __EXCEPT_PAGE_FAULT
02266     {
02267         SetLastError(STATUS_ACCESS_VIOLATION);
02268     }
02269     __ENDTRY
02270     TRACE("returning %d\n", ret);
02271     return ret;
02272 }
02273 
02274 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
02275  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02276  void *pvStructInfo, DWORD *pcbStructInfo)
02277 {
02278     BOOL ret = FALSE;
02279 
02280     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
02281      pvStructInfo, *pcbStructInfo);
02282 
02283     __TRY
02284     {
02285         struct AsnDecodeSequenceItem items[] = {
02286          { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
02287            CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
02288            offsetof(CAT_NAMEVALUE, pwszTag), 0 },
02289          { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
02290            CRYPT_AsnDecodeInt, MEMBERSIZE(CAT_NAMEVALUE, fdwFlags, Value),
02291            FALSE, FALSE, 0, 0 },
02292          { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
02293            CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
02294            offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
02295         };
02296 
02297         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02298          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02299          pvStructInfo, pcbStructInfo, NULL);
02300     }
02301     __EXCEPT_PAGE_FAULT
02302     {
02303         SetLastError(STATUS_ACCESS_VIOLATION);
02304     }
02305     __ENDTRY
02306     TRACE("returning %d\n", ret);
02307     return ret;
02308 }
02309 
02310 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
02311  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02312  void *pvStructInfo, DWORD *pcbStructInfo)
02313 {
02314     BOOL ret;
02315 
02316     if (cbEncoded < 3)
02317     {
02318         SetLastError(CRYPT_E_ASN1_CORRUPT);
02319         return FALSE;
02320     }
02321     if (GET_LEN_BYTES(pbEncoded[1]) > 1)
02322     {
02323         SetLastError(CRYPT_E_ASN1_CORRUPT);
02324         return FALSE;
02325     }
02326     if (pbEncoded[1] > 1)
02327     {
02328         SetLastError(CRYPT_E_ASN1_CORRUPT);
02329         return FALSE;
02330     }
02331     if (!pvStructInfo)
02332     {
02333         *pcbStructInfo = sizeof(BOOL);
02334         ret = TRUE;
02335     }
02336     else if (*pcbStructInfo < sizeof(BOOL))
02337     {
02338         *pcbStructInfo = sizeof(BOOL);
02339         SetLastError(ERROR_MORE_DATA);
02340         ret = FALSE;
02341     }
02342     else
02343     {
02344         *pcbStructInfo = sizeof(BOOL);
02345         *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
02346         ret = TRUE;
02347     }
02348     TRACE("returning %d (%08x)\n", ret, GetLastError());
02349     return ret;
02350 }
02351 
02352 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType,
02353  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
02354  void *pvStructInfo, DWORD *pcbStructInfo)
02355 {
02356     BOOL ret = FALSE;
02357 
02358     TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
02359      pvStructInfo, *pcbStructInfo);
02360 
02361     __TRY
02362     {
02363         struct AsnDecodeSequenceItem items[] = {
02364          { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable),
02365            CRYPT_AsnDecodeBool, MEMBERSIZE(SPC_FINANCIAL_CRITERIA,
02366            fFinancialInfoAvailable, fMeetsCriteria), FALSE, FALSE, 0, 0 },
02367          { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria),
02368            CRYPT_AsnDecodeBool, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA,
02369            fMeetsCriteria), FALSE, FALSE, 0, 0 },
02370         };
02371 
02372         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
02373          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
02374          pvStructInfo, pcbStructInfo, NULL);
02375     }
02376     __EXCEPT_PAGE_FAULT
02377     {
02378         SetLastError(STATUS_ACCESS_VIOLATION);
02379     }
02380     __ENDTRY
02381     TRACE("returning %d\n", ret);
02382     return ret;
02383 }

Generated on Mon May 28 2012 04:26:34 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.