Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenobject.c
Go to the documentation of this file.
00001 /* 00002 * crypt32 Crypt*Object functions 00003 * 00004 * Copyright 2007 Juan Lang 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 #include <stdarg.h> 00021 #define NONAMELESSUNION 00022 #include "windef.h" 00023 #include "winbase.h" 00024 #include "wincrypt.h" 00025 #include "mssip.h" 00026 #include "winuser.h" 00027 #include "wintrust.h" 00028 #include "crypt32_private.h" 00029 #include "cryptres.h" 00030 #include "wine/unicode.h" 00031 #include "wine/debug.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00034 00035 static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob) 00036 { 00037 BOOL ret = FALSE; 00038 HANDLE file; 00039 00040 TRACE("%s\n", debugstr_w(fileName)); 00041 00042 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, 00043 OPEN_EXISTING, 0, NULL); 00044 if (file != INVALID_HANDLE_VALUE) 00045 { 00046 ret = TRUE; 00047 blob->cbData = GetFileSize(file, NULL); 00048 if (blob->cbData) 00049 { 00050 blob->pbData = CryptMemAlloc(blob->cbData); 00051 if (blob->pbData) 00052 { 00053 DWORD read; 00054 00055 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL); 00056 } 00057 } 00058 CloseHandle(file); 00059 } 00060 TRACE("returning %d\n", ret); 00061 return ret; 00062 } 00063 00064 static BOOL CRYPT_QueryContextBlob(const CERT_BLOB *blob, 00065 DWORD dwExpectedContentTypeFlags, HCERTSTORE store, 00066 DWORD *contentType, const void **ppvContext) 00067 { 00068 BOOL ret = FALSE; 00069 00070 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) 00071 { 00072 ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING, 00073 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); 00074 if (ret && contentType) 00075 *contentType = CERT_QUERY_CONTENT_CERT; 00076 } 00077 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL)) 00078 { 00079 ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING, 00080 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); 00081 if (ret && contentType) 00082 *contentType = CERT_QUERY_CONTENT_CRL; 00083 } 00084 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL)) 00085 { 00086 ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING, 00087 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); 00088 if (ret && contentType) 00089 *contentType = CERT_QUERY_CONTENT_CTL; 00090 } 00091 return ret; 00092 } 00093 00094 static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject, 00095 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, 00096 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType, 00097 HCERTSTORE *phCertStore, const void **ppvContext) 00098 { 00099 CERT_BLOB fileBlob; 00100 const CERT_BLOB *blob; 00101 HCERTSTORE store; 00102 BOOL ret; 00103 DWORD formatType = 0; 00104 00105 switch (dwObjectType) 00106 { 00107 case CERT_QUERY_OBJECT_FILE: 00108 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so 00109 * just read the file directly 00110 */ 00111 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob); 00112 blob = &fileBlob; 00113 break; 00114 case CERT_QUERY_OBJECT_BLOB: 00115 blob = pvObject; 00116 ret = TRUE; 00117 break; 00118 default: 00119 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ 00120 ret = FALSE; 00121 } 00122 if (!ret) 00123 return FALSE; 00124 00125 ret = FALSE; 00126 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 00127 CERT_STORE_CREATE_NEW_FLAG, NULL); 00128 if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY) 00129 { 00130 ret = CRYPT_QueryContextBlob(blob, dwExpectedContentTypeFlags, store, 00131 pdwContentType, ppvContext); 00132 if (ret) 00133 formatType = CERT_QUERY_FORMAT_BINARY; 00134 } 00135 if (!ret && 00136 (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED)) 00137 { 00138 CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData }; 00139 CRYPT_DATA_BLOB decoded; 00140 00141 while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1]) 00142 trimmed.cbData--; 00143 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData, 00144 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL); 00145 if (ret) 00146 { 00147 decoded.pbData = CryptMemAlloc(decoded.cbData); 00148 if (decoded.pbData) 00149 { 00150 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, 00151 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData, 00152 &decoded.cbData, NULL, NULL); 00153 if (ret) 00154 { 00155 ret = CRYPT_QueryContextBlob(&decoded, 00156 dwExpectedContentTypeFlags, store, pdwContentType, 00157 ppvContext); 00158 if (ret) 00159 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED; 00160 } 00161 CryptMemFree(decoded.pbData); 00162 } 00163 else 00164 ret = FALSE; 00165 } 00166 } 00167 if (ret) 00168 { 00169 if (pdwMsgAndCertEncodingType) 00170 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; 00171 if (pdwFormatType) 00172 *pdwFormatType = formatType; 00173 if (phCertStore) 00174 *phCertStore = CertDuplicateStore(store); 00175 } 00176 CertCloseStore(store, 0); 00177 if (blob == &fileBlob) 00178 CryptMemFree(blob->pbData); 00179 TRACE("returning %d\n", ret); 00180 return ret; 00181 } 00182 00183 static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType, 00184 const void *pvObject, DWORD dwExpectedContentTypeFlags, 00185 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, 00186 HCERTSTORE *phCertStore, const void **ppvContext) 00187 { 00188 CERT_BLOB fileBlob; 00189 const CERT_BLOB *blob; 00190 const WINE_CONTEXT_INTERFACE *contextInterface = NULL; 00191 const void *context; 00192 DWORD contextType; 00193 BOOL ret; 00194 00195 switch (dwObjectType) 00196 { 00197 case CERT_QUERY_OBJECT_FILE: 00198 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so 00199 * just read the file directly 00200 */ 00201 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob); 00202 blob = &fileBlob; 00203 break; 00204 case CERT_QUERY_OBJECT_BLOB: 00205 blob = pvObject; 00206 ret = TRUE; 00207 break; 00208 default: 00209 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ 00210 ret = FALSE; 00211 } 00212 if (!ret) 00213 return FALSE; 00214 00215 ret = FALSE; 00216 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData, 00217 CERT_STORE_ALL_CONTEXT_FLAG, &contextType); 00218 if (context) 00219 { 00220 DWORD contentType, certStoreOffset; 00221 00222 ret = TRUE; 00223 switch (contextType) 00224 { 00225 case CERT_STORE_CERTIFICATE_CONTEXT: 00226 contextInterface = pCertInterface; 00227 contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT; 00228 certStoreOffset = offsetof(CERT_CONTEXT, hCertStore); 00229 if (!(dwExpectedContentTypeFlags & 00230 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT)) 00231 { 00232 SetLastError(ERROR_INVALID_DATA); 00233 ret = FALSE; 00234 goto end; 00235 } 00236 break; 00237 case CERT_STORE_CRL_CONTEXT: 00238 contextInterface = pCRLInterface; 00239 contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL; 00240 certStoreOffset = offsetof(CRL_CONTEXT, hCertStore); 00241 if (!(dwExpectedContentTypeFlags & 00242 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL)) 00243 { 00244 SetLastError(ERROR_INVALID_DATA); 00245 ret = FALSE; 00246 goto end; 00247 } 00248 break; 00249 case CERT_STORE_CTL_CONTEXT: 00250 contextInterface = pCTLInterface; 00251 contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL; 00252 certStoreOffset = offsetof(CTL_CONTEXT, hCertStore); 00253 if (!(dwExpectedContentTypeFlags & 00254 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)) 00255 { 00256 SetLastError(ERROR_INVALID_DATA); 00257 ret = FALSE; 00258 goto end; 00259 } 00260 break; 00261 default: 00262 SetLastError(ERROR_INVALID_DATA); 00263 ret = FALSE; 00264 goto end; 00265 } 00266 if (pdwMsgAndCertEncodingType) 00267 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; 00268 if (pdwContentType) 00269 *pdwContentType = contentType; 00270 if (phCertStore) 00271 *phCertStore = CertDuplicateStore( 00272 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset)); 00273 if (ppvContext) 00274 *ppvContext = contextInterface->duplicate(context); 00275 } 00276 00277 end: 00278 if (contextInterface && context) 00279 contextInterface->free(context); 00280 if (blob == &fileBlob) 00281 CryptMemFree(blob->pbData); 00282 TRACE("returning %d\n", ret); 00283 return ret; 00284 } 00285 00286 static BOOL CRYPT_QuerySerializedStoreFromFile(LPCWSTR fileName, 00287 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, 00288 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) 00289 { 00290 HANDLE file; 00291 BOOL ret = FALSE; 00292 00293 TRACE("%s\n", debugstr_w(fileName)); 00294 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, 00295 OPEN_EXISTING, 0, NULL); 00296 if (file != INVALID_HANDLE_VALUE) 00297 { 00298 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 00299 CERT_STORE_CREATE_NEW_FLAG, NULL); 00300 00301 ret = CRYPT_ReadSerializedStoreFromFile(file, store); 00302 if (ret) 00303 { 00304 if (pdwMsgAndCertEncodingType) 00305 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; 00306 if (pdwContentType) 00307 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE; 00308 if (phCertStore) 00309 *phCertStore = CertDuplicateStore(store); 00310 } 00311 CertCloseStore(store, 0); 00312 CloseHandle(file); 00313 } 00314 TRACE("returning %d\n", ret); 00315 return ret; 00316 } 00317 00318 static BOOL CRYPT_QuerySerializedStoreFromBlob(const CRYPT_DATA_BLOB *blob, 00319 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, 00320 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) 00321 { 00322 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 00323 CERT_STORE_CREATE_NEW_FLAG, NULL); 00324 BOOL ret; 00325 00326 TRACE("(%d, %p)\n", blob->cbData, blob->pbData); 00327 00328 ret = CRYPT_ReadSerializedStoreFromBlob(blob, store); 00329 if (ret) 00330 { 00331 if (pdwMsgAndCertEncodingType) 00332 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; 00333 if (pdwContentType) 00334 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE; 00335 if (phCertStore) 00336 *phCertStore = CertDuplicateStore(store); 00337 } 00338 CertCloseStore(store, 0); 00339 TRACE("returning %d\n", ret); 00340 return ret; 00341 } 00342 00343 static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType, 00344 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, 00345 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) 00346 { 00347 switch (dwObjectType) 00348 { 00349 case CERT_QUERY_OBJECT_FILE: 00350 return CRYPT_QuerySerializedStoreFromFile(pvObject, 00351 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); 00352 case CERT_QUERY_OBJECT_BLOB: 00353 return CRYPT_QuerySerializedStoreFromBlob(pvObject, 00354 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); 00355 default: 00356 FIXME("unimplemented for type %d\n", dwObjectType); 00357 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ 00358 return FALSE; 00359 } 00360 } 00361 00362 static BOOL CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB *blob, 00363 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg) 00364 { 00365 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 00366 BOOL ret = FALSE; 00367 HCRYPTMSG msg; 00368 00369 if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL))) 00370 { 00371 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); 00372 if (ret) 00373 { 00374 DWORD type, len = sizeof(type); 00375 00376 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len); 00377 if (ret) 00378 { 00379 if (type != CMSG_SIGNED) 00380 { 00381 SetLastError(ERROR_INVALID_DATA); 00382 ret = FALSE; 00383 } 00384 } 00385 } 00386 if (!ret) 00387 { 00388 CryptMsgClose(msg); 00389 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, 00390 NULL); 00391 if (msg) 00392 { 00393 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); 00394 if (!ret) 00395 { 00396 CryptMsgClose(msg); 00397 msg = NULL; 00398 } 00399 } 00400 } 00401 } 00402 if (ret) 00403 { 00404 if (pdwMsgAndCertEncodingType) 00405 *pdwMsgAndCertEncodingType = encodingType; 00406 if (pdwContentType) 00407 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; 00408 if (phMsg) 00409 *phMsg = msg; 00410 } 00411 return ret; 00412 } 00413 00414 static BOOL CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB *blob, 00415 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg) 00416 { 00417 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 00418 BOOL ret = FALSE; 00419 HCRYPTMSG msg; 00420 00421 if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL))) 00422 { 00423 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); 00424 if (ret) 00425 { 00426 DWORD type, len = sizeof(type); 00427 00428 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len); 00429 if (ret) 00430 { 00431 if (type != CMSG_DATA) 00432 { 00433 SetLastError(ERROR_INVALID_DATA); 00434 ret = FALSE; 00435 } 00436 } 00437 } 00438 if (!ret) 00439 { 00440 CryptMsgClose(msg); 00441 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, 00442 NULL, NULL); 00443 if (msg) 00444 { 00445 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); 00446 if (!ret) 00447 { 00448 CryptMsgClose(msg); 00449 msg = NULL; 00450 } 00451 } 00452 } 00453 } 00454 if (ret) 00455 { 00456 if (pdwMsgAndCertEncodingType) 00457 *pdwMsgAndCertEncodingType = encodingType; 00458 if (pdwContentType) 00459 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; 00460 if (phMsg) 00461 *phMsg = msg; 00462 } 00463 return ret; 00464 } 00465 00466 /* Used to decode non-embedded messages */ 00467 static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject, 00468 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, 00469 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType, 00470 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) 00471 { 00472 CERT_BLOB fileBlob; 00473 const CERT_BLOB *blob; 00474 BOOL ret; 00475 HCRYPTMSG msg = NULL; 00476 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 00477 DWORD formatType = 0; 00478 00479 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType, pvObject, 00480 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, 00481 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore, 00482 phMsg); 00483 00484 switch (dwObjectType) 00485 { 00486 case CERT_QUERY_OBJECT_FILE: 00487 /* This isn't an embedded PKCS7 message, so just read the file 00488 * directly 00489 */ 00490 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob); 00491 blob = &fileBlob; 00492 break; 00493 case CERT_QUERY_OBJECT_BLOB: 00494 blob = pvObject; 00495 ret = TRUE; 00496 break; 00497 default: 00498 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ 00499 ret = FALSE; 00500 } 00501 if (!ret) 00502 return FALSE; 00503 00504 ret = FALSE; 00505 if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY) 00506 { 00507 /* Try it first as a signed message */ 00508 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) 00509 ret = CRYPT_QuerySignedMessage(blob, pdwMsgAndCertEncodingType, 00510 pdwContentType, &msg); 00511 /* Failing that, try as an unsigned message */ 00512 if (!ret && 00513 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) 00514 ret = CRYPT_QueryUnsignedMessage(blob, pdwMsgAndCertEncodingType, 00515 pdwContentType, &msg); 00516 if (ret) 00517 formatType = CERT_QUERY_FORMAT_BINARY; 00518 } 00519 if (!ret && 00520 (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED)) 00521 { 00522 CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData }; 00523 CRYPT_DATA_BLOB decoded; 00524 00525 while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1]) 00526 trimmed.cbData--; 00527 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData, 00528 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL); 00529 if (ret) 00530 { 00531 decoded.pbData = CryptMemAlloc(decoded.cbData); 00532 if (decoded.pbData) 00533 { 00534 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, 00535 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData, 00536 &decoded.cbData, NULL, NULL); 00537 if (ret) 00538 { 00539 /* Try it first as a signed message */ 00540 if (dwExpectedContentTypeFlags & 00541 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) 00542 ret = CRYPT_QuerySignedMessage(&decoded, 00543 pdwMsgAndCertEncodingType, pdwContentType, &msg); 00544 /* Failing that, try as an unsigned message */ 00545 if (!ret && (dwExpectedContentTypeFlags & 00546 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) 00547 ret = CRYPT_QueryUnsignedMessage(&decoded, 00548 pdwMsgAndCertEncodingType, pdwContentType, &msg); 00549 if (ret) 00550 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED; 00551 } 00552 CryptMemFree(decoded.pbData); 00553 } 00554 else 00555 ret = FALSE; 00556 } 00557 if (!ret && !(blob->cbData % sizeof(WCHAR))) 00558 { 00559 CRYPT_DATA_BLOB decoded; 00560 LPWSTR str = (LPWSTR)blob->pbData; 00561 DWORD strLen = blob->cbData / sizeof(WCHAR); 00562 00563 /* Try again, assuming the input string is UTF-16 base64 */ 00564 while (strLen && !str[strLen - 1]) 00565 strLen--; 00566 ret = CryptStringToBinaryW(str, strLen, CRYPT_STRING_BASE64_ANY, 00567 NULL, &decoded.cbData, NULL, NULL); 00568 if (ret) 00569 { 00570 decoded.pbData = CryptMemAlloc(decoded.cbData); 00571 if (decoded.pbData) 00572 { 00573 ret = CryptStringToBinaryW(str, strLen, 00574 CRYPT_STRING_BASE64_ANY, decoded.pbData, &decoded.cbData, 00575 NULL, NULL); 00576 if (ret) 00577 { 00578 /* Try it first as a signed message */ 00579 if (dwExpectedContentTypeFlags & 00580 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) 00581 ret = CRYPT_QuerySignedMessage(&decoded, 00582 pdwMsgAndCertEncodingType, pdwContentType, &msg); 00583 /* Failing that, try as an unsigned message */ 00584 if (!ret && (dwExpectedContentTypeFlags & 00585 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) 00586 ret = CRYPT_QueryUnsignedMessage(&decoded, 00587 pdwMsgAndCertEncodingType, pdwContentType, &msg); 00588 if (ret) 00589 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED; 00590 } 00591 CryptMemFree(decoded.pbData); 00592 } 00593 else 00594 ret = FALSE; 00595 } 00596 } 00597 } 00598 if (ret) 00599 { 00600 if (pdwFormatType) 00601 *pdwFormatType = formatType; 00602 if (phCertStore) 00603 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0, 00604 0, msg); 00605 if (phMsg) 00606 *phMsg = msg; 00607 else 00608 CryptMsgClose(msg); 00609 } 00610 if (blob == &fileBlob) 00611 CryptMemFree(blob->pbData); 00612 TRACE("returning %d\n", ret); 00613 return ret; 00614 } 00615 00616 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType, 00617 const void *pvObject, DWORD dwExpectedContentTypeFlags, 00618 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, 00619 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) 00620 { 00621 HANDLE file; 00622 GUID subject; 00623 BOOL ret = FALSE; 00624 00625 TRACE("%s\n", debugstr_w(pvObject)); 00626 00627 if (dwObjectType != CERT_QUERY_OBJECT_FILE) 00628 { 00629 WARN("don't know what to do for type %d embedded signed messages\n", 00630 dwObjectType); 00631 SetLastError(E_INVALIDARG); 00632 return FALSE; 00633 } 00634 file = CreateFileW(pvObject, GENERIC_READ, FILE_SHARE_READ, 00635 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00636 if (file != INVALID_HANDLE_VALUE) 00637 { 00638 ret = CryptSIPRetrieveSubjectGuid(pvObject, file, &subject); 00639 if (ret) 00640 { 00641 SIP_DISPATCH_INFO sip; 00642 00643 memset(&sip, 0, sizeof(sip)); 00644 sip.cbSize = sizeof(sip); 00645 ret = CryptSIPLoad(&subject, 0, &sip); 00646 if (ret) 00647 { 00648 SIP_SUBJECTINFO subjectInfo; 00649 CERT_BLOB blob; 00650 DWORD encodingType; 00651 00652 memset(&subjectInfo, 0, sizeof(subjectInfo)); 00653 subjectInfo.cbSize = sizeof(subjectInfo); 00654 subjectInfo.pgSubjectType = &subject; 00655 subjectInfo.hFile = file; 00656 subjectInfo.pwsFileName = pvObject; 00657 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData, 00658 NULL); 00659 if (ret) 00660 { 00661 blob.pbData = CryptMemAlloc(blob.cbData); 00662 if (blob.pbData) 00663 { 00664 ret = sip.pfGet(&subjectInfo, &encodingType, 0, 00665 &blob.cbData, blob.pbData); 00666 if (ret) 00667 { 00668 ret = CRYPT_QueryMessageObject( 00669 CERT_QUERY_OBJECT_BLOB, &blob, 00670 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED, 00671 CERT_QUERY_FORMAT_FLAG_BINARY, 00672 pdwMsgAndCertEncodingType, NULL, NULL, 00673 phCertStore, phMsg); 00674 if (ret && pdwContentType) 00675 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED; 00676 } 00677 CryptMemFree(blob.pbData); 00678 } 00679 else 00680 { 00681 SetLastError(ERROR_OUTOFMEMORY); 00682 ret = FALSE; 00683 } 00684 } 00685 } 00686 } 00687 CloseHandle(file); 00688 } 00689 TRACE("returning %d\n", ret); 00690 return ret; 00691 } 00692 00693 BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject, 00694 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, 00695 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, 00696 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg, 00697 const void **ppvContext) 00698 { 00699 static const DWORD unimplementedTypes = 00700 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX | 00701 CERT_QUERY_CONTENT_FLAG_CERT_PAIR; 00702 BOOL ret = TRUE; 00703 00704 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n", 00705 dwObjectType, pvObject, dwExpectedContentTypeFlags, 00706 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType, 00707 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext); 00708 00709 if (dwObjectType != CERT_QUERY_OBJECT_BLOB && 00710 dwObjectType != CERT_QUERY_OBJECT_FILE) 00711 { 00712 WARN("unsupported type %d\n", dwObjectType); 00713 SetLastError(E_INVALIDARG); 00714 return FALSE; 00715 } 00716 if (!pvObject) 00717 { 00718 WARN("missing required argument\n"); 00719 SetLastError(E_INVALIDARG); 00720 return FALSE; 00721 } 00722 if (dwExpectedContentTypeFlags & unimplementedTypes) 00723 WARN("unimplemented for types %08x\n", 00724 dwExpectedContentTypeFlags & unimplementedTypes); 00725 00726 if (pdwFormatType) 00727 *pdwFormatType = CERT_QUERY_FORMAT_BINARY; 00728 if (phCertStore) 00729 *phCertStore = NULL; 00730 if (phMsg) 00731 *phMsg = NULL; 00732 if (ppvContext) 00733 *ppvContext = NULL; 00734 00735 ret = FALSE; 00736 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) || 00737 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) || 00738 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL)) 00739 { 00740 ret = CRYPT_QueryContextObject(dwObjectType, pvObject, 00741 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, 00742 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore, 00743 ppvContext); 00744 } 00745 if (!ret && 00746 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE)) 00747 { 00748 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject, 00749 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); 00750 } 00751 if (!ret && 00752 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) || 00753 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) || 00754 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))) 00755 { 00756 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject, 00757 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, 00758 phCertStore, ppvContext); 00759 } 00760 if (!ret && 00761 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) || 00762 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))) 00763 { 00764 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject, 00765 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, 00766 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, 00767 phCertStore, phMsg); 00768 } 00769 if (!ret && 00770 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED)) 00771 { 00772 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject, 00773 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, 00774 phCertStore, phMsg); 00775 } 00776 if (!ret) 00777 SetLastError(CRYPT_E_NO_MATCH); 00778 TRACE("returning %d\n", ret); 00779 return ret; 00780 } 00781 00782 static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType, 00783 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 00784 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 00785 DWORD *pcbFormat) 00786 { 00787 BOOL ret; 00788 DWORD bytesNeeded; 00789 00790 if (cbEncoded) 00791 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR); 00792 else 00793 bytesNeeded = sizeof(WCHAR); 00794 if (!pbFormat) 00795 { 00796 *pcbFormat = bytesNeeded; 00797 ret = TRUE; 00798 } 00799 else if (*pcbFormat < bytesNeeded) 00800 { 00801 *pcbFormat = bytesNeeded; 00802 SetLastError(ERROR_MORE_DATA); 00803 ret = FALSE; 00804 } 00805 else 00806 { 00807 static const WCHAR fmt[] = { '%','0','2','x',' ',0 }; 00808 static const WCHAR endFmt[] = { '%','0','2','x',0 }; 00809 DWORD i; 00810 LPWSTR ptr = pbFormat; 00811 00812 *pcbFormat = bytesNeeded; 00813 if (cbEncoded) 00814 { 00815 for (i = 0; i < cbEncoded; i++) 00816 { 00817 if (i < cbEncoded - 1) 00818 ptr += sprintfW(ptr, fmt, pbEncoded[i]); 00819 else 00820 ptr += sprintfW(ptr, endFmt, pbEncoded[i]); 00821 } 00822 } 00823 else 00824 *ptr = 0; 00825 ret = TRUE; 00826 } 00827 return ret; 00828 } 00829 00830 #define MAX_STRING_RESOURCE_LEN 128 00831 00832 static const WCHAR commaSpace[] = { ',',' ',0 }; 00833 00834 struct BitToString 00835 { 00836 BYTE bit; 00837 int id; 00838 WCHAR str[MAX_STRING_RESOURCE_LEN]; 00839 }; 00840 00841 static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map, 00842 DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first) 00843 { 00844 DWORD bytesNeeded = sizeof(WCHAR); 00845 int i; 00846 BOOL ret = TRUE, localFirst = *first; 00847 00848 for (i = 0; i < mapEntries; i++) 00849 if (bits & map[i].bit) 00850 { 00851 if (!localFirst) 00852 bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR); 00853 localFirst = FALSE; 00854 bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR); 00855 } 00856 if (!pbFormat) 00857 { 00858 *first = localFirst; 00859 *pcbFormat = bytesNeeded; 00860 } 00861 else if (*pcbFormat < bytesNeeded) 00862 { 00863 *first = localFirst; 00864 *pcbFormat = bytesNeeded; 00865 SetLastError(ERROR_MORE_DATA); 00866 ret = FALSE; 00867 } 00868 else 00869 { 00870 LPWSTR str = pbFormat; 00871 00872 localFirst = *first; 00873 *pcbFormat = bytesNeeded; 00874 for (i = 0; i < mapEntries; i++) 00875 if (bits & map[i].bit) 00876 { 00877 if (!localFirst) 00878 { 00879 strcpyW(str, commaSpace); 00880 str += strlenW(commaSpace); 00881 } 00882 localFirst = FALSE; 00883 strcpyW(str, map[i].str); 00884 str += strlenW(map[i].str); 00885 } 00886 *first = localFirst; 00887 } 00888 return ret; 00889 } 00890 00891 static struct BitToString keyUsageByte0Map[] = { 00892 { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } }, 00893 { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } }, 00894 { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } }, 00895 { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } }, 00896 { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } }, 00897 { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } }, 00898 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } }, 00899 { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } }, 00900 { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } }, 00901 }; 00902 static struct BitToString keyUsageByte1Map[] = { 00903 { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } }, 00904 }; 00905 00906 static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType, 00907 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 00908 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 00909 DWORD *pcbFormat) 00910 { 00911 DWORD size; 00912 CRYPT_BIT_BLOB *bits; 00913 BOOL ret; 00914 00915 if (!cbEncoded) 00916 { 00917 SetLastError(E_INVALIDARG); 00918 return FALSE; 00919 } 00920 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE, 00921 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size))) 00922 { 00923 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN]; 00924 DWORD bytesNeeded = sizeof(WCHAR); 00925 00926 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, 00927 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0])); 00928 if (!bits->cbData || bits->cbData > 2) 00929 { 00930 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); 00931 if (!pbFormat) 00932 *pcbFormat = bytesNeeded; 00933 else if (*pcbFormat < bytesNeeded) 00934 { 00935 *pcbFormat = bytesNeeded; 00936 SetLastError(ERROR_MORE_DATA); 00937 ret = FALSE; 00938 } 00939 else 00940 { 00941 LPWSTR str = pbFormat; 00942 00943 *pcbFormat = bytesNeeded; 00944 strcpyW(str, infoNotAvailable); 00945 } 00946 } 00947 else 00948 { 00949 static BOOL stringsLoaded = FALSE; 00950 int i; 00951 DWORD bitStringLen; 00952 BOOL first = TRUE; 00953 00954 if (!stringsLoaded) 00955 { 00956 for (i = 0; 00957 i < sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]); 00958 i++) 00959 LoadStringW(hInstance, keyUsageByte0Map[i].id, 00960 keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN); 00961 for (i = 0; 00962 i < sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]); 00963 i++) 00964 LoadStringW(hInstance, keyUsageByte1Map[i].id, 00965 keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN); 00966 stringsLoaded = TRUE; 00967 } 00968 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map, 00969 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]), 00970 NULL, &bitStringLen, &first); 00971 bytesNeeded += bitStringLen; 00972 if (bits->cbData == 2) 00973 { 00974 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map, 00975 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]), 00976 NULL, &bitStringLen, &first); 00977 bytesNeeded += bitStringLen; 00978 } 00979 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */ 00980 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, 00981 bits->cbData, NULL, &size); 00982 bytesNeeded += size; 00983 if (!pbFormat) 00984 *pcbFormat = bytesNeeded; 00985 else if (*pcbFormat < bytesNeeded) 00986 { 00987 *pcbFormat = bytesNeeded; 00988 SetLastError(ERROR_MORE_DATA); 00989 ret = FALSE; 00990 } 00991 else 00992 { 00993 LPWSTR str = pbFormat; 00994 00995 bitStringLen = bytesNeeded; 00996 first = TRUE; 00997 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map, 00998 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]), 00999 str, &bitStringLen, &first); 01000 str += bitStringLen / sizeof(WCHAR) - 1; 01001 if (bits->cbData == 2) 01002 { 01003 bitStringLen = bytesNeeded; 01004 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map, 01005 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]), 01006 str, &bitStringLen, &first); 01007 str += bitStringLen / sizeof(WCHAR) - 1; 01008 } 01009 *str++ = ' '; 01010 *str++ = '('; 01011 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, 01012 bits->cbData, str, &size); 01013 str += size / sizeof(WCHAR) - 1; 01014 *str++ = ')'; 01015 *str = 0; 01016 } 01017 } 01018 LocalFree(bits); 01019 } 01020 return ret; 01021 } 01022 01023 static const WCHAR crlf[] = { '\r','\n',0 }; 01024 01025 static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN]; 01026 static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN]; 01027 static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN]; 01028 static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN]; 01029 01030 static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType, 01031 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 01032 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 01033 DWORD *pcbFormat) 01034 { 01035 DWORD size; 01036 CERT_BASIC_CONSTRAINTS2_INFO *info; 01037 BOOL ret; 01038 01039 if (!cbEncoded) 01040 { 01041 SetLastError(E_INVALIDARG); 01042 return FALSE; 01043 } 01044 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2, 01045 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) 01046 { 01047 static const WCHAR pathFmt[] = { '%','d',0 }; 01048 static BOOL stringsLoaded = FALSE; 01049 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */ 01050 WCHAR pathLength[MAX_STRING_RESOURCE_LEN]; 01051 LPCWSTR sep, subjectType; 01052 DWORD sepLen; 01053 01054 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01055 { 01056 sep = crlf; 01057 sepLen = strlenW(crlf) * sizeof(WCHAR); 01058 } 01059 else 01060 { 01061 sep = commaSpace; 01062 sepLen = strlenW(commaSpace) * sizeof(WCHAR); 01063 } 01064 01065 if (!stringsLoaded) 01066 { 01067 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader, 01068 sizeof(subjectTypeHeader) / sizeof(subjectTypeHeader[0])); 01069 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA, 01070 sizeof(subjectTypeCA) / sizeof(subjectTypeCA[0])); 01071 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT, 01072 subjectTypeEndCert, 01073 sizeof(subjectTypeEndCert) / sizeof(subjectTypeEndCert[0])); 01074 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader, 01075 sizeof(pathLengthHeader) / sizeof(pathLengthHeader[0])); 01076 stringsLoaded = TRUE; 01077 } 01078 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR); 01079 if (info->fCA) 01080 subjectType = subjectTypeCA; 01081 else 01082 subjectType = subjectTypeEndCert; 01083 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR); 01084 bytesNeeded += sepLen; 01085 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR); 01086 if (info->fPathLenConstraint) 01087 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint); 01088 else 01089 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength, 01090 sizeof(pathLength) / sizeof(pathLength[0])); 01091 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR); 01092 if (!pbFormat) 01093 *pcbFormat = bytesNeeded; 01094 else if (*pcbFormat < bytesNeeded) 01095 { 01096 *pcbFormat = bytesNeeded; 01097 SetLastError(ERROR_MORE_DATA); 01098 ret = FALSE; 01099 } 01100 else 01101 { 01102 LPWSTR str = pbFormat; 01103 01104 *pcbFormat = bytesNeeded; 01105 strcpyW(str, subjectTypeHeader); 01106 str += strlenW(subjectTypeHeader); 01107 strcpyW(str, subjectType); 01108 str += strlenW(subjectType); 01109 strcpyW(str, sep); 01110 str += sepLen / sizeof(WCHAR); 01111 strcpyW(str, pathLengthHeader); 01112 str += strlenW(pathLengthHeader); 01113 strcpyW(str, pathLength); 01114 } 01115 LocalFree(info); 01116 } 01117 return ret; 01118 } 01119 01120 static BOOL CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB *blob, int id, 01121 LPWSTR str, DWORD *pcbStr) 01122 { 01123 WCHAR buf[MAX_STRING_RESOURCE_LEN]; 01124 DWORD bytesNeeded; 01125 BOOL ret; 01126 01127 LoadStringW(hInstance, id, buf, sizeof(buf) / sizeof(buf[0])); 01128 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL, 01129 blob->pbData, blob->cbData, NULL, &bytesNeeded); 01130 bytesNeeded += strlenW(buf) * sizeof(WCHAR); 01131 if (!str) 01132 { 01133 *pcbStr = bytesNeeded; 01134 ret = TRUE; 01135 } 01136 else if (*pcbStr < bytesNeeded) 01137 { 01138 *pcbStr = bytesNeeded; 01139 SetLastError(ERROR_MORE_DATA); 01140 ret = FALSE; 01141 } 01142 else 01143 { 01144 *pcbStr = bytesNeeded; 01145 strcpyW(str, buf); 01146 str += strlenW(str); 01147 bytesNeeded -= strlenW(str) * sizeof(WCHAR); 01148 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL, 01149 blob->pbData, blob->cbData, str, &bytesNeeded); 01150 } 01151 return ret; 01152 } 01153 01154 static BOOL CRYPT_FormatKeyId(const CRYPT_DATA_BLOB *keyId, LPWSTR str, 01155 DWORD *pcbStr) 01156 { 01157 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr); 01158 } 01159 01160 static BOOL CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB *serialNum, LPWSTR str, 01161 DWORD *pcbStr) 01162 { 01163 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER, 01164 str, pcbStr); 01165 } 01166 01167 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 }; 01168 static const WCHAR colonCrlf[] = { ':','\r','\n',0 }; 01169 01170 static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel, 01171 const CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr) 01172 { 01173 BOOL ret; 01174 WCHAR buf[MAX_STRING_RESOURCE_LEN]; 01175 WCHAR mask[MAX_STRING_RESOURCE_LEN]; 01176 WCHAR ipAddrBuf[32]; 01177 WCHAR maskBuf[16]; 01178 DWORD bytesNeeded = sizeof(WCHAR); 01179 DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG; 01180 01181 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01182 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR); 01183 switch (entry->dwAltNameChoice) 01184 { 01185 case CERT_ALT_NAME_RFC822_NAME: 01186 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf, 01187 sizeof(buf) / sizeof(buf[0])); 01188 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR); 01189 ret = TRUE; 01190 break; 01191 case CERT_ALT_NAME_DNS_NAME: 01192 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf, 01193 sizeof(buf) / sizeof(buf[0])); 01194 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR); 01195 ret = TRUE; 01196 break; 01197 case CERT_ALT_NAME_DIRECTORY_NAME: 01198 { 01199 DWORD directoryNameLen; 01200 01201 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01202 strType |= CERT_NAME_STR_CRLF_FLAG; 01203 directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING, 01204 indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0); 01205 LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf, 01206 sizeof(buf) / sizeof(buf[0])); 01207 bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR); 01208 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01209 bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR); 01210 else 01211 bytesNeeded += sizeof(WCHAR); /* '=' */ 01212 ret = TRUE; 01213 break; 01214 } 01215 case CERT_ALT_NAME_URL: 01216 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf, 01217 sizeof(buf) / sizeof(buf[0])); 01218 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR); 01219 ret = TRUE; 01220 break; 01221 case CERT_ALT_NAME_IP_ADDRESS: 01222 { 01223 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.', 01224 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0 01225 }; 01226 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d', 01227 '.','%','d',0 }; 01228 01229 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf, 01230 sizeof(buf) / sizeof(buf[0])); 01231 if (entry->u.IPAddress.cbData == 8) 01232 { 01233 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01234 { 01235 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask, 01236 sizeof(mask) / sizeof(mask[0])); 01237 bytesNeeded += strlenW(mask) * sizeof(WCHAR); 01238 sprintfW(ipAddrBuf, ipAddrFmt, 01239 entry->u.IPAddress.pbData[0], 01240 entry->u.IPAddress.pbData[1], 01241 entry->u.IPAddress.pbData[2], 01242 entry->u.IPAddress.pbData[3]); 01243 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR); 01244 /* indent again, for the mask line */ 01245 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR); 01246 sprintfW(maskBuf, ipAddrFmt, 01247 entry->u.IPAddress.pbData[4], 01248 entry->u.IPAddress.pbData[5], 01249 entry->u.IPAddress.pbData[6], 01250 entry->u.IPAddress.pbData[7]); 01251 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR); 01252 bytesNeeded += strlenW(crlf) * sizeof(WCHAR); 01253 } 01254 else 01255 { 01256 sprintfW(ipAddrBuf, ipAddrWithMaskFmt, 01257 entry->u.IPAddress.pbData[0], 01258 entry->u.IPAddress.pbData[1], 01259 entry->u.IPAddress.pbData[2], 01260 entry->u.IPAddress.pbData[3], 01261 entry->u.IPAddress.pbData[4], 01262 entry->u.IPAddress.pbData[5], 01263 entry->u.IPAddress.pbData[6], 01264 entry->u.IPAddress.pbData[7]); 01265 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR); 01266 } 01267 ret = TRUE; 01268 } 01269 else 01270 { 01271 FIXME("unknown IP address format (%d bytes)\n", 01272 entry->u.IPAddress.cbData); 01273 ret = FALSE; 01274 } 01275 break; 01276 } 01277 default: 01278 FIXME("unimplemented for %d\n", entry->dwAltNameChoice); 01279 ret = FALSE; 01280 } 01281 if (ret) 01282 { 01283 bytesNeeded += strlenW(buf) * sizeof(WCHAR); 01284 if (!str) 01285 *pcbStr = bytesNeeded; 01286 else if (*pcbStr < bytesNeeded) 01287 { 01288 *pcbStr = bytesNeeded; 01289 SetLastError(ERROR_MORE_DATA); 01290 ret = FALSE; 01291 } 01292 else 01293 { 01294 DWORD i; 01295 01296 *pcbStr = bytesNeeded; 01297 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01298 { 01299 for (i = 0; i < indentLevel; i++) 01300 { 01301 strcpyW(str, indent); 01302 str += strlenW(indent); 01303 } 01304 } 01305 strcpyW(str, buf); 01306 str += strlenW(str); 01307 switch (entry->dwAltNameChoice) 01308 { 01309 case CERT_ALT_NAME_RFC822_NAME: 01310 case CERT_ALT_NAME_DNS_NAME: 01311 case CERT_ALT_NAME_URL: 01312 strcpyW(str, entry->u.pwszURL); 01313 break; 01314 case CERT_ALT_NAME_DIRECTORY_NAME: 01315 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01316 { 01317 strcpyW(str, colonCrlf); 01318 str += strlenW(colonCrlf); 01319 } 01320 else 01321 *str++ = '='; 01322 cert_name_to_str_with_indent(X509_ASN_ENCODING, 01323 indentLevel + 1, &entry->u.DirectoryName, strType, str, 01324 bytesNeeded / sizeof(WCHAR)); 01325 break; 01326 case CERT_ALT_NAME_IP_ADDRESS: 01327 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01328 { 01329 strcpyW(str, ipAddrBuf); 01330 str += strlenW(ipAddrBuf); 01331 strcpyW(str, crlf); 01332 str += strlenW(crlf); 01333 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01334 { 01335 for (i = 0; i < indentLevel; i++) 01336 { 01337 strcpyW(str, indent); 01338 str += strlenW(indent); 01339 } 01340 } 01341 strcpyW(str, mask); 01342 str += strlenW(mask); 01343 strcpyW(str, maskBuf); 01344 } 01345 else 01346 strcpyW(str, ipAddrBuf); 01347 break; 01348 } 01349 } 01350 } 01351 return ret; 01352 } 01353 01354 static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel, 01355 const CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr) 01356 { 01357 DWORD i, size, bytesNeeded = 0; 01358 BOOL ret = TRUE; 01359 LPCWSTR sep; 01360 DWORD sepLen; 01361 01362 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01363 { 01364 sep = crlf; 01365 sepLen = strlenW(crlf) * sizeof(WCHAR); 01366 } 01367 else 01368 { 01369 sep = commaSpace; 01370 sepLen = strlenW(commaSpace) * sizeof(WCHAR); 01371 } 01372 01373 for (i = 0; ret && i < name->cAltEntry; i++) 01374 { 01375 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel, 01376 &name->rgAltEntry[i], NULL, &size); 01377 if (ret) 01378 { 01379 bytesNeeded += size - sizeof(WCHAR); 01380 if (i < name->cAltEntry - 1) 01381 bytesNeeded += sepLen; 01382 } 01383 } 01384 if (ret) 01385 { 01386 bytesNeeded += sizeof(WCHAR); 01387 if (!str) 01388 *pcbStr = bytesNeeded; 01389 else if (*pcbStr < bytesNeeded) 01390 { 01391 *pcbStr = bytesNeeded; 01392 SetLastError(ERROR_MORE_DATA); 01393 ret = FALSE; 01394 } 01395 else 01396 { 01397 *pcbStr = bytesNeeded; 01398 for (i = 0; ret && i < name->cAltEntry; i++) 01399 { 01400 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel, 01401 &name->rgAltEntry[i], str, &size); 01402 if (ret) 01403 { 01404 str += size / sizeof(WCHAR) - 1; 01405 if (i < name->cAltEntry - 1) 01406 { 01407 strcpyW(str, sep); 01408 str += sepLen / sizeof(WCHAR); 01409 } 01410 } 01411 } 01412 } 01413 } 01414 return ret; 01415 } 01416 01417 static const WCHAR colonSep[] = { ':',' ',0 }; 01418 01419 static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType, 01420 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 01421 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 01422 DWORD *pcbFormat) 01423 { 01424 BOOL ret; 01425 CERT_ALT_NAME_INFO *info; 01426 DWORD size; 01427 01428 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME, 01429 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) 01430 { 01431 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat); 01432 LocalFree(info); 01433 } 01434 return ret; 01435 } 01436 01437 static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType, 01438 const CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr) 01439 { 01440 WCHAR buf[MAX_STRING_RESOURCE_LEN]; 01441 DWORD bytesNeeded, sepLen; 01442 LPCWSTR sep; 01443 BOOL ret; 01444 01445 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, sizeof(buf) / sizeof(buf[0])); 01446 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL, 01447 &bytesNeeded); 01448 bytesNeeded += strlenW(buf) * sizeof(WCHAR); 01449 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01450 { 01451 sep = colonCrlf; 01452 sepLen = strlenW(colonCrlf) * sizeof(WCHAR); 01453 } 01454 else 01455 { 01456 sep = colonSep; 01457 sepLen = strlenW(colonSep) * sizeof(WCHAR); 01458 } 01459 bytesNeeded += sepLen; 01460 if (ret) 01461 { 01462 if (!str) 01463 *pcbStr = bytesNeeded; 01464 else if (*pcbStr < bytesNeeded) 01465 { 01466 *pcbStr = bytesNeeded; 01467 SetLastError(ERROR_MORE_DATA); 01468 ret = FALSE; 01469 } 01470 else 01471 { 01472 *pcbStr = bytesNeeded; 01473 strcpyW(str, buf); 01474 bytesNeeded -= strlenW(str) * sizeof(WCHAR); 01475 str += strlenW(str); 01476 strcpyW(str, sep); 01477 str += sepLen / sizeof(WCHAR); 01478 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str, 01479 &bytesNeeded); 01480 } 01481 } 01482 return ret; 01483 } 01484 01485 static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType, 01486 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 01487 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 01488 DWORD *pcbFormat) 01489 { 01490 CERT_AUTHORITY_KEY_ID2_INFO *info; 01491 DWORD size; 01492 BOOL ret = FALSE; 01493 01494 if (!cbEncoded) 01495 { 01496 SetLastError(E_INVALIDARG); 01497 return FALSE; 01498 } 01499 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2, 01500 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) 01501 { 01502 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */ 01503 LPCWSTR sep; 01504 DWORD sepLen; 01505 BOOL needSeparator = FALSE; 01506 01507 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01508 { 01509 sep = crlf; 01510 sepLen = strlenW(crlf) * sizeof(WCHAR); 01511 } 01512 else 01513 { 01514 sep = commaSpace; 01515 sepLen = strlenW(commaSpace) * sizeof(WCHAR); 01516 } 01517 01518 if (info->KeyId.cbData) 01519 { 01520 needSeparator = TRUE; 01521 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size); 01522 if (ret) 01523 { 01524 /* don't include NULL-terminator more than once */ 01525 bytesNeeded += size - sizeof(WCHAR); 01526 } 01527 } 01528 if (info->AuthorityCertIssuer.cAltEntry) 01529 { 01530 if (needSeparator) 01531 bytesNeeded += sepLen; 01532 needSeparator = TRUE; 01533 ret = CRYPT_FormatCertIssuer(dwFormatStrType, 01534 &info->AuthorityCertIssuer, NULL, &size); 01535 if (ret) 01536 { 01537 /* don't include NULL-terminator more than once */ 01538 bytesNeeded += size - sizeof(WCHAR); 01539 } 01540 } 01541 if (info->AuthorityCertSerialNumber.cbData) 01542 { 01543 if (needSeparator) 01544 bytesNeeded += sepLen; 01545 ret = CRYPT_FormatCertSerialNumber( 01546 &info->AuthorityCertSerialNumber, NULL, &size); 01547 if (ret) 01548 { 01549 /* don't include NULL-terminator more than once */ 01550 bytesNeeded += size - sizeof(WCHAR); 01551 } 01552 } 01553 if (ret) 01554 { 01555 if (!pbFormat) 01556 *pcbFormat = bytesNeeded; 01557 else if (*pcbFormat < bytesNeeded) 01558 { 01559 *pcbFormat = bytesNeeded; 01560 SetLastError(ERROR_MORE_DATA); 01561 ret = FALSE; 01562 } 01563 else 01564 { 01565 LPWSTR str = pbFormat; 01566 01567 *pcbFormat = bytesNeeded; 01568 needSeparator = FALSE; 01569 if (info->KeyId.cbData) 01570 { 01571 needSeparator = TRUE; 01572 /* Overestimate size available, it's already been checked 01573 * above. 01574 */ 01575 size = bytesNeeded; 01576 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size); 01577 if (ret) 01578 str += size / sizeof(WCHAR) - 1; 01579 } 01580 if (info->AuthorityCertIssuer.cAltEntry) 01581 { 01582 if (needSeparator) 01583 { 01584 strcpyW(str, sep); 01585 str += sepLen / sizeof(WCHAR); 01586 } 01587 needSeparator = TRUE; 01588 /* Overestimate size available, it's already been checked 01589 * above. 01590 */ 01591 size = bytesNeeded; 01592 ret = CRYPT_FormatCertIssuer(dwFormatStrType, 01593 &info->AuthorityCertIssuer, str, &size); 01594 if (ret) 01595 str += size / sizeof(WCHAR) - 1; 01596 } 01597 if (info->AuthorityCertSerialNumber.cbData) 01598 { 01599 if (needSeparator) 01600 { 01601 strcpyW(str, sep); 01602 str += sepLen / sizeof(WCHAR); 01603 } 01604 /* Overestimate size available, it's already been checked 01605 * above. 01606 */ 01607 size = bytesNeeded; 01608 ret = CRYPT_FormatCertSerialNumber( 01609 &info->AuthorityCertSerialNumber, str, &size); 01610 } 01611 } 01612 } 01613 LocalFree(info); 01614 } 01615 return ret; 01616 } 01617 01618 static WCHAR aia[MAX_STRING_RESOURCE_LEN]; 01619 static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN]; 01620 static WCHAR ocsp[MAX_STRING_RESOURCE_LEN]; 01621 static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN]; 01622 static WCHAR unknown[MAX_STRING_RESOURCE_LEN]; 01623 static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN]; 01624 01625 static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType, 01626 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 01627 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 01628 DWORD *pcbFormat) 01629 { 01630 CERT_AUTHORITY_INFO_ACCESS *info; 01631 DWORD size; 01632 BOOL ret = FALSE; 01633 01634 if (!cbEncoded) 01635 { 01636 SetLastError(E_INVALIDARG); 01637 return FALSE; 01638 } 01639 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, 01640 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, 01641 NULL, &info, &size))) 01642 { 01643 DWORD bytesNeeded = sizeof(WCHAR); 01644 01645 if (!info->cAccDescr) 01646 { 01647 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN]; 01648 01649 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, 01650 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0])); 01651 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); 01652 if (!pbFormat) 01653 *pcbFormat = bytesNeeded; 01654 else if (*pcbFormat < bytesNeeded) 01655 { 01656 *pcbFormat = bytesNeeded; 01657 SetLastError(ERROR_MORE_DATA); 01658 ret = FALSE; 01659 } 01660 else 01661 { 01662 *pcbFormat = bytesNeeded; 01663 strcpyW(pbFormat, infoNotAvailable); 01664 } 01665 } 01666 else 01667 { 01668 static const WCHAR numFmt[] = { '%','d',0 }; 01669 static const WCHAR equal[] = { '=',0 }; 01670 static BOOL stringsLoaded = FALSE; 01671 DWORD i; 01672 LPCWSTR headingSep, accessMethodSep, locationSep; 01673 WCHAR accessDescrNum[11]; 01674 01675 if (!stringsLoaded) 01676 { 01677 LoadStringW(hInstance, IDS_AIA, aia, 01678 sizeof(aia) / sizeof(aia[0])); 01679 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod, 01680 sizeof(accessMethod) / sizeof(accessMethod[0])); 01681 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp, 01682 sizeof(ocsp) / sizeof(ocsp[0])); 01683 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers, 01684 sizeof(caIssuers) / sizeof(caIssuers[0])); 01685 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown, 01686 sizeof(unknown) / sizeof(unknown[0])); 01687 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation, 01688 sizeof(accessLocation) / sizeof(accessLocation[0])); 01689 stringsLoaded = TRUE; 01690 } 01691 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01692 { 01693 headingSep = crlf; 01694 accessMethodSep = crlf; 01695 locationSep = colonCrlf; 01696 } 01697 else 01698 { 01699 headingSep = colonSep; 01700 accessMethodSep = commaSpace; 01701 locationSep = equal; 01702 } 01703 01704 for (i = 0; ret && i < info->cAccDescr; i++) 01705 { 01706 /* Heading */ 01707 bytesNeeded += sizeof(WCHAR); /* left bracket */ 01708 sprintfW(accessDescrNum, numFmt, i + 1); 01709 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR); 01710 bytesNeeded += sizeof(WCHAR); /* right bracket */ 01711 bytesNeeded += strlenW(aia) * sizeof(WCHAR); 01712 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR); 01713 /* Access method */ 01714 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR); 01715 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01716 bytesNeeded += strlenW(indent) * sizeof(WCHAR); 01717 if (!strcmp(info->rgAccDescr[i].pszAccessMethod, 01718 szOID_PKIX_OCSP)) 01719 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR); 01720 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod, 01721 szOID_PKIX_CA_ISSUERS)) 01722 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers); 01723 else 01724 bytesNeeded += strlenW(unknown) * sizeof(WCHAR); 01725 bytesNeeded += sizeof(WCHAR); /* space */ 01726 bytesNeeded += sizeof(WCHAR); /* left paren */ 01727 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod) 01728 * sizeof(WCHAR); 01729 bytesNeeded += sizeof(WCHAR); /* right paren */ 01730 /* Delimiter between access method and location */ 01731 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR); 01732 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01733 bytesNeeded += strlenW(indent) * sizeof(WCHAR); 01734 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR); 01735 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR); 01736 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2, 01737 &info->rgAccDescr[i].AccessLocation, NULL, &size); 01738 if (ret) 01739 bytesNeeded += size - sizeof(WCHAR); 01740 /* Need extra delimiter between access method entries */ 01741 if (i < info->cAccDescr - 1) 01742 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR); 01743 } 01744 if (ret) 01745 { 01746 if (!pbFormat) 01747 *pcbFormat = bytesNeeded; 01748 else if (*pcbFormat < bytesNeeded) 01749 { 01750 *pcbFormat = bytesNeeded; 01751 SetLastError(ERROR_MORE_DATA); 01752 ret = FALSE; 01753 } 01754 else 01755 { 01756 LPWSTR str = pbFormat; 01757 DWORD altNameEntrySize; 01758 01759 *pcbFormat = bytesNeeded; 01760 for (i = 0; ret && i < info->cAccDescr; i++) 01761 { 01762 LPCSTR oidPtr; 01763 01764 *str++ = '['; 01765 sprintfW(accessDescrNum, numFmt, i + 1); 01766 strcpyW(str, accessDescrNum); 01767 str += strlenW(accessDescrNum); 01768 *str++ = ']'; 01769 strcpyW(str, aia); 01770 str += strlenW(aia); 01771 strcpyW(str, headingSep); 01772 str += strlenW(headingSep); 01773 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01774 { 01775 strcpyW(str, indent); 01776 str += strlenW(indent); 01777 } 01778 strcpyW(str, accessMethod); 01779 str += strlenW(accessMethod); 01780 if (!strcmp(info->rgAccDescr[i].pszAccessMethod, 01781 szOID_PKIX_OCSP)) 01782 { 01783 strcpyW(str, ocsp); 01784 str += strlenW(ocsp); 01785 } 01786 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod, 01787 szOID_PKIX_CA_ISSUERS)) 01788 { 01789 strcpyW(str, caIssuers); 01790 str += strlenW(caIssuers); 01791 } 01792 else 01793 { 01794 strcpyW(str, unknown); 01795 str += strlenW(unknown); 01796 } 01797 *str++ = ' '; 01798 *str++ = '('; 01799 for (oidPtr = info->rgAccDescr[i].pszAccessMethod; 01800 *oidPtr; oidPtr++, str++) 01801 *str = *oidPtr; 01802 *str++ = ')'; 01803 strcpyW(str, accessMethodSep); 01804 str += strlenW(accessMethodSep); 01805 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01806 { 01807 strcpyW(str, indent); 01808 str += strlenW(indent); 01809 } 01810 strcpyW(str, accessLocation); 01811 str += strlenW(accessLocation); 01812 strcpyW(str, locationSep); 01813 str += strlenW(locationSep); 01814 /* This overestimates the size available, but that 01815 * won't matter since we checked earlier whether enough 01816 * space for the entire string was available. 01817 */ 01818 altNameEntrySize = bytesNeeded; 01819 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2, 01820 &info->rgAccDescr[i].AccessLocation, str, 01821 &altNameEntrySize); 01822 if (ret) 01823 str += altNameEntrySize / sizeof(WCHAR) - 1; 01824 if (i < info->cAccDescr - 1) 01825 { 01826 strcpyW(str, accessMethodSep); 01827 str += strlenW(accessMethodSep); 01828 } 01829 } 01830 } 01831 } 01832 } 01833 LocalFree(info); 01834 } 01835 return ret; 01836 } 01837 01838 static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN]; 01839 static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN]; 01840 static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN]; 01841 static WCHAR superseded[MAX_STRING_RESOURCE_LEN]; 01842 static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN]; 01843 static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN]; 01844 01845 struct reason_map_entry 01846 { 01847 BYTE reasonBit; 01848 LPWSTR reason; 01849 int id; 01850 }; 01851 static struct reason_map_entry reason_map[] = { 01852 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE }, 01853 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE }, 01854 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged, 01855 IDS_REASON_AFFILIATION_CHANGED }, 01856 { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED }, 01857 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased, 01858 IDS_REASON_CESSATION_OF_OPERATION }, 01859 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold, 01860 IDS_REASON_CERTIFICATE_HOLD }, 01861 }; 01862 01863 static BOOL CRYPT_FormatReason(DWORD dwFormatStrType, 01864 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr) 01865 { 01866 static const WCHAR sep[] = { ',',' ',0 }; 01867 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 }; 01868 static BOOL stringsLoaded = FALSE; 01869 int i, numReasons = 0; 01870 BOOL ret = TRUE; 01871 DWORD bytesNeeded = sizeof(WCHAR); 01872 WCHAR bits[6]; 01873 01874 if (!stringsLoaded) 01875 { 01876 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++) 01877 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason, 01878 MAX_STRING_RESOURCE_LEN); 01879 stringsLoaded = TRUE; 01880 } 01881 /* No need to check reasonFlags->cbData, we already know it's positive. 01882 * Ignore any other bytes, as they're for undefined bits. 01883 */ 01884 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++) 01885 { 01886 if (reasonFlags->pbData[0] & reason_map[i].reasonBit) 01887 { 01888 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR); 01889 if (numReasons++) 01890 bytesNeeded += strlenW(sep) * sizeof(WCHAR); 01891 } 01892 } 01893 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]); 01894 bytesNeeded += strlenW(bits); 01895 if (!str) 01896 *pcbStr = bytesNeeded; 01897 else if (*pcbStr < bytesNeeded) 01898 { 01899 *pcbStr = bytesNeeded; 01900 SetLastError(ERROR_MORE_DATA); 01901 ret = FALSE; 01902 } 01903 else 01904 { 01905 *pcbStr = bytesNeeded; 01906 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++) 01907 { 01908 if (reasonFlags->pbData[0] & reason_map[i].reasonBit) 01909 { 01910 strcpyW(str, reason_map[i].reason); 01911 str += strlenW(reason_map[i].reason); 01912 if (i < sizeof(reason_map) / sizeof(reason_map[0]) - 1 && 01913 numReasons) 01914 { 01915 strcpyW(str, sep); 01916 str += strlenW(sep); 01917 } 01918 } 01919 } 01920 strcpyW(str, bits); 01921 } 01922 return ret; 01923 } 01924 01925 static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN]; 01926 static WCHAR distPointName[MAX_STRING_RESOURCE_LEN]; 01927 static WCHAR fullName[MAX_STRING_RESOURCE_LEN]; 01928 static WCHAR rdnName[MAX_STRING_RESOURCE_LEN]; 01929 static WCHAR reason[MAX_STRING_RESOURCE_LEN]; 01930 static WCHAR issuer[MAX_STRING_RESOURCE_LEN]; 01931 01932 static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType, 01933 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 01934 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 01935 DWORD *pcbFormat) 01936 { 01937 CRL_DIST_POINTS_INFO *info; 01938 DWORD size; 01939 BOOL ret = FALSE; 01940 01941 if (!cbEncoded) 01942 { 01943 SetLastError(E_INVALIDARG); 01944 return FALSE; 01945 } 01946 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS, 01947 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) 01948 { 01949 static const WCHAR numFmt[] = { '%','d',0 }; 01950 static const WCHAR colon[] = { ':',0 }; 01951 static BOOL stringsLoaded = FALSE; 01952 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */ 01953 BOOL haveAnEntry = FALSE; 01954 LPCWSTR headingSep, nameSep; 01955 WCHAR distPointNum[11]; 01956 DWORD i; 01957 01958 if (!stringsLoaded) 01959 { 01960 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint, 01961 sizeof(crlDistPoint) / sizeof(crlDistPoint[0])); 01962 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName, 01963 sizeof(distPointName) / sizeof(distPointName[0])); 01964 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName, 01965 sizeof(fullName) / sizeof(fullName[0])); 01966 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName, 01967 sizeof(rdnName) / sizeof(rdnName[0])); 01968 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason, 01969 sizeof(reason) / sizeof(reason[0])); 01970 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer, 01971 sizeof(issuer) / sizeof(issuer[0])); 01972 stringsLoaded = TRUE; 01973 } 01974 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 01975 { 01976 headingSep = crlf; 01977 nameSep = colonCrlf; 01978 } 01979 else 01980 { 01981 headingSep = colonSep; 01982 nameSep = colon; 01983 } 01984 01985 for (i = 0; ret && i < info->cDistPoint; i++) 01986 { 01987 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i]; 01988 01989 if (distPoint->DistPointName.dwDistPointNameChoice != 01990 CRL_DIST_POINT_NO_NAME) 01991 { 01992 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR); 01993 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR); 01994 if (distPoint->DistPointName.dwDistPointNameChoice == 01995 CRL_DIST_POINT_FULL_NAME) 01996 bytesNeeded += strlenW(fullName) * sizeof(WCHAR); 01997 else 01998 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR); 01999 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR); 02000 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 02001 bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR); 02002 /* The indent level (3) is higher than when used as the issuer, 02003 * because the name is subordinate to the name type (full vs. 02004 * RDN.) 02005 */ 02006 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3, 02007 &distPoint->DistPointName.u.FullName, NULL, &size); 02008 if (ret) 02009 bytesNeeded += size - sizeof(WCHAR); 02010 haveAnEntry = TRUE; 02011 } 02012 else if (distPoint->ReasonFlags.cbData) 02013 { 02014 bytesNeeded += strlenW(reason) * sizeof(WCHAR); 02015 ret = CRYPT_FormatReason(dwFormatStrType, 02016 &distPoint->ReasonFlags, NULL, &size); 02017 if (ret) 02018 bytesNeeded += size - sizeof(WCHAR); 02019 haveAnEntry = TRUE; 02020 } 02021 else if (distPoint->CRLIssuer.cAltEntry) 02022 { 02023 bytesNeeded += strlenW(issuer) * sizeof(WCHAR); 02024 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR); 02025 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2, 02026 &distPoint->CRLIssuer, NULL, &size); 02027 if (ret) 02028 bytesNeeded += size - sizeof(WCHAR); 02029 haveAnEntry = TRUE; 02030 } 02031 if (haveAnEntry) 02032 { 02033 bytesNeeded += sizeof(WCHAR); /* left bracket */ 02034 sprintfW(distPointNum, numFmt, i + 1); 02035 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR); 02036 bytesNeeded += sizeof(WCHAR); /* right bracket */ 02037 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR); 02038 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR); 02039 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 02040 bytesNeeded += strlenW(indent) * sizeof(WCHAR); 02041 } 02042 } 02043 if (!haveAnEntry) 02044 { 02045 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN]; 02046 02047 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, 02048 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0])); 02049 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); 02050 if (!pbFormat) 02051 *pcbFormat = bytesNeeded; 02052 else if (*pcbFormat < bytesNeeded) 02053 { 02054 *pcbFormat = bytesNeeded; 02055 SetLastError(ERROR_MORE_DATA); 02056 ret = FALSE; 02057 } 02058 else 02059 { 02060 *pcbFormat = bytesNeeded; 02061 strcpyW(pbFormat, infoNotAvailable); 02062 } 02063 } 02064 else 02065 { 02066 if (!pbFormat) 02067 *pcbFormat = bytesNeeded; 02068 else if (*pcbFormat < bytesNeeded) 02069 { 02070 *pcbFormat = bytesNeeded; 02071 SetLastError(ERROR_MORE_DATA); 02072 ret = FALSE; 02073 } 02074 else 02075 { 02076 LPWSTR str = pbFormat; 02077 02078 *pcbFormat = bytesNeeded; 02079 for (i = 0; ret && i < info->cDistPoint; i++) 02080 { 02081 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i]; 02082 02083 *str++ = '['; 02084 sprintfW(distPointNum, numFmt, i + 1); 02085 strcpyW(str, distPointNum); 02086 str += strlenW(distPointNum); 02087 *str++ = ']'; 02088 strcpyW(str, crlDistPoint); 02089 str += strlenW(crlDistPoint); 02090 strcpyW(str, headingSep); 02091 str += strlenW(headingSep); 02092 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 02093 { 02094 strcpyW(str, indent); 02095 str += strlenW(indent); 02096 } 02097 if (distPoint->DistPointName.dwDistPointNameChoice != 02098 CRL_DIST_POINT_NO_NAME) 02099 { 02100 DWORD altNameSize = bytesNeeded; 02101 02102 strcpyW(str, distPointName); 02103 str += strlenW(distPointName); 02104 strcpyW(str, nameSep); 02105 str += strlenW(nameSep); 02106 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 02107 { 02108 strcpyW(str, indent); 02109 str += strlenW(indent); 02110 strcpyW(str, indent); 02111 str += strlenW(indent); 02112 } 02113 if (distPoint->DistPointName.dwDistPointNameChoice == 02114 CRL_DIST_POINT_FULL_NAME) 02115 { 02116 strcpyW(str, fullName); 02117 str += strlenW(fullName); 02118 } 02119 else 02120 { 02121 strcpyW(str, rdnName); 02122 str += strlenW(rdnName); 02123 } 02124 strcpyW(str, nameSep); 02125 str += strlenW(nameSep); 02126 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3, 02127 &distPoint->DistPointName.u.FullName, str, 02128 &altNameSize); 02129 if (ret) 02130 str += altNameSize / sizeof(WCHAR) - 1; 02131 } 02132 else if (distPoint->ReasonFlags.cbData) 02133 { 02134 DWORD reasonSize = bytesNeeded; 02135 02136 strcpyW(str, reason); 02137 str += strlenW(reason); 02138 ret = CRYPT_FormatReason(dwFormatStrType, 02139 &distPoint->ReasonFlags, str, &reasonSize); 02140 if (ret) 02141 str += reasonSize / sizeof(WCHAR) - 1; 02142 } 02143 else if (distPoint->CRLIssuer.cAltEntry) 02144 { 02145 DWORD crlIssuerSize = bytesNeeded; 02146 02147 strcpyW(str, issuer); 02148 str += strlenW(issuer); 02149 strcpyW(str, nameSep); 02150 str += strlenW(nameSep); 02151 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2, 02152 &distPoint->CRLIssuer, str, 02153 &crlIssuerSize); 02154 if (ret) 02155 str += crlIssuerSize / sizeof(WCHAR) - 1; 02156 } 02157 } 02158 } 02159 } 02160 LocalFree(info); 02161 } 02162 return ret; 02163 } 02164 02165 static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType, 02166 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 02167 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 02168 DWORD *pcbFormat) 02169 { 02170 CERT_ENHKEY_USAGE *usage; 02171 DWORD size; 02172 BOOL ret = FALSE; 02173 02174 if (!cbEncoded) 02175 { 02176 SetLastError(E_INVALIDARG); 02177 return FALSE; 02178 } 02179 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE, 02180 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size))) 02181 { 02182 WCHAR unknown[MAX_STRING_RESOURCE_LEN]; 02183 DWORD i; 02184 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */ 02185 LPCWSTR sep; 02186 DWORD sepLen; 02187 02188 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 02189 { 02190 sep = crlf; 02191 sepLen = strlenW(crlf) * sizeof(WCHAR); 02192 } 02193 else 02194 { 02195 sep = commaSpace; 02196 sepLen = strlenW(commaSpace) * sizeof(WCHAR); 02197 } 02198 02199 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown, 02200 sizeof(unknown) / sizeof(unknown[0])); 02201 for (i = 0; i < usage->cUsageIdentifier; i++) 02202 { 02203 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, 02204 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID); 02205 02206 if (info) 02207 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR); 02208 else 02209 bytesNeeded += strlenW(unknown) * sizeof(WCHAR); 02210 bytesNeeded += sizeof(WCHAR); /* space */ 02211 bytesNeeded += sizeof(WCHAR); /* left paren */ 02212 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) * 02213 sizeof(WCHAR); 02214 bytesNeeded += sizeof(WCHAR); /* right paren */ 02215 if (i < usage->cUsageIdentifier - 1) 02216 bytesNeeded += sepLen; 02217 } 02218 if (!pbFormat) 02219 *pcbFormat = bytesNeeded; 02220 else if (*pcbFormat < bytesNeeded) 02221 { 02222 *pcbFormat = bytesNeeded; 02223 SetLastError(ERROR_MORE_DATA); 02224 ret = FALSE; 02225 } 02226 else 02227 { 02228 LPWSTR str = pbFormat; 02229 02230 *pcbFormat = bytesNeeded; 02231 for (i = 0; i < usage->cUsageIdentifier; i++) 02232 { 02233 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, 02234 usage->rgpszUsageIdentifier[i], 02235 CRYPT_ENHKEY_USAGE_OID_GROUP_ID); 02236 LPCSTR oidPtr; 02237 02238 if (info) 02239 { 02240 strcpyW(str, info->pwszName); 02241 str += strlenW(info->pwszName); 02242 } 02243 else 02244 { 02245 strcpyW(str, unknown); 02246 str += strlenW(unknown); 02247 } 02248 *str++ = ' '; 02249 *str++ = '('; 02250 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++) 02251 *str++ = *oidPtr; 02252 *str++ = ')'; 02253 *str = 0; 02254 if (i < usage->cUsageIdentifier - 1) 02255 { 02256 strcpyW(str, sep); 02257 str += sepLen / sizeof(WCHAR); 02258 } 02259 } 02260 } 02261 LocalFree(usage); 02262 } 02263 return ret; 02264 } 02265 02266 static struct BitToString netscapeCertTypeMap[] = { 02267 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } }, 02268 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } }, 02269 { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } }, 02270 { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } }, 02271 { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } }, 02272 { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } }, 02273 { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } }, 02274 }; 02275 02276 static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType, 02277 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 02278 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 02279 DWORD *pcbFormat) 02280 { 02281 DWORD size; 02282 CRYPT_BIT_BLOB *bits; 02283 BOOL ret; 02284 02285 if (!cbEncoded) 02286 { 02287 SetLastError(E_INVALIDARG); 02288 return FALSE; 02289 } 02290 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS, 02291 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size))) 02292 { 02293 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN]; 02294 DWORD bytesNeeded = sizeof(WCHAR); 02295 02296 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, 02297 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0])); 02298 if (!bits->cbData || bits->cbData > 1) 02299 { 02300 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR); 02301 if (!pbFormat) 02302 *pcbFormat = bytesNeeded; 02303 else if (*pcbFormat < bytesNeeded) 02304 { 02305 *pcbFormat = bytesNeeded; 02306 SetLastError(ERROR_MORE_DATA); 02307 ret = FALSE; 02308 } 02309 else 02310 { 02311 LPWSTR str = pbFormat; 02312 02313 *pcbFormat = bytesNeeded; 02314 strcpyW(str, infoNotAvailable); 02315 } 02316 } 02317 else 02318 { 02319 static BOOL stringsLoaded = FALSE; 02320 int i; 02321 DWORD bitStringLen; 02322 BOOL first = TRUE; 02323 02324 if (!stringsLoaded) 02325 { 02326 for (i = 0; i < sizeof(netscapeCertTypeMap) / 02327 sizeof(netscapeCertTypeMap[0]); i++) 02328 LoadStringW(hInstance, netscapeCertTypeMap[i].id, 02329 netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN); 02330 stringsLoaded = TRUE; 02331 } 02332 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap, 02333 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]), 02334 NULL, &bitStringLen, &first); 02335 bytesNeeded += bitStringLen; 02336 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */ 02337 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, 02338 bits->cbData, NULL, &size); 02339 bytesNeeded += size; 02340 if (!pbFormat) 02341 *pcbFormat = bytesNeeded; 02342 else if (*pcbFormat < bytesNeeded) 02343 { 02344 *pcbFormat = bytesNeeded; 02345 SetLastError(ERROR_MORE_DATA); 02346 ret = FALSE; 02347 } 02348 else 02349 { 02350 LPWSTR str = pbFormat; 02351 02352 bitStringLen = bytesNeeded; 02353 first = TRUE; 02354 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap, 02355 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]), 02356 str, &bitStringLen, &first); 02357 str += bitStringLen / sizeof(WCHAR) - 1; 02358 *str++ = ' '; 02359 *str++ = '('; 02360 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData, 02361 bits->cbData, str, &size); 02362 str += size / sizeof(WCHAR) - 1; 02363 *str++ = ')'; 02364 *str = 0; 02365 } 02366 } 02367 LocalFree(bits); 02368 } 02369 return ret; 02370 } 02371 02372 static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN]; 02373 static WCHAR available[MAX_STRING_RESOURCE_LEN]; 02374 static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN]; 02375 static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN]; 02376 static WCHAR yes[MAX_STRING_RESOURCE_LEN]; 02377 static WCHAR no[MAX_STRING_RESOURCE_LEN]; 02378 02379 static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType, 02380 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 02381 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 02382 DWORD *pcbFormat) 02383 { 02384 SPC_FINANCIAL_CRITERIA criteria; 02385 DWORD size = sizeof(criteria); 02386 BOOL ret = FALSE; 02387 02388 if (!cbEncoded) 02389 { 02390 SetLastError(E_INVALIDARG); 02391 return FALSE; 02392 } 02393 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, 02394 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria, 02395 &size))) 02396 { 02397 static BOOL stringsLoaded = FALSE; 02398 DWORD bytesNeeded = sizeof(WCHAR); 02399 LPCWSTR sep; 02400 DWORD sepLen; 02401 02402 if (!stringsLoaded) 02403 { 02404 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria, 02405 sizeof(financialCriteria) / sizeof(financialCriteria[0])); 02406 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available, 02407 sizeof(available) / sizeof(available[0])); 02408 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE, 02409 notAvailable, sizeof(notAvailable) / sizeof(notAvailable[0])); 02410 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA, 02411 meetsCriteria, sizeof(meetsCriteria) / sizeof(meetsCriteria[0])); 02412 LoadStringW(hInstance, IDS_YES, yes, sizeof(yes) / sizeof(yes[0])); 02413 LoadStringW(hInstance, IDS_NO, no, sizeof(no) / sizeof(no[0])); 02414 stringsLoaded = TRUE; 02415 } 02416 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) 02417 { 02418 sep = crlf; 02419 sepLen = strlenW(crlf) * sizeof(WCHAR); 02420 } 02421 else 02422 { 02423 sep = commaSpace; 02424 sepLen = strlenW(commaSpace) * sizeof(WCHAR); 02425 } 02426 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR); 02427 if (criteria.fFinancialInfoAvailable) 02428 { 02429 bytesNeeded += strlenW(available) * sizeof(WCHAR); 02430 bytesNeeded += sepLen; 02431 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR); 02432 if (criteria.fMeetsCriteria) 02433 bytesNeeded += strlenW(yes) * sizeof(WCHAR); 02434 else 02435 bytesNeeded += strlenW(no) * sizeof(WCHAR); 02436 } 02437 else 02438 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR); 02439 if (!pbFormat) 02440 *pcbFormat = bytesNeeded; 02441 else if (*pcbFormat < bytesNeeded) 02442 { 02443 *pcbFormat = bytesNeeded; 02444 SetLastError(ERROR_MORE_DATA); 02445 ret = FALSE; 02446 } 02447 else 02448 { 02449 LPWSTR str = pbFormat; 02450 02451 *pcbFormat = bytesNeeded; 02452 strcpyW(str, financialCriteria); 02453 str += strlenW(financialCriteria); 02454 if (criteria.fFinancialInfoAvailable) 02455 { 02456 strcpyW(str, available); 02457 str += strlenW(available); 02458 strcpyW(str, sep); 02459 str += sepLen / sizeof(WCHAR); 02460 strcpyW(str, meetsCriteria); 02461 str += strlenW(meetsCriteria); 02462 if (criteria.fMeetsCriteria) 02463 strcpyW(str, yes); 02464 else 02465 strcpyW(str, no); 02466 } 02467 else 02468 { 02469 strcpyW(str, notAvailable); 02470 } 02471 } 02472 } 02473 return ret; 02474 } 02475 02476 static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType, 02477 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, 02478 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, 02479 DWORD *pcbFormat) 02480 { 02481 CERT_NAME_VALUE *value; 02482 DWORD size; 02483 BOOL ret; 02484 02485 if (!cbEncoded) 02486 { 02487 SetLastError(E_INVALIDARG); 02488 return FALSE; 02489 } 02490 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING, 02491 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size))) 02492 { 02493 if (!pbFormat) 02494 *pcbFormat = value->Value.cbData; 02495 else if (*pcbFormat < value->Value.cbData) 02496 { 02497 *pcbFormat = value->Value.cbData; 02498 SetLastError(ERROR_MORE_DATA); 02499 ret = FALSE; 02500 } 02501 else 02502 { 02503 LPWSTR str = pbFormat; 02504 02505 *pcbFormat = value->Value.cbData; 02506 strcpyW(str, (LPWSTR)value->Value.pbData); 02507 } 02508 } 02509 return ret; 02510 } 02511 02512 typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *, 02513 LPCSTR, const BYTE *, DWORD, void *, DWORD *); 02514 02515 static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType, 02516 DWORD formatStrType, LPCSTR lpszStructType) 02517 { 02518 CryptFormatObjectFunc format = NULL; 02519 02520 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) 02521 { 02522 SetLastError(ERROR_FILE_NOT_FOUND); 02523 return NULL; 02524 } 02525 if (IS_INTOID(lpszStructType)) 02526 { 02527 switch (LOWORD(lpszStructType)) 02528 { 02529 case LOWORD(X509_KEY_USAGE): 02530 format = CRYPT_FormatKeyUsage; 02531 break; 02532 case LOWORD(X509_ALTERNATE_NAME): 02533 format = CRYPT_FormatAltName; 02534 break; 02535 case LOWORD(X509_BASIC_CONSTRAINTS2): 02536 format = CRYPT_FormatBasicConstraints2; 02537 break; 02538 case LOWORD(X509_AUTHORITY_KEY_ID2): 02539 format = CRYPT_FormatAuthorityKeyId2; 02540 break; 02541 case LOWORD(X509_AUTHORITY_INFO_ACCESS): 02542 format = CRYPT_FormatAuthorityInfoAccess; 02543 break; 02544 case LOWORD(X509_CRL_DIST_POINTS): 02545 format = CRYPT_FormatCRLDistPoints; 02546 break; 02547 case LOWORD(X509_ENHANCED_KEY_USAGE): 02548 format = CRYPT_FormatEnhancedKeyUsage; 02549 break; 02550 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT): 02551 format = CRYPT_FormatSpcFinancialCriteria; 02552 break; 02553 } 02554 } 02555 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) 02556 format = CRYPT_FormatAltName; 02557 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) 02558 format = CRYPT_FormatAltName; 02559 else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) 02560 format = CRYPT_FormatKeyUsage; 02561 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) 02562 format = CRYPT_FormatAltName; 02563 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) 02564 format = CRYPT_FormatAltName; 02565 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) 02566 format = CRYPT_FormatBasicConstraints2; 02567 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) 02568 format = CRYPT_FormatAuthorityInfoAccess; 02569 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) 02570 format = CRYPT_FormatAuthorityKeyId2; 02571 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) 02572 format = CRYPT_FormatCRLDistPoints; 02573 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) 02574 format = CRYPT_FormatEnhancedKeyUsage; 02575 else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE)) 02576 format = CRYPT_FormatNetscapeCertType; 02577 else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) || 02578 !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) || 02579 !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) || 02580 !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) || 02581 !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) || 02582 !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) || 02583 !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT)) 02584 format = CRYPT_FormatUnicodeString; 02585 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID)) 02586 format = CRYPT_FormatSpcFinancialCriteria; 02587 return format; 02588 } 02589 02590 BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType, 02591 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, 02592 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat) 02593 { 02594 CryptFormatObjectFunc format = NULL; 02595 HCRYPTOIDFUNCADDR hFunc = NULL; 02596 BOOL ret = FALSE; 02597 02598 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType, 02599 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType), 02600 pbEncoded, cbEncoded, pbFormat, pcbFormat); 02601 02602 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType, 02603 dwFormatStrType, lpszStructType))) 02604 { 02605 static HCRYPTOIDFUNCSET set = NULL; 02606 02607 if (!set) 02608 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0); 02609 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, 02610 (void **)&format, &hFunc); 02611 } 02612 if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) == 02613 X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX)) 02614 format = CRYPT_FormatHexString; 02615 if (format) 02616 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType, 02617 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat, 02618 pcbFormat); 02619 if (hFunc) 02620 CryptFreeOIDFunctionAddress(hFunc, 0); 02621 return ret; 02622 } Generated on Mon May 28 2012 04:22:56 for ReactOS by
1.7.6.1
|