Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenasn.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
1.7.6.1
|