Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencert.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2004-2006 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 * 00018 */ 00019 00020 #include <assert.h> 00021 #include <stdarg.h> 00022 00023 #define NONAMELESSUNION 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "wincrypt.h" 00027 #include "winnls.h" 00028 #include "rpc.h" 00029 #include "wine/debug.h" 00030 #include "wine/unicode.h" 00031 #include "crypt32_private.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00034 00035 /* Internal version of CertGetCertificateContextProperty that gets properties 00036 * directly from the context (or the context it's linked to, depending on its 00037 * type.) Doesn't handle special-case properties, since they are handled by 00038 * CertGetCertificateContextProperty, and are particular to the store in which 00039 * the property exists (which is separate from the context.) 00040 */ 00041 static BOOL CertContext_GetProperty(void *context, DWORD dwPropId, 00042 void *pvData, DWORD *pcbData); 00043 00044 /* Internal version of CertSetCertificateContextProperty that sets properties 00045 * directly on the context (or the context it's linked to, depending on its 00046 * type.) Doesn't handle special cases, since they're handled by 00047 * CertSetCertificateContextProperty anyway. 00048 */ 00049 static BOOL CertContext_SetProperty(void *context, DWORD dwPropId, 00050 DWORD dwFlags, const void *pvData); 00051 00052 BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore, 00053 DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded, 00054 DWORD dwAddDisposition, PCCERT_CONTEXT *ppCertContext) 00055 { 00056 PCCERT_CONTEXT cert = CertCreateCertificateContext(dwCertEncodingType, 00057 pbCertEncoded, cbCertEncoded); 00058 BOOL ret; 00059 00060 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore, dwCertEncodingType, 00061 pbCertEncoded, cbCertEncoded, dwAddDisposition, ppCertContext); 00062 00063 if (cert) 00064 { 00065 ret = CertAddCertificateContextToStore(hCertStore, cert, 00066 dwAddDisposition, ppCertContext); 00067 CertFreeCertificateContext(cert); 00068 } 00069 else 00070 ret = FALSE; 00071 return ret; 00072 } 00073 00074 BOOL WINAPI CertAddEncodedCertificateToSystemStoreA(LPCSTR pszCertStoreName, 00075 const BYTE *pbCertEncoded, DWORD cbCertEncoded) 00076 { 00077 HCERTSTORE store; 00078 BOOL ret = FALSE; 00079 00080 TRACE("(%s, %p, %d)\n", debugstr_a(pszCertStoreName), pbCertEncoded, 00081 cbCertEncoded); 00082 00083 store = CertOpenSystemStoreA(0, pszCertStoreName); 00084 if (store) 00085 { 00086 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 00087 pbCertEncoded, cbCertEncoded, CERT_STORE_ADD_USE_EXISTING, NULL); 00088 CertCloseStore(store, 0); 00089 } 00090 return ret; 00091 } 00092 00093 BOOL WINAPI CertAddEncodedCertificateToSystemStoreW(LPCWSTR pszCertStoreName, 00094 const BYTE *pbCertEncoded, DWORD cbCertEncoded) 00095 { 00096 HCERTSTORE store; 00097 BOOL ret = FALSE; 00098 00099 TRACE("(%s, %p, %d)\n", debugstr_w(pszCertStoreName), pbCertEncoded, 00100 cbCertEncoded); 00101 00102 store = CertOpenSystemStoreW(0, pszCertStoreName); 00103 if (store) 00104 { 00105 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 00106 pbCertEncoded, cbCertEncoded, CERT_STORE_ADD_USE_EXISTING, NULL); 00107 CertCloseStore(store, 0); 00108 } 00109 return ret; 00110 } 00111 00112 BOOL WINAPI CertAddCertificateLinkToStore(HCERTSTORE hCertStore, 00113 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition, 00114 PCCERT_CONTEXT *ppCertContext) 00115 { 00116 static int calls; 00117 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore; 00118 00119 if (!(calls++)) 00120 FIXME("(%p, %p, %08x, %p): semi-stub\n", hCertStore, pCertContext, 00121 dwAddDisposition, ppCertContext); 00122 if (store->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) 00123 return FALSE; 00124 if (store->type == StoreTypeCollection) 00125 { 00126 SetLastError(E_INVALIDARG); 00127 return FALSE; 00128 } 00129 return CertAddCertificateContextToStore(hCertStore, pCertContext, 00130 dwAddDisposition, ppCertContext); 00131 } 00132 00133 PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType, 00134 const BYTE *pbCertEncoded, DWORD cbCertEncoded) 00135 { 00136 PCERT_CONTEXT cert = NULL; 00137 BOOL ret; 00138 PCERT_INFO certInfo = NULL; 00139 DWORD size = 0; 00140 00141 TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCertEncoded, 00142 cbCertEncoded); 00143 00144 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) 00145 { 00146 SetLastError(E_INVALIDARG); 00147 return NULL; 00148 } 00149 00150 ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_TO_BE_SIGNED, 00151 pbCertEncoded, cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, 00152 &certInfo, &size); 00153 if (ret) 00154 { 00155 BYTE *data = NULL; 00156 00157 cert = Context_CreateDataContext(sizeof(CERT_CONTEXT)); 00158 if (!cert) 00159 goto end; 00160 data = CryptMemAlloc(cbCertEncoded); 00161 if (!data) 00162 { 00163 CertFreeCertificateContext(cert); 00164 cert = NULL; 00165 goto end; 00166 } 00167 memcpy(data, pbCertEncoded, cbCertEncoded); 00168 cert->dwCertEncodingType = dwCertEncodingType; 00169 cert->pbCertEncoded = data; 00170 cert->cbCertEncoded = cbCertEncoded; 00171 cert->pCertInfo = certInfo; 00172 cert->hCertStore = 0; 00173 } 00174 00175 end: 00176 return cert; 00177 } 00178 00179 PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext( 00180 PCCERT_CONTEXT pCertContext) 00181 { 00182 TRACE("(%p)\n", pCertContext); 00183 00184 if (!pCertContext) 00185 return NULL; 00186 00187 Context_AddRef((void *)pCertContext, sizeof(CERT_CONTEXT)); 00188 return pCertContext; 00189 } 00190 00191 static void CertDataContext_Free(void *context) 00192 { 00193 PCERT_CONTEXT certContext = context; 00194 00195 CryptMemFree(certContext->pbCertEncoded); 00196 LocalFree(certContext->pCertInfo); 00197 } 00198 00199 BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext) 00200 { 00201 BOOL ret = TRUE; 00202 00203 TRACE("(%p)\n", pCertContext); 00204 00205 if (pCertContext) 00206 ret = Context_Release((void *)pCertContext, sizeof(CERT_CONTEXT), 00207 CertDataContext_Free); 00208 return ret; 00209 } 00210 00211 DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext, 00212 DWORD dwPropId) 00213 { 00214 PCONTEXT_PROPERTY_LIST properties = Context_GetProperties( 00215 pCertContext, sizeof(CERT_CONTEXT)); 00216 DWORD ret; 00217 00218 TRACE("(%p, %d)\n", pCertContext, dwPropId); 00219 00220 if (properties) 00221 ret = ContextPropertyList_EnumPropIDs(properties, dwPropId); 00222 else 00223 ret = 0; 00224 return ret; 00225 } 00226 00227 static BOOL CertContext_GetHashProp(void *context, DWORD dwPropId, 00228 ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData, 00229 DWORD *pcbData) 00230 { 00231 BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData, 00232 pcbData); 00233 if (ret && pvData) 00234 { 00235 CRYPT_DATA_BLOB blob = { *pcbData, pvData }; 00236 00237 ret = CertContext_SetProperty(context, dwPropId, 0, &blob); 00238 } 00239 return ret; 00240 } 00241 00242 static BOOL CertContext_CopyParam(void *pvData, DWORD *pcbData, const void *pb, 00243 DWORD cb) 00244 { 00245 BOOL ret = TRUE; 00246 00247 if (!pvData) 00248 *pcbData = cb; 00249 else if (*pcbData < cb) 00250 { 00251 SetLastError(ERROR_MORE_DATA); 00252 *pcbData = cb; 00253 ret = FALSE; 00254 } 00255 else 00256 { 00257 memcpy(pvData, pb, cb); 00258 *pcbData = cb; 00259 } 00260 return ret; 00261 } 00262 00263 static BOOL CertContext_GetProperty(void *context, DWORD dwPropId, 00264 void *pvData, DWORD *pcbData) 00265 { 00266 PCCERT_CONTEXT pCertContext = context; 00267 PCONTEXT_PROPERTY_LIST properties = 00268 Context_GetProperties(context, sizeof(CERT_CONTEXT)); 00269 BOOL ret; 00270 CRYPT_DATA_BLOB blob; 00271 00272 TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData); 00273 00274 if (properties) 00275 ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob); 00276 else 00277 ret = FALSE; 00278 if (ret) 00279 ret = CertContext_CopyParam(pvData, pcbData, blob.pbData, blob.cbData); 00280 else 00281 { 00282 /* Implicit properties */ 00283 switch (dwPropId) 00284 { 00285 case CERT_SHA1_HASH_PROP_ID: 00286 ret = CertContext_GetHashProp(context, dwPropId, CALG_SHA1, 00287 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData, 00288 pcbData); 00289 break; 00290 case CERT_MD5_HASH_PROP_ID: 00291 ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5, 00292 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData, 00293 pcbData); 00294 break; 00295 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID: 00296 ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5, 00297 pCertContext->pCertInfo->Subject.pbData, 00298 pCertContext->pCertInfo->Subject.cbData, 00299 pvData, pcbData); 00300 break; 00301 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: 00302 ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5, 00303 pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, 00304 pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, 00305 pvData, pcbData); 00306 break; 00307 case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID: 00308 ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5, 00309 pCertContext->pCertInfo->SerialNumber.pbData, 00310 pCertContext->pCertInfo->SerialNumber.cbData, 00311 pvData, pcbData); 00312 break; 00313 case CERT_SIGNATURE_HASH_PROP_ID: 00314 ret = CryptHashToBeSigned(0, pCertContext->dwCertEncodingType, 00315 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData, 00316 pcbData); 00317 if (ret && pvData) 00318 { 00319 CRYPT_DATA_BLOB blob = { *pcbData, pvData }; 00320 00321 ret = CertContext_SetProperty(context, dwPropId, 0, &blob); 00322 } 00323 break; 00324 case CERT_KEY_IDENTIFIER_PROP_ID: 00325 { 00326 PCERT_EXTENSION ext = CertFindExtension( 00327 szOID_SUBJECT_KEY_IDENTIFIER, pCertContext->pCertInfo->cExtension, 00328 pCertContext->pCertInfo->rgExtension); 00329 00330 if (ext) 00331 { 00332 CRYPT_DATA_BLOB value; 00333 DWORD size = sizeof(value); 00334 00335 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, 00336 szOID_SUBJECT_KEY_IDENTIFIER, ext->Value.pbData, 00337 ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL, &value, 00338 &size); 00339 if (ret) 00340 { 00341 ret = CertContext_CopyParam(pvData, pcbData, value.pbData, 00342 value.cbData); 00343 CertContext_SetProperty(context, dwPropId, 0, &value); 00344 } 00345 } 00346 else 00347 SetLastError(ERROR_INVALID_DATA); 00348 break; 00349 } 00350 default: 00351 SetLastError(CRYPT_E_NOT_FOUND); 00352 } 00353 } 00354 TRACE("returning %d\n", ret); 00355 return ret; 00356 } 00357 00358 void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info) 00359 { 00360 DWORD i, containerLen, provNameLen; 00361 LPBYTE data = (LPBYTE)info + sizeof(CRYPT_KEY_PROV_INFO); 00362 00363 info->pwszContainerName = (LPWSTR)data; 00364 containerLen = (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); 00365 data += containerLen; 00366 00367 info->pwszProvName = (LPWSTR)data; 00368 provNameLen = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); 00369 data += provNameLen; 00370 00371 info->rgProvParam = (PCRYPT_KEY_PROV_PARAM)data; 00372 data += info->cProvParam * sizeof(CRYPT_KEY_PROV_PARAM); 00373 00374 for (i = 0; i < info->cProvParam; i++) 00375 { 00376 info->rgProvParam[i].pbData = data; 00377 data += info->rgProvParam[i].cbData; 00378 } 00379 } 00380 00381 BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, 00382 DWORD dwPropId, void *pvData, DWORD *pcbData) 00383 { 00384 BOOL ret; 00385 00386 TRACE("(%p, %d, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData); 00387 00388 switch (dwPropId) 00389 { 00390 case 0: 00391 case CERT_CERT_PROP_ID: 00392 case CERT_CRL_PROP_ID: 00393 case CERT_CTL_PROP_ID: 00394 SetLastError(E_INVALIDARG); 00395 ret = FALSE; 00396 break; 00397 case CERT_ACCESS_STATE_PROP_ID: 00398 if (pCertContext->hCertStore) 00399 ret = CertGetStoreProperty(pCertContext->hCertStore, dwPropId, 00400 pvData, pcbData); 00401 else 00402 { 00403 DWORD state = 0; 00404 00405 ret = CertContext_CopyParam(pvData, pcbData, &state, sizeof(state)); 00406 } 00407 break; 00408 case CERT_KEY_PROV_HANDLE_PROP_ID: 00409 { 00410 CERT_KEY_CONTEXT keyContext; 00411 DWORD size = sizeof(keyContext); 00412 00413 ret = CertContext_GetProperty((void *)pCertContext, 00414 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size); 00415 if (ret) 00416 ret = CertContext_CopyParam(pvData, pcbData, &keyContext.hCryptProv, 00417 sizeof(keyContext.hCryptProv)); 00418 break; 00419 } 00420 case CERT_KEY_PROV_INFO_PROP_ID: 00421 ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData, 00422 pcbData); 00423 if (ret && pvData) 00424 CRYPT_FixKeyProvInfoPointers(pvData); 00425 break; 00426 default: 00427 ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData, 00428 pcbData); 00429 } 00430 00431 TRACE("returning %d\n", ret); 00432 return ret; 00433 } 00434 00435 /* Copies key provider info from from into to, where to is assumed to be a 00436 * contiguous buffer of memory large enough for from and all its associated 00437 * data, but whose pointers are uninitialized. 00438 * Upon return, to contains a contiguous copy of from, packed in the following 00439 * order: 00440 * - CRYPT_KEY_PROV_INFO 00441 * - pwszContainerName 00442 * - pwszProvName 00443 * - rgProvParam[0]... 00444 */ 00445 static void CRYPT_CopyKeyProvInfo(PCRYPT_KEY_PROV_INFO to, 00446 const CRYPT_KEY_PROV_INFO *from) 00447 { 00448 DWORD i; 00449 LPBYTE nextData = (LPBYTE)to + sizeof(CRYPT_KEY_PROV_INFO); 00450 00451 if (from->pwszContainerName) 00452 { 00453 to->pwszContainerName = (LPWSTR)nextData; 00454 lstrcpyW(to->pwszContainerName, from->pwszContainerName); 00455 nextData += (lstrlenW(from->pwszContainerName) + 1) * sizeof(WCHAR); 00456 } 00457 else 00458 to->pwszContainerName = NULL; 00459 if (from->pwszProvName) 00460 { 00461 to->pwszProvName = (LPWSTR)nextData; 00462 lstrcpyW(to->pwszProvName, from->pwszProvName); 00463 nextData += (lstrlenW(from->pwszProvName) + 1) * sizeof(WCHAR); 00464 } 00465 else 00466 to->pwszProvName = NULL; 00467 to->dwProvType = from->dwProvType; 00468 to->dwFlags = from->dwFlags; 00469 to->cProvParam = from->cProvParam; 00470 to->rgProvParam = (PCRYPT_KEY_PROV_PARAM)nextData; 00471 nextData += to->cProvParam * sizeof(CRYPT_KEY_PROV_PARAM); 00472 to->dwKeySpec = from->dwKeySpec; 00473 for (i = 0; i < to->cProvParam; i++) 00474 { 00475 memcpy(&to->rgProvParam[i], &from->rgProvParam[i], 00476 sizeof(CRYPT_KEY_PROV_PARAM)); 00477 to->rgProvParam[i].pbData = nextData; 00478 memcpy(to->rgProvParam[i].pbData, from->rgProvParam[i].pbData, 00479 from->rgProvParam[i].cbData); 00480 nextData += from->rgProvParam[i].cbData; 00481 } 00482 } 00483 00484 static BOOL CertContext_SetKeyProvInfoProperty(PCONTEXT_PROPERTY_LIST properties, 00485 const CRYPT_KEY_PROV_INFO *info) 00486 { 00487 BOOL ret; 00488 LPBYTE buf = NULL; 00489 DWORD size = sizeof(CRYPT_KEY_PROV_INFO), i, containerSize, provNameSize; 00490 00491 if (info->pwszContainerName) 00492 containerSize = (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); 00493 else 00494 containerSize = 0; 00495 if (info->pwszProvName) 00496 provNameSize = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); 00497 else 00498 provNameSize = 0; 00499 size += containerSize + provNameSize; 00500 for (i = 0; i < info->cProvParam; i++) 00501 size += sizeof(CRYPT_KEY_PROV_PARAM) + info->rgProvParam[i].cbData; 00502 buf = CryptMemAlloc(size); 00503 if (buf) 00504 { 00505 CRYPT_CopyKeyProvInfo((PCRYPT_KEY_PROV_INFO)buf, info); 00506 ret = ContextPropertyList_SetProperty(properties, 00507 CERT_KEY_PROV_INFO_PROP_ID, buf, size); 00508 CryptMemFree(buf); 00509 } 00510 else 00511 ret = FALSE; 00512 return ret; 00513 } 00514 00515 static BOOL CertContext_SetProperty(void *context, DWORD dwPropId, 00516 DWORD dwFlags, const void *pvData) 00517 { 00518 PCONTEXT_PROPERTY_LIST properties = 00519 Context_GetProperties(context, sizeof(CERT_CONTEXT)); 00520 BOOL ret; 00521 00522 TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData); 00523 00524 if (!properties) 00525 ret = FALSE; 00526 else 00527 { 00528 switch (dwPropId) 00529 { 00530 case CERT_AUTO_ENROLL_PROP_ID: 00531 case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */ 00532 case CERT_DESCRIPTION_PROP_ID: 00533 case CERT_FRIENDLY_NAME_PROP_ID: 00534 case CERT_HASH_PROP_ID: 00535 case CERT_KEY_IDENTIFIER_PROP_ID: 00536 case CERT_MD5_HASH_PROP_ID: 00537 case CERT_NEXT_UPDATE_LOCATION_PROP_ID: 00538 case CERT_PUBKEY_ALG_PARA_PROP_ID: 00539 case CERT_PVK_FILE_PROP_ID: 00540 case CERT_SIGNATURE_HASH_PROP_ID: 00541 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID: 00542 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID: 00543 case CERT_EXTENDED_ERROR_INFO_PROP_ID: 00544 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: 00545 case CERT_ENROLLMENT_PROP_ID: 00546 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID: 00547 case CERT_RENEWAL_PROP_ID: 00548 { 00549 if (pvData) 00550 { 00551 const CRYPT_DATA_BLOB *blob = pvData; 00552 00553 ret = ContextPropertyList_SetProperty(properties, dwPropId, 00554 blob->pbData, blob->cbData); 00555 } 00556 else 00557 { 00558 ContextPropertyList_RemoveProperty(properties, dwPropId); 00559 ret = TRUE; 00560 } 00561 break; 00562 } 00563 case CERT_DATE_STAMP_PROP_ID: 00564 if (pvData) 00565 ret = ContextPropertyList_SetProperty(properties, dwPropId, 00566 pvData, sizeof(FILETIME)); 00567 else 00568 { 00569 ContextPropertyList_RemoveProperty(properties, dwPropId); 00570 ret = TRUE; 00571 } 00572 break; 00573 case CERT_KEY_CONTEXT_PROP_ID: 00574 { 00575 if (pvData) 00576 { 00577 const CERT_KEY_CONTEXT *keyContext = pvData; 00578 00579 if (keyContext->cbSize != sizeof(CERT_KEY_CONTEXT)) 00580 { 00581 SetLastError(E_INVALIDARG); 00582 ret = FALSE; 00583 } 00584 else 00585 ret = ContextPropertyList_SetProperty(properties, dwPropId, 00586 (const BYTE *)keyContext, keyContext->cbSize); 00587 } 00588 else 00589 { 00590 ContextPropertyList_RemoveProperty(properties, dwPropId); 00591 ret = TRUE; 00592 } 00593 break; 00594 } 00595 case CERT_KEY_PROV_INFO_PROP_ID: 00596 if (pvData) 00597 ret = CertContext_SetKeyProvInfoProperty(properties, pvData); 00598 else 00599 { 00600 ContextPropertyList_RemoveProperty(properties, dwPropId); 00601 ret = TRUE; 00602 } 00603 break; 00604 case CERT_KEY_PROV_HANDLE_PROP_ID: 00605 { 00606 CERT_KEY_CONTEXT keyContext; 00607 DWORD size = sizeof(keyContext); 00608 00609 ret = CertContext_GetProperty(context, CERT_KEY_CONTEXT_PROP_ID, 00610 &keyContext, &size); 00611 if (ret) 00612 { 00613 if (!(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) 00614 CryptReleaseContext(keyContext.hCryptProv, 0); 00615 } 00616 keyContext.cbSize = sizeof(keyContext); 00617 if (pvData) 00618 keyContext.hCryptProv = *(const HCRYPTPROV *)pvData; 00619 else 00620 { 00621 keyContext.hCryptProv = 0; 00622 keyContext.dwKeySpec = AT_SIGNATURE; 00623 } 00624 ret = CertContext_SetProperty(context, CERT_KEY_CONTEXT_PROP_ID, 00625 0, &keyContext); 00626 break; 00627 } 00628 default: 00629 FIXME("%d: stub\n", dwPropId); 00630 ret = FALSE; 00631 } 00632 } 00633 TRACE("returning %d\n", ret); 00634 return ret; 00635 } 00636 00637 BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext, 00638 DWORD dwPropId, DWORD dwFlags, const void *pvData) 00639 { 00640 BOOL ret; 00641 00642 TRACE("(%p, %d, %08x, %p)\n", pCertContext, dwPropId, dwFlags, pvData); 00643 00644 /* Handle special cases for "read-only"/invalid prop IDs. Windows just 00645 * crashes on most of these, I'll be safer. 00646 */ 00647 switch (dwPropId) 00648 { 00649 case 0: 00650 case CERT_ACCESS_STATE_PROP_ID: 00651 case CERT_CERT_PROP_ID: 00652 case CERT_CRL_PROP_ID: 00653 case CERT_CTL_PROP_ID: 00654 SetLastError(E_INVALIDARG); 00655 return FALSE; 00656 } 00657 ret = CertContext_SetProperty((void *)pCertContext, dwPropId, dwFlags, 00658 pvData); 00659 TRACE("returning %d\n", ret); 00660 return ret; 00661 } 00662 00663 /* Acquires the private key using the key provider info, retrieving info from 00664 * the certificate if info is NULL. The acquired provider is returned in 00665 * *phCryptProv, and the key spec for the provider is returned in *pdwKeySpec. 00666 */ 00667 static BOOL CRYPT_AcquirePrivateKeyFromProvInfo(PCCERT_CONTEXT pCert, 00668 PCRYPT_KEY_PROV_INFO info, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec) 00669 { 00670 DWORD size = 0; 00671 BOOL allocated = FALSE, ret = TRUE; 00672 00673 if (!info) 00674 { 00675 ret = CertGetCertificateContextProperty(pCert, 00676 CERT_KEY_PROV_INFO_PROP_ID, 0, &size); 00677 if (ret) 00678 { 00679 info = HeapAlloc(GetProcessHeap(), 0, size); 00680 if (info) 00681 { 00682 ret = CertGetCertificateContextProperty(pCert, 00683 CERT_KEY_PROV_INFO_PROP_ID, info, &size); 00684 allocated = TRUE; 00685 } 00686 else 00687 { 00688 SetLastError(ERROR_OUTOFMEMORY); 00689 ret = FALSE; 00690 } 00691 } 00692 else 00693 SetLastError(CRYPT_E_NO_KEY_PROPERTY); 00694 } 00695 if (ret) 00696 { 00697 ret = CryptAcquireContextW(phCryptProv, info->pwszContainerName, 00698 info->pwszProvName, info->dwProvType, 0); 00699 if (ret) 00700 { 00701 DWORD i; 00702 00703 for (i = 0; i < info->cProvParam; i++) 00704 { 00705 CryptSetProvParam(*phCryptProv, 00706 info->rgProvParam[i].dwParam, info->rgProvParam[i].pbData, 00707 info->rgProvParam[i].dwFlags); 00708 } 00709 *pdwKeySpec = info->dwKeySpec; 00710 } 00711 else 00712 SetLastError(CRYPT_E_NO_KEY_PROPERTY); 00713 } 00714 if (allocated) 00715 HeapFree(GetProcessHeap(), 0, info); 00716 return ret; 00717 } 00718 00719 BOOL WINAPI CryptAcquireCertificatePrivateKey(PCCERT_CONTEXT pCert, 00720 DWORD dwFlags, void *pvReserved, HCRYPTPROV_OR_NCRYPT_KEY_HANDLE *phCryptProv, 00721 DWORD *pdwKeySpec, BOOL *pfCallerFreeProv) 00722 { 00723 BOOL ret = FALSE, cache = FALSE; 00724 PCRYPT_KEY_PROV_INFO info = NULL; 00725 CERT_KEY_CONTEXT keyContext; 00726 DWORD size; 00727 00728 TRACE("(%p, %08x, %p, %p, %p, %p)\n", pCert, dwFlags, pvReserved, 00729 phCryptProv, pdwKeySpec, pfCallerFreeProv); 00730 00731 if (dwFlags & CRYPT_ACQUIRE_USE_PROV_INFO_FLAG) 00732 { 00733 DWORD size = 0; 00734 00735 ret = CertGetCertificateContextProperty(pCert, 00736 CERT_KEY_PROV_INFO_PROP_ID, 0, &size); 00737 if (ret) 00738 { 00739 info = HeapAlloc(GetProcessHeap(), 0, size); 00740 ret = CertGetCertificateContextProperty(pCert, 00741 CERT_KEY_PROV_INFO_PROP_ID, info, &size); 00742 if (ret) 00743 cache = info->dwFlags & CERT_SET_KEY_CONTEXT_PROP_ID; 00744 } 00745 } 00746 else if (dwFlags & CRYPT_ACQUIRE_CACHE_FLAG) 00747 cache = TRUE; 00748 *phCryptProv = 0; 00749 if (cache) 00750 { 00751 size = sizeof(keyContext); 00752 ret = CertGetCertificateContextProperty(pCert, CERT_KEY_CONTEXT_PROP_ID, 00753 &keyContext, &size); 00754 if (ret) 00755 { 00756 *phCryptProv = keyContext.hCryptProv; 00757 if (pdwKeySpec) 00758 *pdwKeySpec = keyContext.dwKeySpec; 00759 if (pfCallerFreeProv) 00760 *pfCallerFreeProv = !cache; 00761 } 00762 } 00763 if (!*phCryptProv) 00764 { 00765 ret = CRYPT_AcquirePrivateKeyFromProvInfo(pCert, info, 00766 &keyContext.hCryptProv, &keyContext.dwKeySpec); 00767 if (ret) 00768 { 00769 *phCryptProv = keyContext.hCryptProv; 00770 if (pdwKeySpec) 00771 *pdwKeySpec = keyContext.dwKeySpec; 00772 if (cache) 00773 { 00774 keyContext.cbSize = sizeof(keyContext); 00775 if (CertSetCertificateContextProperty(pCert, 00776 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext)) 00777 { 00778 if (pfCallerFreeProv) 00779 *pfCallerFreeProv = FALSE; 00780 } 00781 } 00782 else 00783 { 00784 if (pfCallerFreeProv) 00785 *pfCallerFreeProv = TRUE; 00786 } 00787 } 00788 } 00789 HeapFree(GetProcessHeap(), 0, info); 00790 return ret; 00791 } 00792 00793 static BOOL key_prov_info_matches_cert(PCCERT_CONTEXT pCert, 00794 const CRYPT_KEY_PROV_INFO *keyProvInfo) 00795 { 00796 HCRYPTPROV csp; 00797 BOOL matches = FALSE; 00798 00799 if (CryptAcquireContextW(&csp, keyProvInfo->pwszContainerName, 00800 keyProvInfo->pwszProvName, keyProvInfo->dwProvType, keyProvInfo->dwFlags)) 00801 { 00802 DWORD size; 00803 00804 /* Need to sign something to verify the sig. What to sign? Why not 00805 * the certificate itself? 00806 */ 00807 if (CryptSignAndEncodeCertificate(csp, AT_SIGNATURE, 00808 pCert->dwCertEncodingType, X509_CERT_TO_BE_SIGNED, pCert->pCertInfo, 00809 &pCert->pCertInfo->SignatureAlgorithm, NULL, NULL, &size)) 00810 { 00811 BYTE *certEncoded = CryptMemAlloc(size); 00812 00813 if (certEncoded) 00814 { 00815 if (CryptSignAndEncodeCertificate(csp, AT_SIGNATURE, 00816 pCert->dwCertEncodingType, X509_CERT_TO_BE_SIGNED, 00817 pCert->pCertInfo, &pCert->pCertInfo->SignatureAlgorithm, 00818 NULL, certEncoded, &size)) 00819 { 00820 if (size == pCert->cbCertEncoded && 00821 !memcmp(certEncoded, pCert->pbCertEncoded, size)) 00822 matches = TRUE; 00823 } 00824 CryptMemFree(certEncoded); 00825 } 00826 } 00827 CryptReleaseContext(csp, 0); 00828 } 00829 return matches; 00830 } 00831 00832 static BOOL container_matches_cert(PCCERT_CONTEXT pCert, LPCSTR container, 00833 CRYPT_KEY_PROV_INFO *keyProvInfo) 00834 { 00835 CRYPT_KEY_PROV_INFO copy; 00836 WCHAR containerW[MAX_PATH]; 00837 BOOL matches = FALSE; 00838 00839 MultiByteToWideChar(CP_ACP, 0, container, -1, 00840 containerW, sizeof(containerW) / sizeof(containerW[0])); 00841 /* We make a copy of the CRYPT_KEY_PROV_INFO because the caller expects 00842 * keyProvInfo->pwszContainerName to be NULL or a heap-allocated container 00843 * name. 00844 */ 00845 memcpy(©, keyProvInfo, sizeof(copy)); 00846 copy.pwszContainerName = containerW; 00847 matches = key_prov_info_matches_cert(pCert, ©); 00848 if (matches) 00849 { 00850 keyProvInfo->pwszContainerName = 00851 CryptMemAlloc((strlenW(containerW) + 1) * sizeof(WCHAR)); 00852 if (keyProvInfo->pwszContainerName) 00853 { 00854 strcpyW(keyProvInfo->pwszContainerName, containerW); 00855 keyProvInfo->dwKeySpec = AT_SIGNATURE; 00856 } 00857 else 00858 matches = FALSE; 00859 } 00860 return matches; 00861 } 00862 00863 /* Searches the provider named keyProvInfo.pwszProvName for a container whose 00864 * private key matches pCert's public key. Upon success, updates keyProvInfo 00865 * with the matching container's info (free keyProvInfo.pwszContainerName upon 00866 * success.) 00867 * Returns TRUE if found, FALSE if not. 00868 */ 00869 static BOOL find_key_prov_info_in_provider(PCCERT_CONTEXT pCert, 00870 CRYPT_KEY_PROV_INFO *keyProvInfo) 00871 { 00872 HCRYPTPROV defProvider; 00873 BOOL ret, found = FALSE; 00874 char containerA[MAX_PATH]; 00875 00876 assert(keyProvInfo->pwszContainerName == NULL); 00877 if ((ret = CryptAcquireContextW(&defProvider, NULL, 00878 keyProvInfo->pwszProvName, keyProvInfo->dwProvType, 00879 keyProvInfo->dwFlags | CRYPT_VERIFYCONTEXT))) 00880 { 00881 DWORD enumFlags = keyProvInfo->dwFlags | CRYPT_FIRST; 00882 00883 while (ret && !found) 00884 { 00885 DWORD size = sizeof(containerA); 00886 00887 ret = CryptGetProvParam(defProvider, PP_ENUMCONTAINERS, 00888 (BYTE *)containerA, &size, enumFlags); 00889 if (ret) 00890 found = container_matches_cert(pCert, containerA, keyProvInfo); 00891 if (enumFlags & CRYPT_FIRST) 00892 { 00893 enumFlags &= ~CRYPT_FIRST; 00894 enumFlags |= CRYPT_NEXT; 00895 } 00896 } 00897 CryptReleaseContext(defProvider, 0); 00898 } 00899 return found; 00900 } 00901 00902 static BOOL find_matching_provider(PCCERT_CONTEXT pCert, DWORD dwFlags) 00903 { 00904 BOOL found = FALSE, ret = TRUE; 00905 DWORD index = 0, cbProvName = 0; 00906 CRYPT_KEY_PROV_INFO keyProvInfo; 00907 00908 TRACE("(%p, %08x)\n", pCert, dwFlags); 00909 00910 memset(&keyProvInfo, 0, sizeof(keyProvInfo)); 00911 while (ret && !found) 00912 { 00913 DWORD size = 0; 00914 00915 ret = CryptEnumProvidersW(index, NULL, 0, &keyProvInfo.dwProvType, 00916 NULL, &size); 00917 if (ret) 00918 { 00919 if (size <= cbProvName) 00920 ret = CryptEnumProvidersW(index, NULL, 0, 00921 &keyProvInfo.dwProvType, keyProvInfo.pwszProvName, &size); 00922 else 00923 { 00924 CryptMemFree(keyProvInfo.pwszProvName); 00925 keyProvInfo.pwszProvName = CryptMemAlloc(size); 00926 if (keyProvInfo.pwszProvName) 00927 { 00928 cbProvName = size; 00929 ret = CryptEnumProvidersW(index, NULL, 0, 00930 &keyProvInfo.dwProvType, keyProvInfo.pwszProvName, &size); 00931 if (ret) 00932 { 00933 if (dwFlags & CRYPT_FIND_SILENT_KEYSET_FLAG) 00934 keyProvInfo.dwFlags |= CRYPT_SILENT; 00935 if (dwFlags & CRYPT_FIND_USER_KEYSET_FLAG || 00936 !(dwFlags & (CRYPT_FIND_USER_KEYSET_FLAG | 00937 CRYPT_FIND_MACHINE_KEYSET_FLAG))) 00938 { 00939 keyProvInfo.dwFlags |= CRYPT_USER_KEYSET; 00940 found = find_key_prov_info_in_provider(pCert, 00941 &keyProvInfo); 00942 } 00943 if (!found) 00944 { 00945 if (dwFlags & CRYPT_FIND_MACHINE_KEYSET_FLAG || 00946 !(dwFlags & (CRYPT_FIND_USER_KEYSET_FLAG | 00947 CRYPT_FIND_MACHINE_KEYSET_FLAG))) 00948 { 00949 keyProvInfo.dwFlags &= ~CRYPT_USER_KEYSET; 00950 keyProvInfo.dwFlags |= CRYPT_MACHINE_KEYSET; 00951 found = find_key_prov_info_in_provider(pCert, 00952 &keyProvInfo); 00953 } 00954 } 00955 } 00956 } 00957 else 00958 ret = FALSE; 00959 } 00960 index++; 00961 } 00962 } 00963 if (found) 00964 CertSetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, 00965 0, &keyProvInfo); 00966 CryptMemFree(keyProvInfo.pwszProvName); 00967 CryptMemFree(keyProvInfo.pwszContainerName); 00968 return found; 00969 } 00970 00971 static BOOL cert_prov_info_matches_cert(PCCERT_CONTEXT pCert) 00972 { 00973 BOOL matches = FALSE; 00974 DWORD size; 00975 00976 if (CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, 00977 NULL, &size)) 00978 { 00979 CRYPT_KEY_PROV_INFO *keyProvInfo = CryptMemAlloc(size); 00980 00981 if (keyProvInfo) 00982 { 00983 if (CertGetCertificateContextProperty(pCert, 00984 CERT_KEY_PROV_INFO_PROP_ID, keyProvInfo, &size)) 00985 matches = key_prov_info_matches_cert(pCert, keyProvInfo); 00986 CryptMemFree(keyProvInfo); 00987 } 00988 } 00989 return matches; 00990 } 00991 00992 BOOL WINAPI CryptFindCertificateKeyProvInfo(PCCERT_CONTEXT pCert, 00993 DWORD dwFlags, void *pvReserved) 00994 { 00995 BOOL matches = FALSE; 00996 00997 TRACE("(%p, %08x, %p)\n", pCert, dwFlags, pvReserved); 00998 00999 matches = cert_prov_info_matches_cert(pCert); 01000 if (!matches) 01001 matches = find_matching_provider(pCert, dwFlags); 01002 return matches; 01003 } 01004 01005 BOOL WINAPI CertCompareCertificate(DWORD dwCertEncodingType, 01006 PCERT_INFO pCertId1, PCERT_INFO pCertId2) 01007 { 01008 BOOL ret; 01009 01010 TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pCertId1, pCertId2); 01011 01012 ret = CertCompareCertificateName(dwCertEncodingType, &pCertId1->Issuer, 01013 &pCertId2->Issuer) && CertCompareIntegerBlob(&pCertId1->SerialNumber, 01014 &pCertId2->SerialNumber); 01015 TRACE("returning %d\n", ret); 01016 return ret; 01017 } 01018 01019 BOOL WINAPI CertCompareCertificateName(DWORD dwCertEncodingType, 01020 PCERT_NAME_BLOB pCertName1, PCERT_NAME_BLOB pCertName2) 01021 { 01022 BOOL ret; 01023 01024 TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pCertName1, pCertName2); 01025 01026 if (pCertName1->cbData == pCertName2->cbData) 01027 { 01028 if (pCertName1->cbData) 01029 ret = !memcmp(pCertName1->pbData, pCertName2->pbData, 01030 pCertName1->cbData); 01031 else 01032 ret = TRUE; 01033 } 01034 else 01035 ret = FALSE; 01036 TRACE("returning %d\n", ret); 01037 return ret; 01038 } 01039 01040 /* Returns the number of significant bytes in pInt, where a byte is 01041 * insignificant if it's a leading 0 for positive numbers or a leading 0xff 01042 * for negative numbers. pInt is assumed to be little-endian. 01043 */ 01044 static DWORD CRYPT_significantBytes(const CRYPT_INTEGER_BLOB *pInt) 01045 { 01046 DWORD ret = pInt->cbData; 01047 01048 while (ret > 1) 01049 { 01050 if (pInt->pbData[ret - 2] <= 0x7f && pInt->pbData[ret - 1] == 0) 01051 ret--; 01052 else if (pInt->pbData[ret - 2] >= 0x80 && pInt->pbData[ret - 1] == 0xff) 01053 ret--; 01054 else 01055 break; 01056 } 01057 return ret; 01058 } 01059 01060 BOOL WINAPI CertCompareIntegerBlob(PCRYPT_INTEGER_BLOB pInt1, 01061 PCRYPT_INTEGER_BLOB pInt2) 01062 { 01063 BOOL ret; 01064 DWORD cb1, cb2; 01065 01066 TRACE("(%p, %p)\n", pInt1, pInt2); 01067 01068 cb1 = CRYPT_significantBytes(pInt1); 01069 cb2 = CRYPT_significantBytes(pInt2); 01070 if (cb1 == cb2) 01071 { 01072 if (cb1) 01073 ret = !memcmp(pInt1->pbData, pInt2->pbData, cb1); 01074 else 01075 ret = TRUE; 01076 } 01077 else 01078 ret = FALSE; 01079 TRACE("returning %d\n", ret); 01080 return ret; 01081 } 01082 01083 BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType, 01084 PCERT_PUBLIC_KEY_INFO pPublicKey1, PCERT_PUBLIC_KEY_INFO pPublicKey2) 01085 { 01086 BOOL ret; 01087 01088 TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pPublicKey1, pPublicKey2); 01089 01090 switch (GET_CERT_ENCODING_TYPE(dwCertEncodingType)) 01091 { 01092 case 0: /* Seems to mean "raw binary bits" */ 01093 if (pPublicKey1->PublicKey.cbData == pPublicKey2->PublicKey.cbData && 01094 pPublicKey1->PublicKey.cUnusedBits == pPublicKey2->PublicKey.cUnusedBits) 01095 { 01096 if (pPublicKey2->PublicKey.cbData) 01097 ret = !memcmp(pPublicKey1->PublicKey.pbData, 01098 pPublicKey2->PublicKey.pbData, pPublicKey1->PublicKey.cbData); 01099 else 01100 ret = TRUE; 01101 } 01102 else 01103 ret = FALSE; 01104 break; 01105 default: 01106 WARN("Unknown encoding type %08x\n", dwCertEncodingType); 01107 /* FALLTHROUGH */ 01108 case X509_ASN_ENCODING: 01109 { 01110 BLOBHEADER *pblob1, *pblob2; 01111 DWORD length; 01112 ret = FALSE; 01113 if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 01114 pPublicKey1->PublicKey.pbData, pPublicKey1->PublicKey.cbData, 01115 0, NULL, &length)) 01116 { 01117 pblob1 = CryptMemAlloc(length); 01118 if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 01119 pPublicKey1->PublicKey.pbData, pPublicKey1->PublicKey.cbData, 01120 0, pblob1, &length)) 01121 { 01122 if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 01123 pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData, 01124 0, NULL, &length)) 01125 { 01126 pblob2 = CryptMemAlloc(length); 01127 if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, 01128 pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData, 01129 0, pblob2, &length)) 01130 { 01131 /* The RSAPUBKEY structure directly follows the BLOBHEADER */ 01132 RSAPUBKEY *pk1 = (LPVOID)(pblob1 + 1), 01133 *pk2 = (LPVOID)(pblob2 + 1); 01134 ret = (pk1->bitlen == pk2->bitlen) && (pk1->pubexp == pk2->pubexp) 01135 && !memcmp(pk1 + 1, pk2 + 1, pk1->bitlen/8); 01136 } 01137 CryptMemFree(pblob2); 01138 } 01139 } 01140 CryptMemFree(pblob1); 01141 } 01142 01143 break; 01144 } 01145 } 01146 return ret; 01147 } 01148 01149 DWORD WINAPI CertGetPublicKeyLength(DWORD dwCertEncodingType, 01150 PCERT_PUBLIC_KEY_INFO pPublicKey) 01151 { 01152 DWORD len = 0; 01153 01154 TRACE("(%08x, %p)\n", dwCertEncodingType, pPublicKey); 01155 01156 if (GET_CERT_ENCODING_TYPE(dwCertEncodingType) != X509_ASN_ENCODING) 01157 { 01158 SetLastError(ERROR_FILE_NOT_FOUND); 01159 return 0; 01160 } 01161 if (pPublicKey->Algorithm.pszObjId && 01162 !strcmp(pPublicKey->Algorithm.pszObjId, szOID_RSA_DH)) 01163 { 01164 FIXME("unimplemented for DH public keys\n"); 01165 SetLastError(CRYPT_E_ASN1_BADTAG); 01166 } 01167 else 01168 { 01169 DWORD size; 01170 PBYTE buf; 01171 BOOL ret = CryptDecodeObjectEx(dwCertEncodingType, 01172 RSA_CSP_PUBLICKEYBLOB, pPublicKey->PublicKey.pbData, 01173 pPublicKey->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, 01174 &size); 01175 01176 if (ret) 01177 { 01178 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER)); 01179 01180 len = rsaPubKey->bitlen; 01181 LocalFree(buf); 01182 } 01183 } 01184 return len; 01185 } 01186 01187 typedef BOOL (*CertCompareFunc)(PCCERT_CONTEXT pCertContext, DWORD dwType, 01188 DWORD dwFlags, const void *pvPara); 01189 01190 static BOOL compare_cert_by_md5_hash(PCCERT_CONTEXT pCertContext, DWORD dwType, 01191 DWORD dwFlags, const void *pvPara) 01192 { 01193 BOOL ret; 01194 BYTE hash[16]; 01195 DWORD size = sizeof(hash); 01196 01197 ret = CertGetCertificateContextProperty(pCertContext, 01198 CERT_MD5_HASH_PROP_ID, hash, &size); 01199 if (ret) 01200 { 01201 const CRYPT_HASH_BLOB *pHash = pvPara; 01202 01203 if (size == pHash->cbData) 01204 ret = !memcmp(pHash->pbData, hash, size); 01205 else 01206 ret = FALSE; 01207 } 01208 return ret; 01209 } 01210 01211 static BOOL compare_cert_by_sha1_hash(PCCERT_CONTEXT pCertContext, DWORD dwType, 01212 DWORD dwFlags, const void *pvPara) 01213 { 01214 BOOL ret; 01215 BYTE hash[20]; 01216 DWORD size = sizeof(hash); 01217 01218 ret = CertGetCertificateContextProperty(pCertContext, 01219 CERT_SHA1_HASH_PROP_ID, hash, &size); 01220 if (ret) 01221 { 01222 const CRYPT_HASH_BLOB *pHash = pvPara; 01223 01224 if (size == pHash->cbData) 01225 ret = !memcmp(pHash->pbData, hash, size); 01226 else 01227 ret = FALSE; 01228 } 01229 return ret; 01230 } 01231 01232 static BOOL compare_cert_by_name(PCCERT_CONTEXT pCertContext, DWORD dwType, 01233 DWORD dwFlags, const void *pvPara) 01234 { 01235 CERT_NAME_BLOB *blob = (CERT_NAME_BLOB *)pvPara, *toCompare; 01236 BOOL ret; 01237 01238 if (dwType & CERT_INFO_SUBJECT_FLAG) 01239 toCompare = &pCertContext->pCertInfo->Subject; 01240 else 01241 toCompare = &pCertContext->pCertInfo->Issuer; 01242 ret = CertCompareCertificateName(pCertContext->dwCertEncodingType, 01243 toCompare, blob); 01244 return ret; 01245 } 01246 01247 static BOOL compare_cert_by_public_key(PCCERT_CONTEXT pCertContext, 01248 DWORD dwType, DWORD dwFlags, const void *pvPara) 01249 { 01250 CERT_PUBLIC_KEY_INFO *publicKey = (CERT_PUBLIC_KEY_INFO *)pvPara; 01251 BOOL ret; 01252 01253 ret = CertComparePublicKeyInfo(pCertContext->dwCertEncodingType, 01254 &pCertContext->pCertInfo->SubjectPublicKeyInfo, publicKey); 01255 return ret; 01256 } 01257 01258 static BOOL compare_cert_by_subject_cert(PCCERT_CONTEXT pCertContext, 01259 DWORD dwType, DWORD dwFlags, const void *pvPara) 01260 { 01261 CERT_INFO *pCertInfo = (CERT_INFO *)pvPara; 01262 BOOL ret; 01263 01264 /* Matching serial number and subject match.. */ 01265 ret = CertCompareCertificateName(pCertContext->dwCertEncodingType, 01266 &pCertContext->pCertInfo->Subject, &pCertInfo->Issuer); 01267 if (ret) 01268 ret = CertCompareIntegerBlob(&pCertContext->pCertInfo->SerialNumber, 01269 &pCertInfo->SerialNumber); 01270 else 01271 { 01272 /* failing that, if the serial number and issuer match, we match */ 01273 ret = CertCompareIntegerBlob(&pCertContext->pCertInfo->SerialNumber, 01274 &pCertInfo->SerialNumber); 01275 if (ret) 01276 ret = CertCompareCertificateName(pCertContext->dwCertEncodingType, 01277 &pCertContext->pCertInfo->Issuer, &pCertInfo->Issuer); 01278 } 01279 TRACE("returning %d\n", ret); 01280 return ret; 01281 } 01282 01283 static BOOL compare_cert_by_cert_id(PCCERT_CONTEXT pCertContext, DWORD dwType, 01284 DWORD dwFlags, const void *pvPara) 01285 { 01286 CERT_ID *id = (CERT_ID *)pvPara; 01287 BOOL ret; 01288 01289 switch (id->dwIdChoice) 01290 { 01291 case CERT_ID_ISSUER_SERIAL_NUMBER: 01292 ret = CertCompareCertificateName(pCertContext->dwCertEncodingType, 01293 &pCertContext->pCertInfo->Issuer, &id->u.IssuerSerialNumber.Issuer); 01294 if (ret) 01295 ret = CertCompareIntegerBlob(&pCertContext->pCertInfo->SerialNumber, 01296 &id->u.IssuerSerialNumber.SerialNumber); 01297 break; 01298 case CERT_ID_SHA1_HASH: 01299 ret = compare_cert_by_sha1_hash(pCertContext, dwType, dwFlags, 01300 &id->u.HashId); 01301 break; 01302 case CERT_ID_KEY_IDENTIFIER: 01303 { 01304 DWORD size = 0; 01305 01306 ret = CertGetCertificateContextProperty(pCertContext, 01307 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); 01308 if (ret && size == id->u.KeyId.cbData) 01309 { 01310 LPBYTE buf = CryptMemAlloc(size); 01311 01312 if (buf) 01313 { 01314 CertGetCertificateContextProperty(pCertContext, 01315 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); 01316 ret = !memcmp(buf, id->u.KeyId.pbData, size); 01317 CryptMemFree(buf); 01318 } 01319 } 01320 else 01321 ret = FALSE; 01322 break; 01323 } 01324 default: 01325 ret = FALSE; 01326 break; 01327 } 01328 return ret; 01329 } 01330 01331 static BOOL compare_existing_cert(PCCERT_CONTEXT pCertContext, DWORD dwType, 01332 DWORD dwFlags, const void *pvPara) 01333 { 01334 PCCERT_CONTEXT toCompare = pvPara; 01335 return CertCompareCertificate(pCertContext->dwCertEncodingType, 01336 pCertContext->pCertInfo, toCompare->pCertInfo); 01337 } 01338 01339 static BOOL compare_cert_by_signature_hash(PCCERT_CONTEXT pCertContext, DWORD dwType, 01340 DWORD dwFlags, const void *pvPara) 01341 { 01342 const CRYPT_HASH_BLOB *hash = pvPara; 01343 DWORD size = 0; 01344 BOOL ret; 01345 01346 ret = CertGetCertificateContextProperty(pCertContext, 01347 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size); 01348 if (ret && size == hash->cbData) 01349 { 01350 LPBYTE buf = CryptMemAlloc(size); 01351 01352 if (buf) 01353 { 01354 CertGetCertificateContextProperty(pCertContext, 01355 CERT_SIGNATURE_HASH_PROP_ID, buf, &size); 01356 ret = !memcmp(buf, hash->pbData, size); 01357 CryptMemFree(buf); 01358 } 01359 } 01360 else 01361 ret = FALSE; 01362 return ret; 01363 } 01364 01365 static inline PCCERT_CONTEXT cert_compare_certs_in_store(HCERTSTORE store, 01366 PCCERT_CONTEXT prev, CertCompareFunc compare, DWORD dwType, DWORD dwFlags, 01367 const void *pvPara) 01368 { 01369 BOOL matches = FALSE; 01370 PCCERT_CONTEXT ret; 01371 01372 ret = prev; 01373 do { 01374 ret = CertEnumCertificatesInStore(store, ret); 01375 if (ret) 01376 matches = compare(ret, dwType, dwFlags, pvPara); 01377 } while (ret != NULL && !matches); 01378 return ret; 01379 } 01380 01381 typedef PCCERT_CONTEXT (*CertFindFunc)(HCERTSTORE store, DWORD dwType, 01382 DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev); 01383 01384 static PCCERT_CONTEXT find_cert_any(HCERTSTORE store, DWORD dwType, 01385 DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev) 01386 { 01387 return CertEnumCertificatesInStore(store, prev); 01388 } 01389 01390 static PCCERT_CONTEXT find_cert_by_issuer(HCERTSTORE store, DWORD dwType, 01391 DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev) 01392 { 01393 BOOL ret; 01394 PCCERT_CONTEXT found = NULL, subject = pvPara; 01395 PCERT_EXTENSION ext; 01396 DWORD size; 01397 01398 if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER, 01399 subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension))) 01400 { 01401 CERT_AUTHORITY_KEY_ID_INFO *info; 01402 01403 ret = CryptDecodeObjectEx(subject->dwCertEncodingType, 01404 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData, 01405 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, 01406 &info, &size); 01407 if (ret) 01408 { 01409 CERT_ID id; 01410 01411 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData) 01412 { 01413 id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 01414 memcpy(&id.u.IssuerSerialNumber.Issuer, &info->CertIssuer, 01415 sizeof(CERT_NAME_BLOB)); 01416 memcpy(&id.u.IssuerSerialNumber.SerialNumber, 01417 &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB)); 01418 } 01419 else if (info->KeyId.cbData) 01420 { 01421 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER; 01422 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB)); 01423 } 01424 else 01425 ret = FALSE; 01426 if (ret) 01427 found = cert_compare_certs_in_store(store, prev, 01428 compare_cert_by_cert_id, dwType, dwFlags, &id); 01429 LocalFree(info); 01430 } 01431 } 01432 else if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, 01433 subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension))) 01434 { 01435 CERT_AUTHORITY_KEY_ID2_INFO *info; 01436 01437 ret = CryptDecodeObjectEx(subject->dwCertEncodingType, 01438 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData, 01439 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, 01440 &info, &size); 01441 if (ret) 01442 { 01443 CERT_ID id; 01444 01445 if (info->AuthorityCertIssuer.cAltEntry && 01446 info->AuthorityCertSerialNumber.cbData) 01447 { 01448 PCERT_ALT_NAME_ENTRY directoryName = NULL; 01449 DWORD i; 01450 01451 for (i = 0; !directoryName && 01452 i < info->AuthorityCertIssuer.cAltEntry; i++) 01453 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice 01454 == CERT_ALT_NAME_DIRECTORY_NAME) 01455 directoryName = 01456 &info->AuthorityCertIssuer.rgAltEntry[i]; 01457 if (directoryName) 01458 { 01459 id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 01460 memcpy(&id.u.IssuerSerialNumber.Issuer, 01461 &directoryName->u.DirectoryName, sizeof(CERT_NAME_BLOB)); 01462 memcpy(&id.u.IssuerSerialNumber.SerialNumber, 01463 &info->AuthorityCertSerialNumber, 01464 sizeof(CRYPT_INTEGER_BLOB)); 01465 } 01466 else 01467 { 01468 FIXME("no supported name type in authority key id2\n"); 01469 ret = FALSE; 01470 } 01471 } 01472 else if (info->KeyId.cbData) 01473 { 01474 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER; 01475 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB)); 01476 } 01477 else 01478 ret = FALSE; 01479 if (ret) 01480 found = cert_compare_certs_in_store(store, prev, 01481 compare_cert_by_cert_id, dwType, dwFlags, &id); 01482 LocalFree(info); 01483 } 01484 } 01485 else 01486 found = cert_compare_certs_in_store(store, prev, 01487 compare_cert_by_name, CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT, 01488 dwFlags, &subject->pCertInfo->Issuer); 01489 return found; 01490 } 01491 01492 static BOOL compare_cert_by_name_str(PCCERT_CONTEXT pCertContext, 01493 DWORD dwType, DWORD dwFlags, const void *pvPara) 01494 { 01495 PCERT_NAME_BLOB name; 01496 DWORD len; 01497 BOOL ret = FALSE; 01498 01499 if (dwType & CERT_INFO_SUBJECT_FLAG) 01500 name = &pCertContext->pCertInfo->Subject; 01501 else 01502 name = &pCertContext->pCertInfo->Issuer; 01503 len = CertNameToStrW(pCertContext->dwCertEncodingType, name, 01504 CERT_SIMPLE_NAME_STR, NULL, 0); 01505 if (len) 01506 { 01507 LPWSTR str = CryptMemAlloc(len * sizeof(WCHAR)); 01508 01509 if (str) 01510 { 01511 LPWSTR ptr; 01512 01513 CertNameToStrW(pCertContext->dwCertEncodingType, name, 01514 CERT_SIMPLE_NAME_STR, str, len); 01515 for (ptr = str; *ptr; ptr++) 01516 *ptr = tolowerW(*ptr); 01517 if (strstrW(str, pvPara)) 01518 ret = TRUE; 01519 CryptMemFree(str); 01520 } 01521 } 01522 return ret; 01523 } 01524 01525 static PCCERT_CONTEXT find_cert_by_name_str_a(HCERTSTORE store, DWORD dwType, 01526 DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev) 01527 { 01528 PCCERT_CONTEXT found = NULL; 01529 01530 TRACE("%s\n", debugstr_a(pvPara)); 01531 01532 if (pvPara) 01533 { 01534 int len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0); 01535 LPWSTR str = CryptMemAlloc(len * sizeof(WCHAR)); 01536 01537 if (str) 01538 { 01539 LPWSTR ptr; 01540 01541 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, str, len); 01542 for (ptr = str; *ptr; ptr++) 01543 *ptr = tolowerW(*ptr); 01544 found = cert_compare_certs_in_store(store, prev, 01545 compare_cert_by_name_str, dwType, dwFlags, str); 01546 CryptMemFree(str); 01547 } 01548 } 01549 else 01550 found = find_cert_any(store, dwType, dwFlags, NULL, prev); 01551 return found; 01552 } 01553 01554 static PCCERT_CONTEXT find_cert_by_name_str_w(HCERTSTORE store, DWORD dwType, 01555 DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev) 01556 { 01557 PCCERT_CONTEXT found = NULL; 01558 01559 TRACE("%s\n", debugstr_w(pvPara)); 01560 01561 if (pvPara) 01562 { 01563 DWORD len = strlenW(pvPara); 01564 LPWSTR str = CryptMemAlloc((len + 1) * sizeof(WCHAR)); 01565 01566 if (str) 01567 { 01568 LPCWSTR src; 01569 LPWSTR dst; 01570 01571 for (src = pvPara, dst = str; *src; src++, dst++) 01572 *dst = tolowerW(*src); 01573 *dst = 0; 01574 found = cert_compare_certs_in_store(store, prev, 01575 compare_cert_by_name_str, dwType, dwFlags, str); 01576 CryptMemFree(str); 01577 } 01578 } 01579 else 01580 found = find_cert_any(store, dwType, dwFlags, NULL, prev); 01581 return found; 01582 } 01583 01584 PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, 01585 DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType, const void *pvPara, 01586 PCCERT_CONTEXT pPrevCertContext) 01587 { 01588 PCCERT_CONTEXT ret; 01589 CertFindFunc find = NULL; 01590 CertCompareFunc compare = NULL; 01591 01592 TRACE("(%p, %08x, %08x, %08x, %p, %p)\n", hCertStore, dwCertEncodingType, 01593 dwFlags, dwType, pvPara, pPrevCertContext); 01594 01595 switch (dwType >> CERT_COMPARE_SHIFT) 01596 { 01597 case CERT_COMPARE_ANY: 01598 find = find_cert_any; 01599 break; 01600 case CERT_COMPARE_MD5_HASH: 01601 compare = compare_cert_by_md5_hash; 01602 break; 01603 case CERT_COMPARE_SHA1_HASH: 01604 compare = compare_cert_by_sha1_hash; 01605 break; 01606 case CERT_COMPARE_NAME: 01607 compare = compare_cert_by_name; 01608 break; 01609 case CERT_COMPARE_PUBLIC_KEY: 01610 compare = compare_cert_by_public_key; 01611 break; 01612 case CERT_COMPARE_NAME_STR_A: 01613 find = find_cert_by_name_str_a; 01614 break; 01615 case CERT_COMPARE_NAME_STR_W: 01616 find = find_cert_by_name_str_w; 01617 break; 01618 case CERT_COMPARE_SUBJECT_CERT: 01619 compare = compare_cert_by_subject_cert; 01620 break; 01621 case CERT_COMPARE_CERT_ID: 01622 compare = compare_cert_by_cert_id; 01623 break; 01624 case CERT_COMPARE_ISSUER_OF: 01625 find = find_cert_by_issuer; 01626 break; 01627 case CERT_COMPARE_EXISTING: 01628 compare = compare_existing_cert; 01629 break; 01630 case CERT_COMPARE_SIGNATURE_HASH: 01631 compare = compare_cert_by_signature_hash; 01632 break; 01633 default: 01634 FIXME("find type %08x unimplemented\n", dwType); 01635 } 01636 01637 if (find) 01638 ret = find(hCertStore, dwFlags, dwType, pvPara, pPrevCertContext); 01639 else if (compare) 01640 ret = cert_compare_certs_in_store(hCertStore, pPrevCertContext, 01641 compare, dwType, dwFlags, pvPara); 01642 else 01643 ret = NULL; 01644 if (!ret) 01645 SetLastError(CRYPT_E_NOT_FOUND); 01646 TRACE("returning %p\n", ret); 01647 return ret; 01648 } 01649 01650 PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore, 01651 DWORD dwCertEncodingType, PCERT_INFO pCertId) 01652 { 01653 TRACE("(%p, %08x, %p)\n", hCertStore, dwCertEncodingType, pCertId); 01654 01655 if (!pCertId) 01656 { 01657 SetLastError(E_INVALIDARG); 01658 return NULL; 01659 } 01660 return CertFindCertificateInStore(hCertStore, dwCertEncodingType, 0, 01661 CERT_FIND_SUBJECT_CERT, pCertId, NULL); 01662 } 01663 01664 BOOL WINAPI CertVerifySubjectCertificateContext(PCCERT_CONTEXT pSubject, 01665 PCCERT_CONTEXT pIssuer, DWORD *pdwFlags) 01666 { 01667 static const DWORD supportedFlags = CERT_STORE_REVOCATION_FLAG | 01668 CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG; 01669 01670 if (*pdwFlags & ~supportedFlags) 01671 { 01672 SetLastError(E_INVALIDARG); 01673 return FALSE; 01674 } 01675 if (*pdwFlags & CERT_STORE_REVOCATION_FLAG) 01676 { 01677 DWORD flags = 0; 01678 PCCRL_CONTEXT crl = CertGetCRLFromStore(pSubject->hCertStore, pSubject, 01679 NULL, &flags); 01680 01681 /* FIXME: what if the CRL has expired? */ 01682 if (crl) 01683 { 01684 if (CertVerifyCRLRevocation(pSubject->dwCertEncodingType, 01685 pSubject->pCertInfo, 1, (PCRL_INFO *)&crl->pCrlInfo)) 01686 *pdwFlags &= CERT_STORE_REVOCATION_FLAG; 01687 } 01688 else 01689 *pdwFlags |= CERT_STORE_NO_CRL_FLAG; 01690 } 01691 if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG) 01692 { 01693 if (0 == CertVerifyTimeValidity(NULL, pSubject->pCertInfo)) 01694 *pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG; 01695 } 01696 if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG) 01697 { 01698 if (CryptVerifyCertificateSignatureEx(0, pSubject->dwCertEncodingType, 01699 CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)pSubject, 01700 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)pIssuer, 0, NULL)) 01701 *pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG; 01702 } 01703 return TRUE; 01704 } 01705 01706 PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(HCERTSTORE hCertStore, 01707 PCCERT_CONTEXT pSubjectContext, PCCERT_CONTEXT pPrevIssuerContext, 01708 DWORD *pdwFlags) 01709 { 01710 PCCERT_CONTEXT ret; 01711 01712 TRACE("(%p, %p, %p, %08x)\n", hCertStore, pSubjectContext, 01713 pPrevIssuerContext, *pdwFlags); 01714 01715 if (!pSubjectContext) 01716 { 01717 SetLastError(E_INVALIDARG); 01718 return NULL; 01719 } 01720 01721 ret = CertFindCertificateInStore(hCertStore, 01722 pSubjectContext->dwCertEncodingType, 0, CERT_FIND_ISSUER_OF, 01723 pSubjectContext, pPrevIssuerContext); 01724 if (ret) 01725 { 01726 if (!CertVerifySubjectCertificateContext(pSubjectContext, ret, 01727 pdwFlags)) 01728 { 01729 CertFreeCertificateContext(ret); 01730 ret = NULL; 01731 } 01732 } 01733 TRACE("returning %p\n", ret); 01734 return ret; 01735 } 01736 01737 typedef struct _OLD_CERT_REVOCATION_STATUS { 01738 DWORD cbSize; 01739 DWORD dwIndex; 01740 DWORD dwError; 01741 DWORD dwReason; 01742 } OLD_CERT_REVOCATION_STATUS, *POLD_CERT_REVOCATION_STATUS; 01743 01744 typedef BOOL (WINAPI *CertVerifyRevocationFunc)(DWORD, DWORD, DWORD, 01745 void **, DWORD, PCERT_REVOCATION_PARA, PCERT_REVOCATION_STATUS); 01746 01747 BOOL WINAPI CertVerifyRevocation(DWORD dwEncodingType, DWORD dwRevType, 01748 DWORD cContext, PVOID rgpvContext[], DWORD dwFlags, 01749 PCERT_REVOCATION_PARA pRevPara, PCERT_REVOCATION_STATUS pRevStatus) 01750 { 01751 BOOL ret; 01752 01753 TRACE("(%08x, %d, %d, %p, %08x, %p, %p)\n", dwEncodingType, dwRevType, 01754 cContext, rgpvContext, dwFlags, pRevPara, pRevStatus); 01755 01756 if (pRevStatus->cbSize != sizeof(OLD_CERT_REVOCATION_STATUS) && 01757 pRevStatus->cbSize != sizeof(CERT_REVOCATION_STATUS)) 01758 { 01759 SetLastError(E_INVALIDARG); 01760 return FALSE; 01761 } 01762 if (cContext) 01763 { 01764 static HCRYPTOIDFUNCSET set = NULL; 01765 DWORD size; 01766 01767 if (!set) 01768 set = CryptInitOIDFunctionSet(CRYPT_OID_VERIFY_REVOCATION_FUNC, 0); 01769 ret = CryptGetDefaultOIDDllList(set, dwEncodingType, NULL, &size); 01770 if (ret) 01771 { 01772 if (size == 1) 01773 { 01774 /* empty list */ 01775 SetLastError(CRYPT_E_NO_REVOCATION_DLL); 01776 ret = FALSE; 01777 } 01778 else 01779 { 01780 LPWSTR dllList = CryptMemAlloc(size * sizeof(WCHAR)), ptr; 01781 01782 if (dllList) 01783 { 01784 ret = CryptGetDefaultOIDDllList(set, dwEncodingType, 01785 dllList, &size); 01786 if (ret) 01787 { 01788 for (ptr = dllList; ret && *ptr; 01789 ptr += lstrlenW(ptr) + 1) 01790 { 01791 CertVerifyRevocationFunc func; 01792 HCRYPTOIDFUNCADDR hFunc; 01793 01794 ret = CryptGetDefaultOIDFunctionAddress(set, 01795 dwEncodingType, ptr, 0, (void **)&func, &hFunc); 01796 if (ret) 01797 { 01798 ret = func(dwEncodingType, dwRevType, cContext, 01799 rgpvContext, dwFlags, pRevPara, pRevStatus); 01800 CryptFreeOIDFunctionAddress(hFunc, 0); 01801 } 01802 } 01803 } 01804 CryptMemFree(dllList); 01805 } 01806 else 01807 { 01808 SetLastError(ERROR_OUTOFMEMORY); 01809 ret = FALSE; 01810 } 01811 } 01812 } 01813 } 01814 else 01815 ret = TRUE; 01816 return ret; 01817 } 01818 01819 PCRYPT_ATTRIBUTE WINAPI CertFindAttribute(LPCSTR pszObjId, DWORD cAttr, 01820 CRYPT_ATTRIBUTE rgAttr[]) 01821 { 01822 PCRYPT_ATTRIBUTE ret = NULL; 01823 DWORD i; 01824 01825 TRACE("%s %d %p\n", debugstr_a(pszObjId), cAttr, rgAttr); 01826 01827 if (!cAttr) 01828 return NULL; 01829 if (!pszObjId) 01830 { 01831 SetLastError(ERROR_INVALID_PARAMETER); 01832 return NULL; 01833 } 01834 01835 for (i = 0; !ret && i < cAttr; i++) 01836 if (rgAttr[i].pszObjId && !strcmp(pszObjId, rgAttr[i].pszObjId)) 01837 ret = &rgAttr[i]; 01838 return ret; 01839 } 01840 01841 PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions, 01842 CERT_EXTENSION rgExtensions[]) 01843 { 01844 PCERT_EXTENSION ret = NULL; 01845 DWORD i; 01846 01847 TRACE("%s %d %p\n", debugstr_a(pszObjId), cExtensions, rgExtensions); 01848 01849 if (!cExtensions) 01850 return NULL; 01851 if (!pszObjId) 01852 { 01853 SetLastError(ERROR_INVALID_PARAMETER); 01854 return NULL; 01855 } 01856 01857 for (i = 0; !ret && i < cExtensions; i++) 01858 if (rgExtensions[i].pszObjId && !strcmp(pszObjId, 01859 rgExtensions[i].pszObjId)) 01860 ret = &rgExtensions[i]; 01861 return ret; 01862 } 01863 01864 PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName) 01865 { 01866 PCERT_RDN_ATTR ret = NULL; 01867 DWORD i, j; 01868 01869 TRACE("%s %p\n", debugstr_a(pszObjId), pName); 01870 01871 if (!pszObjId) 01872 { 01873 SetLastError(ERROR_INVALID_PARAMETER); 01874 return NULL; 01875 } 01876 01877 for (i = 0; !ret && i < pName->cRDN; i++) 01878 for (j = 0; !ret && j < pName->rgRDN[i].cRDNAttr; j++) 01879 if (pName->rgRDN[i].rgRDNAttr[j].pszObjId && !strcmp(pszObjId, 01880 pName->rgRDN[i].rgRDNAttr[j].pszObjId)) 01881 ret = &pName->rgRDN[i].rgRDNAttr[j]; 01882 return ret; 01883 } 01884 01885 static BOOL find_matching_rdn_attr(DWORD dwFlags, const CERT_NAME_INFO *name, 01886 const CERT_RDN_ATTR *attr) 01887 { 01888 DWORD i, j; 01889 BOOL match = FALSE; 01890 01891 for (i = 0; !match && i < name->cRDN; i++) 01892 { 01893 for (j = 0; j < name->rgRDN[i].cRDNAttr; j++) 01894 { 01895 if (!strcmp(name->rgRDN[i].rgRDNAttr[j].pszObjId, 01896 attr->pszObjId) && 01897 name->rgRDN[i].rgRDNAttr[j].dwValueType == 01898 attr->dwValueType) 01899 { 01900 if (dwFlags & CERT_UNICODE_IS_RDN_ATTRS_FLAG) 01901 { 01902 LPCWSTR nameStr = 01903 (LPCWSTR)name->rgRDN[i].rgRDNAttr[j].Value.pbData; 01904 LPCWSTR attrStr = (LPCWSTR)attr->Value.pbData; 01905 01906 if (attr->Value.cbData != 01907 name->rgRDN[i].rgRDNAttr[j].Value.cbData) 01908 match = FALSE; 01909 else if (dwFlags & CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG) 01910 match = !strncmpiW(nameStr, attrStr, 01911 attr->Value.cbData / sizeof(WCHAR)); 01912 else 01913 match = !strncmpW(nameStr, attrStr, 01914 attr->Value.cbData / sizeof(WCHAR)); 01915 TRACE("%s : %s => %d\n", 01916 debugstr_wn(nameStr, attr->Value.cbData / sizeof(WCHAR)), 01917 debugstr_wn(attrStr, attr->Value.cbData / sizeof(WCHAR)), 01918 match); 01919 } 01920 else 01921 { 01922 LPCSTR nameStr = 01923 (LPCSTR)name->rgRDN[i].rgRDNAttr[j].Value.pbData; 01924 LPCSTR attrStr = (LPCSTR)attr->Value.pbData; 01925 01926 if (attr->Value.cbData != 01927 name->rgRDN[i].rgRDNAttr[j].Value.cbData) 01928 match = FALSE; 01929 else if (dwFlags & CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG) 01930 match = !strncasecmp(nameStr, attrStr, 01931 attr->Value.cbData); 01932 else 01933 match = !strncmp(nameStr, attrStr, attr->Value.cbData); 01934 TRACE("%s : %s => %d\n", 01935 debugstr_an(nameStr, attr->Value.cbData), 01936 debugstr_an(attrStr, attr->Value.cbData), match); 01937 } 01938 } 01939 } 01940 } 01941 return match; 01942 } 01943 01944 BOOL WINAPI CertIsRDNAttrsInCertificateName(DWORD dwCertEncodingType, 01945 DWORD dwFlags, PCERT_NAME_BLOB pCertName, PCERT_RDN pRDN) 01946 { 01947 CERT_NAME_INFO *name; 01948 LPCSTR type; 01949 DWORD size; 01950 BOOL ret; 01951 01952 TRACE("(%08x, %08x, %p, %p)\n", dwCertEncodingType, dwFlags, pCertName, 01953 pRDN); 01954 01955 type = dwFlags & CERT_UNICODE_IS_RDN_ATTRS_FLAG ? X509_UNICODE_NAME : 01956 X509_NAME; 01957 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, type, pCertName->pbData, 01958 pCertName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &name, &size))) 01959 { 01960 DWORD i; 01961 01962 for (i = 0; ret && i < pRDN->cRDNAttr; i++) 01963 ret = find_matching_rdn_attr(dwFlags, name, &pRDN->rgRDNAttr[i]); 01964 if (!ret) 01965 SetLastError(CRYPT_E_NO_MATCH); 01966 LocalFree(name); 01967 } 01968 return ret; 01969 } 01970 01971 LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify, 01972 PCERT_INFO pCertInfo) 01973 { 01974 FILETIME fileTime; 01975 LONG ret; 01976 01977 if (!pTimeToVerify) 01978 { 01979 GetSystemTimeAsFileTime(&fileTime); 01980 pTimeToVerify = &fileTime; 01981 } 01982 if ((ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotBefore)) >= 0) 01983 { 01984 ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotAfter); 01985 if (ret < 0) 01986 ret = 0; 01987 } 01988 return ret; 01989 } 01990 01991 BOOL WINAPI CertVerifyValidityNesting(PCERT_INFO pSubjectInfo, 01992 PCERT_INFO pIssuerInfo) 01993 { 01994 TRACE("(%p, %p)\n", pSubjectInfo, pIssuerInfo); 01995 01996 return CertVerifyTimeValidity(&pSubjectInfo->NotBefore, pIssuerInfo) == 0 01997 && CertVerifyTimeValidity(&pSubjectInfo->NotAfter, pIssuerInfo) == 0; 01998 } 01999 02000 BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, 02001 DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash, 02002 DWORD *pcbComputedHash) 02003 { 02004 BOOL ret = TRUE; 02005 HCRYPTHASH hHash = 0; 02006 02007 TRACE("(%08lx, %d, %08x, %p, %d, %p, %p)\n", hCryptProv, Algid, dwFlags, 02008 pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash); 02009 02010 if (!hCryptProv) 02011 hCryptProv = CRYPT_GetDefaultProvider(); 02012 if (!Algid) 02013 Algid = CALG_SHA1; 02014 if (ret) 02015 { 02016 ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash); 02017 if (ret) 02018 { 02019 ret = CryptHashData(hHash, pbEncoded, cbEncoded, 0); 02020 if (ret) 02021 ret = CryptGetHashParam(hHash, HP_HASHVAL, pbComputedHash, 02022 pcbComputedHash, 0); 02023 CryptDestroyHash(hHash); 02024 } 02025 } 02026 return ret; 02027 } 02028 02029 BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, 02030 DWORD dwFlags, DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, 02031 BYTE *pbComputedHash, DWORD *pcbComputedHash) 02032 { 02033 BOOL ret = TRUE; 02034 HCRYPTHASH hHash = 0; 02035 02036 TRACE("(%08lx, %d, %08x, %d, %p, %p, %p)\n", hCryptProv, Algid, dwFlags, 02037 dwCertEncodingType, pInfo, pbComputedHash, pcbComputedHash); 02038 02039 if (!hCryptProv) 02040 hCryptProv = CRYPT_GetDefaultProvider(); 02041 if (!Algid) 02042 Algid = CALG_MD5; 02043 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) 02044 { 02045 SetLastError(ERROR_FILE_NOT_FOUND); 02046 return FALSE; 02047 } 02048 if (ret) 02049 { 02050 BYTE *buf; 02051 DWORD size = 0; 02052 02053 ret = CRYPT_AsnEncodePubKeyInfoNoNull(dwCertEncodingType, 02054 X509_PUBLIC_KEY_INFO, pInfo, CRYPT_ENCODE_ALLOC_FLAG, NULL, 02055 (LPBYTE)&buf, &size); 02056 if (ret) 02057 { 02058 ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash); 02059 if (ret) 02060 { 02061 ret = CryptHashData(hHash, buf, size, 0); 02062 if (ret) 02063 ret = CryptGetHashParam(hHash, HP_HASHVAL, pbComputedHash, 02064 pcbComputedHash, 0); 02065 CryptDestroyHash(hHash); 02066 } 02067 LocalFree(buf); 02068 } 02069 } 02070 return ret; 02071 } 02072 02073 BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, 02074 DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, 02075 BYTE *pbComputedHash, DWORD *pcbComputedHash) 02076 { 02077 BOOL ret; 02078 CERT_SIGNED_CONTENT_INFO *info; 02079 DWORD size; 02080 02081 TRACE("(%08lx, %08x, %p, %d, %p, %d)\n", hCryptProv, dwCertEncodingType, 02082 pbEncoded, cbEncoded, pbComputedHash, *pcbComputedHash); 02083 02084 ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT, 02085 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); 02086 if (ret) 02087 { 02088 PCCRYPT_OID_INFO oidInfo; 02089 HCRYPTHASH hHash; 02090 02091 if (!hCryptProv) 02092 hCryptProv = CRYPT_GetDefaultProvider(); 02093 oidInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, 02094 info->SignatureAlgorithm.pszObjId, 0); 02095 if (!oidInfo) 02096 { 02097 SetLastError(NTE_BAD_ALGID); 02098 ret = FALSE; 02099 } 02100 else 02101 { 02102 ret = CryptCreateHash(hCryptProv, oidInfo->u.Algid, 0, 0, &hHash); 02103 if (ret) 02104 { 02105 ret = CryptHashData(hHash, info->ToBeSigned.pbData, 02106 info->ToBeSigned.cbData, 0); 02107 if (ret) 02108 ret = CryptGetHashParam(hHash, HP_HASHVAL, pbComputedHash, 02109 pcbComputedHash, 0); 02110 CryptDestroyHash(hHash); 02111 } 02112 } 02113 LocalFree(info); 02114 } 02115 return ret; 02116 } 02117 02118 BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 02119 DWORD dwKeySpec, DWORD dwCertEncodingType, const BYTE *pbEncodedToBeSigned, 02120 DWORD cbEncodedToBeSigned, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, 02121 const void *pvHashAuxInfo, BYTE *pbSignature, DWORD *pcbSignature) 02122 { 02123 BOOL ret; 02124 PCCRYPT_OID_INFO info; 02125 HCRYPTHASH hHash; 02126 02127 TRACE("(%08lx, %d, %d, %p, %d, %p, %p, %p, %p)\n", hCryptProv, 02128 dwKeySpec, dwCertEncodingType, pbEncodedToBeSigned, cbEncodedToBeSigned, 02129 pSignatureAlgorithm, pvHashAuxInfo, pbSignature, pcbSignature); 02130 02131 info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, 02132 pSignatureAlgorithm->pszObjId, 0); 02133 if (!info) 02134 { 02135 SetLastError(NTE_BAD_ALGID); 02136 return FALSE; 02137 } 02138 if (info->dwGroupId == CRYPT_HASH_ALG_OID_GROUP_ID) 02139 { 02140 if (!hCryptProv) 02141 hCryptProv = CRYPT_GetDefaultProvider(); 02142 ret = CryptCreateHash(hCryptProv, info->u.Algid, 0, 0, &hHash); 02143 if (ret) 02144 { 02145 ret = CryptHashData(hHash, pbEncodedToBeSigned, 02146 cbEncodedToBeSigned, 0); 02147 if (ret) 02148 ret = CryptGetHashParam(hHash, HP_HASHVAL, pbSignature, 02149 pcbSignature, 0); 02150 CryptDestroyHash(hHash); 02151 } 02152 } 02153 else 02154 { 02155 if (!hCryptProv) 02156 { 02157 SetLastError(ERROR_INVALID_PARAMETER); 02158 ret = FALSE; 02159 } 02160 else 02161 { 02162 ret = CryptCreateHash(hCryptProv, info->u.Algid, 0, 0, &hHash); 02163 if (ret) 02164 { 02165 ret = CryptHashData(hHash, pbEncodedToBeSigned, 02166 cbEncodedToBeSigned, 0); 02167 if (ret) 02168 ret = CryptSignHashW(hHash, dwKeySpec, NULL, 0, pbSignature, 02169 pcbSignature); 02170 CryptDestroyHash(hHash); 02171 } 02172 } 02173 } 02174 return ret; 02175 } 02176 02177 BOOL WINAPI CryptSignAndEncodeCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, 02178 DWORD dwKeySpec, DWORD dwCertEncodingType, LPCSTR lpszStructType, 02179 const void *pvStructInfo, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, 02180 const void *pvHashAuxInfo, BYTE *pbEncoded, DWORD *pcbEncoded) 02181 { 02182 BOOL ret; 02183 DWORD encodedSize, hashSize; 02184 02185 TRACE("(%08lx, %d, %d, %s, %p, %p, %p, %p, %p)\n", hCryptProv, dwKeySpec, 02186 dwCertEncodingType, debugstr_a(lpszStructType), pvStructInfo, 02187 pSignatureAlgorithm, pvHashAuxInfo, pbEncoded, pcbEncoded); 02188 02189 ret = CryptEncodeObject(dwCertEncodingType, lpszStructType, pvStructInfo, 02190 NULL, &encodedSize); 02191 if (ret) 02192 { 02193 PBYTE encoded = CryptMemAlloc(encodedSize); 02194 02195 if (encoded) 02196 { 02197 ret = CryptEncodeObject(dwCertEncodingType, lpszStructType, 02198 pvStructInfo, encoded, &encodedSize); 02199 if (ret) 02200 { 02201 ret = CryptSignCertificate(hCryptProv, dwKeySpec, 02202 dwCertEncodingType, encoded, encodedSize, pSignatureAlgorithm, 02203 pvHashAuxInfo, NULL, &hashSize); 02204 if (ret) 02205 { 02206 PBYTE hash = CryptMemAlloc(hashSize); 02207 02208 if (hash) 02209 { 02210 ret = CryptSignCertificate(hCryptProv, dwKeySpec, 02211 dwCertEncodingType, encoded, encodedSize, 02212 pSignatureAlgorithm, pvHashAuxInfo, hash, &hashSize); 02213 if (ret) 02214 { 02215 CERT_SIGNED_CONTENT_INFO info = { { 0 } }; 02216 02217 info.ToBeSigned.cbData = encodedSize; 02218 info.ToBeSigned.pbData = encoded; 02219 memcpy(&info.SignatureAlgorithm, 02220 pSignatureAlgorithm, 02221 sizeof(info.SignatureAlgorithm)); 02222 info.Signature.cbData = hashSize; 02223 info.Signature.pbData = hash; 02224 info.Signature.cUnusedBits = 0; 02225 ret = CryptEncodeObject(dwCertEncodingType, 02226 X509_CERT, &info, pbEncoded, pcbEncoded); 02227 } 02228 CryptMemFree(hash); 02229 } 02230 } 02231 } 02232 CryptMemFree(encoded); 02233 } 02234 } 02235 return ret; 02236 } 02237 02238 BOOL WINAPI CryptVerifyCertificateSignature(HCRYPTPROV_LEGACY hCryptProv, 02239 DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, 02240 PCERT_PUBLIC_KEY_INFO pPublicKey) 02241 { 02242 return CryptVerifyCertificateSignatureEx(hCryptProv, dwCertEncodingType, 02243 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, (void *)pbEncoded, 02244 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pPublicKey, 0, NULL); 02245 } 02246 02247 static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, 02248 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pubKeyInfo, 02249 const CERT_SIGNED_CONTENT_INFO *signedCert) 02250 { 02251 BOOL ret; 02252 HCRYPTKEY key; 02253 PCCRYPT_OID_INFO info; 02254 ALG_ID pubKeyID, hashID; 02255 02256 info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, 02257 signedCert->SignatureAlgorithm.pszObjId, 0); 02258 if (!info || info->dwGroupId != CRYPT_SIGN_ALG_OID_GROUP_ID) 02259 { 02260 SetLastError(NTE_BAD_ALGID); 02261 return FALSE; 02262 } 02263 hashID = info->u.Algid; 02264 if (info->ExtraInfo.cbData >= sizeof(ALG_ID)) 02265 pubKeyID = *(ALG_ID *)info->ExtraInfo.pbData; 02266 else 02267 pubKeyID = hashID; 02268 /* Load the default provider if necessary */ 02269 if (!hCryptProv) 02270 hCryptProv = CRYPT_GetDefaultProvider(); 02271 ret = CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, 02272 pubKeyInfo, pubKeyID, 0, NULL, &key); 02273 if (ret) 02274 { 02275 HCRYPTHASH hash; 02276 02277 ret = CryptCreateHash(hCryptProv, hashID, 0, 0, &hash); 02278 if (ret) 02279 { 02280 ret = CryptHashData(hash, signedCert->ToBeSigned.pbData, 02281 signedCert->ToBeSigned.cbData, 0); 02282 if (ret) 02283 ret = CryptVerifySignatureW(hash, signedCert->Signature.pbData, 02284 signedCert->Signature.cbData, key, NULL, 0); 02285 CryptDestroyHash(hash); 02286 } 02287 CryptDestroyKey(key); 02288 } 02289 return ret; 02290 } 02291 02292 BOOL WINAPI CryptVerifyCertificateSignatureEx(HCRYPTPROV_LEGACY hCryptProv, 02293 DWORD dwCertEncodingType, DWORD dwSubjectType, void *pvSubject, 02294 DWORD dwIssuerType, void *pvIssuer, DWORD dwFlags, void *pvReserved) 02295 { 02296 BOOL ret = TRUE; 02297 CRYPT_DATA_BLOB subjectBlob; 02298 02299 TRACE("(%08lx, %d, %d, %p, %d, %p, %08x, %p)\n", hCryptProv, 02300 dwCertEncodingType, dwSubjectType, pvSubject, dwIssuerType, pvIssuer, 02301 dwFlags, pvReserved); 02302 02303 switch (dwSubjectType) 02304 { 02305 case CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB: 02306 { 02307 PCRYPT_DATA_BLOB blob = pvSubject; 02308 02309 subjectBlob.pbData = blob->pbData; 02310 subjectBlob.cbData = blob->cbData; 02311 break; 02312 } 02313 case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT: 02314 { 02315 PCERT_CONTEXT context = pvSubject; 02316 02317 subjectBlob.pbData = context->pbCertEncoded; 02318 subjectBlob.cbData = context->cbCertEncoded; 02319 break; 02320 } 02321 case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL: 02322 { 02323 PCRL_CONTEXT context = pvSubject; 02324 02325 subjectBlob.pbData = context->pbCrlEncoded; 02326 subjectBlob.cbData = context->cbCrlEncoded; 02327 break; 02328 } 02329 default: 02330 SetLastError(E_INVALIDARG); 02331 ret = FALSE; 02332 } 02333 02334 if (ret) 02335 { 02336 PCERT_SIGNED_CONTENT_INFO signedCert = NULL; 02337 DWORD size = 0; 02338 02339 ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT, 02340 subjectBlob.pbData, subjectBlob.cbData, 02341 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, 02342 &signedCert, &size); 02343 if (ret) 02344 { 02345 switch (dwIssuerType) 02346 { 02347 case CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY: 02348 ret = CRYPT_VerifyCertSignatureFromPublicKeyInfo(hCryptProv, 02349 dwCertEncodingType, pvIssuer, 02350 signedCert); 02351 break; 02352 case CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT: 02353 ret = CRYPT_VerifyCertSignatureFromPublicKeyInfo(hCryptProv, 02354 dwCertEncodingType, 02355 &((PCCERT_CONTEXT)pvIssuer)->pCertInfo->SubjectPublicKeyInfo, 02356 signedCert); 02357 break; 02358 case CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN: 02359 FIXME("CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN: stub\n"); 02360 ret = FALSE; 02361 break; 02362 case CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL: 02363 if (pvIssuer) 02364 { 02365 SetLastError(E_INVALIDARG); 02366 ret = FALSE; 02367 } 02368 else 02369 { 02370 FIXME("unimplemented for NULL signer\n"); 02371 SetLastError(E_INVALIDARG); 02372 ret = FALSE; 02373 } 02374 break; 02375 default: 02376 SetLastError(E_INVALIDARG); 02377 ret = FALSE; 02378 } 02379 LocalFree(signedCert); 02380 } 02381 } 02382 return ret; 02383 } 02384 02385 BOOL WINAPI CertGetIntendedKeyUsage(DWORD dwCertEncodingType, 02386 PCERT_INFO pCertInfo, BYTE *pbKeyUsage, DWORD cbKeyUsage) 02387 { 02388 PCERT_EXTENSION ext; 02389 BOOL ret = FALSE; 02390 02391 TRACE("(%08x, %p, %p, %d)\n", dwCertEncodingType, pCertInfo, pbKeyUsage, 02392 cbKeyUsage); 02393 02394 ext = CertFindExtension(szOID_KEY_USAGE, pCertInfo->cExtension, 02395 pCertInfo->rgExtension); 02396 if (ext) 02397 { 02398 CRYPT_BIT_BLOB usage; 02399 DWORD size = sizeof(usage); 02400 02401 ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS, 02402 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL, 02403 &usage, &size); 02404 if (ret) 02405 { 02406 if (cbKeyUsage < usage.cbData) 02407 ret = FALSE; 02408 else 02409 { 02410 memcpy(pbKeyUsage, usage.pbData, usage.cbData); 02411 if (cbKeyUsage > usage.cbData) 02412 memset(pbKeyUsage + usage.cbData, 0, 02413 cbKeyUsage - usage.cbData); 02414 } 02415 } 02416 } 02417 else 02418 SetLastError(0); 02419 return ret; 02420 } 02421 02422 BOOL WINAPI CertGetEnhancedKeyUsage(PCCERT_CONTEXT pCertContext, DWORD dwFlags, 02423 PCERT_ENHKEY_USAGE pUsage, DWORD *pcbUsage) 02424 { 02425 PCERT_ENHKEY_USAGE usage = NULL; 02426 DWORD bytesNeeded; 02427 BOOL ret = TRUE; 02428 02429 if (!pCertContext || !pcbUsage) 02430 { 02431 SetLastError(ERROR_INVALID_PARAMETER); 02432 return FALSE; 02433 } 02434 02435 TRACE("(%p, %08x, %p, %d)\n", pCertContext, dwFlags, pUsage, *pcbUsage); 02436 02437 if (!(dwFlags & CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG)) 02438 { 02439 DWORD propSize = 0; 02440 02441 if (CertGetCertificateContextProperty(pCertContext, 02442 CERT_ENHKEY_USAGE_PROP_ID, NULL, &propSize)) 02443 { 02444 LPBYTE buf = CryptMemAlloc(propSize); 02445 02446 if (buf) 02447 { 02448 if (CertGetCertificateContextProperty(pCertContext, 02449 CERT_ENHKEY_USAGE_PROP_ID, buf, &propSize)) 02450 { 02451 ret = CryptDecodeObjectEx(pCertContext->dwCertEncodingType, 02452 X509_ENHANCED_KEY_USAGE, buf, propSize, 02453 CRYPT_ENCODE_ALLOC_FLAG, NULL, &usage, &bytesNeeded); 02454 } 02455 CryptMemFree(buf); 02456 } 02457 } 02458 } 02459 if (!usage && !(dwFlags & CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG)) 02460 { 02461 PCERT_EXTENSION ext = CertFindExtension(szOID_ENHANCED_KEY_USAGE, 02462 pCertContext->pCertInfo->cExtension, 02463 pCertContext->pCertInfo->rgExtension); 02464 02465 if (ext) 02466 { 02467 ret = CryptDecodeObjectEx(pCertContext->dwCertEncodingType, 02468 X509_ENHANCED_KEY_USAGE, ext->Value.pbData, ext->Value.cbData, 02469 CRYPT_ENCODE_ALLOC_FLAG, NULL, &usage, &bytesNeeded); 02470 } 02471 } 02472 if (!usage) 02473 { 02474 /* If a particular location is specified, this should fail. Otherwise 02475 * it should succeed with an empty usage. (This is true on Win2k and 02476 * later, which we emulate.) 02477 */ 02478 if (dwFlags) 02479 { 02480 SetLastError(CRYPT_E_NOT_FOUND); 02481 ret = FALSE; 02482 } 02483 else 02484 bytesNeeded = sizeof(CERT_ENHKEY_USAGE); 02485 } 02486 02487 if (ret) 02488 { 02489 if (!pUsage) 02490 *pcbUsage = bytesNeeded; 02491 else if (*pcbUsage < bytesNeeded) 02492 { 02493 SetLastError(ERROR_MORE_DATA); 02494 *pcbUsage = bytesNeeded; 02495 ret = FALSE; 02496 } 02497 else 02498 { 02499 *pcbUsage = bytesNeeded; 02500 if (usage) 02501 { 02502 DWORD i; 02503 LPSTR nextOID = (LPSTR)((LPBYTE)pUsage + 02504 sizeof(CERT_ENHKEY_USAGE) + 02505 usage->cUsageIdentifier * sizeof(LPSTR)); 02506 02507 pUsage->cUsageIdentifier = usage->cUsageIdentifier; 02508 pUsage->rgpszUsageIdentifier = (LPSTR *)((LPBYTE)pUsage + 02509 sizeof(CERT_ENHKEY_USAGE)); 02510 for (i = 0; i < usage->cUsageIdentifier; i++) 02511 { 02512 pUsage->rgpszUsageIdentifier[i] = nextOID; 02513 strcpy(nextOID, usage->rgpszUsageIdentifier[i]); 02514 nextOID += strlen(nextOID) + 1; 02515 } 02516 } 02517 else 02518 pUsage->cUsageIdentifier = 0; 02519 } 02520 } 02521 if (usage) 02522 LocalFree(usage); 02523 TRACE("returning %d\n", ret); 02524 return ret; 02525 } 02526 02527 BOOL WINAPI CertSetEnhancedKeyUsage(PCCERT_CONTEXT pCertContext, 02528 PCERT_ENHKEY_USAGE pUsage) 02529 { 02530 BOOL ret; 02531 02532 TRACE("(%p, %p)\n", pCertContext, pUsage); 02533 02534 if (pUsage) 02535 { 02536 CRYPT_DATA_BLOB blob = { 0, NULL }; 02537 02538 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, 02539 pUsage, CRYPT_ENCODE_ALLOC_FLAG, NULL, &blob.pbData, &blob.cbData); 02540 if (ret) 02541 { 02542 ret = CertSetCertificateContextProperty(pCertContext, 02543 CERT_ENHKEY_USAGE_PROP_ID, 0, &blob); 02544 LocalFree(blob.pbData); 02545 } 02546 } 02547 else 02548 ret = CertSetCertificateContextProperty(pCertContext, 02549 CERT_ENHKEY_USAGE_PROP_ID, 0, NULL); 02550 return ret; 02551 } 02552 02553 BOOL WINAPI CertAddEnhancedKeyUsageIdentifier(PCCERT_CONTEXT pCertContext, 02554 LPCSTR pszUsageIdentifier) 02555 { 02556 BOOL ret; 02557 DWORD size; 02558 02559 TRACE("(%p, %s)\n", pCertContext, debugstr_a(pszUsageIdentifier)); 02560 02561 if (CertGetEnhancedKeyUsage(pCertContext, 02562 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size)) 02563 { 02564 PCERT_ENHKEY_USAGE usage = CryptMemAlloc(size); 02565 02566 if (usage) 02567 { 02568 ret = CertGetEnhancedKeyUsage(pCertContext, 02569 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, usage, &size); 02570 if (ret) 02571 { 02572 DWORD i; 02573 BOOL exists = FALSE; 02574 02575 /* Make sure usage doesn't already exist */ 02576 for (i = 0; !exists && i < usage->cUsageIdentifier; i++) 02577 { 02578 if (!strcmp(usage->rgpszUsageIdentifier[i], 02579 pszUsageIdentifier)) 02580 exists = TRUE; 02581 } 02582 if (!exists) 02583 { 02584 PCERT_ENHKEY_USAGE newUsage = CryptMemAlloc(size + 02585 sizeof(LPSTR) + strlen(pszUsageIdentifier) + 1); 02586 02587 if (newUsage) 02588 { 02589 LPSTR nextOID; 02590 02591 newUsage->rgpszUsageIdentifier = (LPSTR *) 02592 ((LPBYTE)newUsage + sizeof(CERT_ENHKEY_USAGE)); 02593 nextOID = (LPSTR)((LPBYTE)newUsage->rgpszUsageIdentifier 02594 + (usage->cUsageIdentifier + 1) * sizeof(LPSTR)); 02595 for (i = 0; i < usage->cUsageIdentifier; i++) 02596 { 02597 newUsage->rgpszUsageIdentifier[i] = nextOID; 02598 strcpy(nextOID, usage->rgpszUsageIdentifier[i]); 02599 nextOID += strlen(nextOID) + 1; 02600 } 02601 newUsage->rgpszUsageIdentifier[i] = nextOID; 02602 strcpy(nextOID, pszUsageIdentifier); 02603 newUsage->cUsageIdentifier = i + 1; 02604 ret = CertSetEnhancedKeyUsage(pCertContext, newUsage); 02605 CryptMemFree(newUsage); 02606 } 02607 else 02608 ret = FALSE; 02609 } 02610 } 02611 CryptMemFree(usage); 02612 } 02613 else 02614 ret = FALSE; 02615 } 02616 else 02617 { 02618 PCERT_ENHKEY_USAGE usage = CryptMemAlloc(sizeof(CERT_ENHKEY_USAGE) + 02619 sizeof(LPSTR) + strlen(pszUsageIdentifier) + 1); 02620 02621 if (usage) 02622 { 02623 usage->rgpszUsageIdentifier = 02624 (LPSTR *)((LPBYTE)usage + sizeof(CERT_ENHKEY_USAGE)); 02625 usage->rgpszUsageIdentifier[0] = (LPSTR)((LPBYTE)usage + 02626 sizeof(CERT_ENHKEY_USAGE) + sizeof(LPSTR)); 02627 strcpy(usage->rgpszUsageIdentifier[0], pszUsageIdentifier); 02628 usage->cUsageIdentifier = 1; 02629 ret = CertSetEnhancedKeyUsage(pCertContext, usage); 02630 CryptMemFree(usage); 02631 } 02632 else 02633 ret = FALSE; 02634 } 02635 return ret; 02636 } 02637 02638 BOOL WINAPI CertRemoveEnhancedKeyUsageIdentifier(PCCERT_CONTEXT pCertContext, 02639 LPCSTR pszUsageIdentifier) 02640 { 02641 BOOL ret; 02642 DWORD size; 02643 CERT_ENHKEY_USAGE usage; 02644 02645 TRACE("(%p, %s)\n", pCertContext, debugstr_a(pszUsageIdentifier)); 02646 02647 size = sizeof(usage); 02648 ret = CertGetEnhancedKeyUsage(pCertContext, 02649 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, &usage, &size); 02650 if (!ret && GetLastError() == ERROR_MORE_DATA) 02651 { 02652 PCERT_ENHKEY_USAGE pUsage = CryptMemAlloc(size); 02653 02654 if (pUsage) 02655 { 02656 ret = CertGetEnhancedKeyUsage(pCertContext, 02657 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size); 02658 if (ret) 02659 { 02660 if (pUsage->cUsageIdentifier) 02661 { 02662 DWORD i; 02663 BOOL found = FALSE; 02664 02665 for (i = 0; i < pUsage->cUsageIdentifier; i++) 02666 { 02667 if (!strcmp(pUsage->rgpszUsageIdentifier[i], 02668 pszUsageIdentifier)) 02669 found = TRUE; 02670 if (found && i < pUsage->cUsageIdentifier - 1) 02671 pUsage->rgpszUsageIdentifier[i] = 02672 pUsage->rgpszUsageIdentifier[i + 1]; 02673 } 02674 pUsage->cUsageIdentifier--; 02675 /* Remove the usage if it's empty */ 02676 if (pUsage->cUsageIdentifier) 02677 ret = CertSetEnhancedKeyUsage(pCertContext, pUsage); 02678 else 02679 ret = CertSetEnhancedKeyUsage(pCertContext, NULL); 02680 } 02681 } 02682 CryptMemFree(pUsage); 02683 } 02684 else 02685 ret = FALSE; 02686 } 02687 else 02688 { 02689 /* it fit in an empty usage, therefore there's nothing to remove */ 02690 ret = TRUE; 02691 } 02692 return ret; 02693 } 02694 02695 struct BitField 02696 { 02697 DWORD cIndexes; 02698 DWORD *indexes; 02699 }; 02700 02701 #define BITS_PER_DWORD (sizeof(DWORD) * 8) 02702 02703 static void CRYPT_SetBitInField(struct BitField *field, DWORD bit) 02704 { 02705 DWORD indexIndex = bit / BITS_PER_DWORD; 02706 02707 if (indexIndex + 1 > field->cIndexes) 02708 { 02709 if (field->cIndexes) 02710 field->indexes = CryptMemRealloc(field->indexes, 02711 (indexIndex + 1) * sizeof(DWORD)); 02712 else 02713 field->indexes = CryptMemAlloc(sizeof(DWORD)); 02714 if (field->indexes) 02715 { 02716 field->indexes[indexIndex] = 0; 02717 field->cIndexes = indexIndex + 1; 02718 } 02719 } 02720 if (field->indexes) 02721 field->indexes[indexIndex] |= 1 << (bit % BITS_PER_DWORD); 02722 } 02723 02724 static BOOL CRYPT_IsBitInFieldSet(const struct BitField *field, DWORD bit) 02725 { 02726 BOOL set = FALSE; 02727 DWORD indexIndex = bit / BITS_PER_DWORD; 02728 02729 assert(field->cIndexes); 02730 set = field->indexes[indexIndex] & (1 << (bit % BITS_PER_DWORD)); 02731 return set; 02732 } 02733 02734 BOOL WINAPI CertGetValidUsages(DWORD cCerts, PCCERT_CONTEXT *rghCerts, 02735 int *cNumOIDs, LPSTR *rghOIDs, DWORD *pcbOIDs) 02736 { 02737 BOOL ret = TRUE; 02738 DWORD i, cbOIDs = 0; 02739 BOOL allUsagesValid = TRUE; 02740 CERT_ENHKEY_USAGE validUsages = { 0, NULL }; 02741 02742 TRACE("(%d, %p, %d, %p, %d)\n", cCerts, rghCerts, *cNumOIDs, 02743 rghOIDs, *pcbOIDs); 02744 02745 for (i = 0; i < cCerts; i++) 02746 { 02747 CERT_ENHKEY_USAGE usage; 02748 DWORD size = sizeof(usage); 02749 02750 ret = CertGetEnhancedKeyUsage(rghCerts[i], 0, &usage, &size); 02751 /* Success is deliberately ignored: it implies all usages are valid */ 02752 if (!ret && GetLastError() == ERROR_MORE_DATA) 02753 { 02754 PCERT_ENHKEY_USAGE pUsage = CryptMemAlloc(size); 02755 02756 allUsagesValid = FALSE; 02757 if (pUsage) 02758 { 02759 ret = CertGetEnhancedKeyUsage(rghCerts[i], 0, pUsage, &size); 02760 if (ret) 02761 { 02762 if (!validUsages.cUsageIdentifier) 02763 { 02764 DWORD j; 02765 02766 cbOIDs = pUsage->cUsageIdentifier * sizeof(LPSTR); 02767 validUsages.cUsageIdentifier = pUsage->cUsageIdentifier; 02768 for (j = 0; j < validUsages.cUsageIdentifier; j++) 02769 cbOIDs += lstrlenA(pUsage->rgpszUsageIdentifier[j]) 02770 + 1; 02771 validUsages.rgpszUsageIdentifier = 02772 CryptMemAlloc(cbOIDs); 02773 if (validUsages.rgpszUsageIdentifier) 02774 { 02775 LPSTR nextOID = (LPSTR) 02776 ((LPBYTE)validUsages.rgpszUsageIdentifier + 02777 validUsages.cUsageIdentifier * sizeof(LPSTR)); 02778 02779 for (j = 0; j < validUsages.cUsageIdentifier; j++) 02780 { 02781 validUsages.rgpszUsageIdentifier[j] = nextOID; 02782 lstrcpyA(validUsages.rgpszUsageIdentifier[j], 02783 pUsage->rgpszUsageIdentifier[j]); 02784 nextOID += lstrlenA(nextOID) + 1; 02785 } 02786 } 02787 } 02788 else 02789 { 02790 struct BitField validIndexes = { 0, NULL }; 02791 DWORD j, k, numRemoved = 0; 02792 02793 /* Merge: build a bitmap of all the indexes of 02794 * validUsages.rgpszUsageIdentifier that are in pUsage. 02795 */ 02796 for (j = 0; j < pUsage->cUsageIdentifier; j++) 02797 { 02798 for (k = 0; k < validUsages.cUsageIdentifier; k++) 02799 { 02800 if (!strcmp(pUsage->rgpszUsageIdentifier[j], 02801 validUsages.rgpszUsageIdentifier[k])) 02802 { 02803 CRYPT_SetBitInField(&validIndexes, k); 02804 break; 02805 } 02806 } 02807 } 02808 /* Merge by removing from validUsages those that are 02809 * not in the bitmap. 02810 */ 02811 for (j = 0; j < validUsages.cUsageIdentifier; j++) 02812 { 02813 if (!CRYPT_IsBitInFieldSet(&validIndexes, j)) 02814 { 02815 if (j < validUsages.cUsageIdentifier - 1) 02816 { 02817 memmove(&validUsages.rgpszUsageIdentifier[j], 02818 &validUsages.rgpszUsageIdentifier[j + 02819 numRemoved + 1], 02820 (validUsages.cUsageIdentifier - numRemoved 02821 - j - 1) * sizeof(LPSTR)); 02822 cbOIDs -= lstrlenA( 02823 validUsages.rgpszUsageIdentifier[j]) + 1 + 02824 sizeof(LPSTR); 02825 validUsages.cUsageIdentifier--; 02826 numRemoved++; 02827 } 02828 else 02829 validUsages.cUsageIdentifier--; 02830 } 02831 } 02832 CryptMemFree(validIndexes.indexes); 02833 } 02834 } 02835 CryptMemFree(pUsage); 02836 } 02837 } 02838 } 02839 ret = TRUE; 02840 if (allUsagesValid) 02841 { 02842 *cNumOIDs = -1; 02843 *pcbOIDs = 0; 02844 } 02845 else 02846 { 02847 *cNumOIDs = validUsages.cUsageIdentifier; 02848 if (!rghOIDs) 02849 *pcbOIDs = cbOIDs; 02850 else if (*pcbOIDs < cbOIDs) 02851 { 02852 *pcbOIDs = cbOIDs; 02853 SetLastError(ERROR_MORE_DATA); 02854 ret = FALSE; 02855 } 02856 else 02857 { 02858 LPSTR nextOID = (LPSTR)((LPBYTE)rghOIDs + 02859 validUsages.cUsageIdentifier * sizeof(LPSTR)); 02860 02861 *pcbOIDs = cbOIDs; 02862 for (i = 0; i < validUsages.cUsageIdentifier; i++) 02863 { 02864 rghOIDs[i] = nextOID; 02865 lstrcpyA(nextOID, validUsages.rgpszUsageIdentifier[i]); 02866 nextOID += lstrlenA(nextOID) + 1; 02867 } 02868 } 02869 } 02870 CryptMemFree(validUsages.rgpszUsageIdentifier); 02871 TRACE("cNumOIDs: %d\n", *cNumOIDs); 02872 TRACE("returning %d\n", ret); 02873 return ret; 02874 } 02875 02876 /* Sets the CERT_KEY_PROV_INFO_PROP_ID property of context from pInfo, or, if 02877 * pInfo is NULL, from the attributes of hProv. 02878 */ 02879 static void CertContext_SetKeyProvInfo(PCCERT_CONTEXT context, 02880 const CRYPT_KEY_PROV_INFO *pInfo, HCRYPTPROV hProv) 02881 { 02882 CRYPT_KEY_PROV_INFO info = { 0 }; 02883 BOOL ret; 02884 02885 if (!pInfo) 02886 { 02887 DWORD size; 02888 int len; 02889 02890 ret = CryptGetProvParam(hProv, PP_CONTAINER, NULL, &size, 0); 02891 if (ret) 02892 { 02893 LPSTR szContainer = CryptMemAlloc(size); 02894 02895 if (szContainer) 02896 { 02897 ret = CryptGetProvParam(hProv, PP_CONTAINER, 02898 (BYTE *)szContainer, &size, 0); 02899 if (ret) 02900 { 02901 len = MultiByteToWideChar(CP_ACP, 0, szContainer, -1, 02902 NULL, 0); 02903 if (len) 02904 { 02905 info.pwszContainerName = CryptMemAlloc(len * 02906 sizeof(WCHAR)); 02907 MultiByteToWideChar(CP_ACP, 0, szContainer, -1, 02908 info.pwszContainerName, len); 02909 } 02910 } 02911 CryptMemFree(szContainer); 02912 } 02913 } 02914 ret = CryptGetProvParam(hProv, PP_NAME, NULL, &size, 0); 02915 if (ret) 02916 { 02917 LPSTR szProvider = CryptMemAlloc(size); 02918 02919 if (szProvider) 02920 { 02921 ret = CryptGetProvParam(hProv, PP_NAME, (BYTE *)szProvider, 02922 &size, 0); 02923 if (ret) 02924 { 02925 len = MultiByteToWideChar(CP_ACP, 0, szProvider, -1, 02926 NULL, 0); 02927 if (len) 02928 { 02929 info.pwszProvName = CryptMemAlloc(len * 02930 sizeof(WCHAR)); 02931 MultiByteToWideChar(CP_ACP, 0, szProvider, -1, 02932 info.pwszProvName, len); 02933 } 02934 } 02935 CryptMemFree(szProvider); 02936 } 02937 } 02938 size = sizeof(info.dwKeySpec); 02939 /* in case no CRYPT_KEY_PROV_INFO given, 02940 * we always use AT_SIGNATURE key spec 02941 */ 02942 info.dwKeySpec = AT_SIGNATURE; 02943 size = sizeof(info.dwProvType); 02944 ret = CryptGetProvParam(hProv, PP_PROVTYPE, (LPBYTE)&info.dwProvType, 02945 &size, 0); 02946 if (!ret) 02947 info.dwProvType = PROV_RSA_FULL; 02948 pInfo = &info; 02949 } 02950 02951 CertSetCertificateContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID, 02952 0, pInfo); 02953 02954 if (pInfo == &info) 02955 { 02956 CryptMemFree(info.pwszContainerName); 02957 CryptMemFree(info.pwszProvName); 02958 } 02959 } 02960 02961 /* Creates a signed certificate context from the unsigned, encoded certificate 02962 * in blob, using the crypto provider hProv and the signature algorithm sigAlgo. 02963 */ 02964 static PCCERT_CONTEXT CRYPT_CreateSignedCert(const CRYPT_DER_BLOB *blob, 02965 HCRYPTPROV hProv, DWORD dwKeySpec, PCRYPT_ALGORITHM_IDENTIFIER sigAlgo) 02966 { 02967 PCCERT_CONTEXT context = NULL; 02968 BOOL ret; 02969 DWORD sigSize = 0; 02970 02971 ret = CryptSignCertificate(hProv, dwKeySpec, X509_ASN_ENCODING, 02972 blob->pbData, blob->cbData, sigAlgo, NULL, NULL, &sigSize); 02973 if (ret) 02974 { 02975 LPBYTE sig = CryptMemAlloc(sigSize); 02976 02977 ret = CryptSignCertificate(hProv, dwKeySpec, X509_ASN_ENCODING, 02978 blob->pbData, blob->cbData, sigAlgo, NULL, sig, &sigSize); 02979 if (ret) 02980 { 02981 CERT_SIGNED_CONTENT_INFO signedInfo; 02982 BYTE *encodedSignedCert = NULL; 02983 DWORD encodedSignedCertSize = 0; 02984 02985 signedInfo.ToBeSigned.cbData = blob->cbData; 02986 signedInfo.ToBeSigned.pbData = blob->pbData; 02987 memcpy(&signedInfo.SignatureAlgorithm, sigAlgo, 02988 sizeof(signedInfo.SignatureAlgorithm)); 02989 signedInfo.Signature.cbData = sigSize; 02990 signedInfo.Signature.pbData = sig; 02991 signedInfo.Signature.cUnusedBits = 0; 02992 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, 02993 &signedInfo, CRYPT_ENCODE_ALLOC_FLAG, NULL, 02994 &encodedSignedCert, &encodedSignedCertSize); 02995 if (ret) 02996 { 02997 context = CertCreateCertificateContext(X509_ASN_ENCODING, 02998 encodedSignedCert, encodedSignedCertSize); 02999 LocalFree(encodedSignedCert); 03000 } 03001 } 03002 CryptMemFree(sig); 03003 } 03004 return context; 03005 } 03006 03007 /* Copies data from the parameters into info, where: 03008 * pSerialNumber: The serial number. Must not be NULL. 03009 * pSubjectIssuerBlob: Specifies both the subject and issuer for info. 03010 * Must not be NULL 03011 * pSignatureAlgorithm: Optional. 03012 * pStartTime: The starting time of the certificate. If NULL, the current 03013 * system time is used. 03014 * pEndTime: The ending time of the certificate. If NULL, one year past the 03015 * starting time is used. 03016 * pubKey: The public key of the certificate. Must not be NULL. 03017 * pExtensions: Extensions to be included with the certificate. Optional. 03018 */ 03019 static void CRYPT_MakeCertInfo(PCERT_INFO info, const CRYPT_DATA_BLOB *pSerialNumber, 03020 const CERT_NAME_BLOB *pSubjectIssuerBlob, 03021 const CRYPT_ALGORITHM_IDENTIFIER *pSignatureAlgorithm, const SYSTEMTIME *pStartTime, 03022 const SYSTEMTIME *pEndTime, const CERT_PUBLIC_KEY_INFO *pubKey, 03023 const CERT_EXTENSIONS *pExtensions) 03024 { 03025 static CHAR oid[] = szOID_RSA_SHA1RSA; 03026 03027 assert(info); 03028 assert(pSerialNumber); 03029 assert(pSubjectIssuerBlob); 03030 assert(pubKey); 03031 03032 if (pExtensions && pExtensions->cExtension) 03033 info->dwVersion = CERT_V3; 03034 else 03035 info->dwVersion = CERT_V1; 03036 info->SerialNumber.cbData = pSerialNumber->cbData; 03037 info->SerialNumber.pbData = pSerialNumber->pbData; 03038 if (pSignatureAlgorithm) 03039 memcpy(&info->SignatureAlgorithm, pSignatureAlgorithm, 03040 sizeof(info->SignatureAlgorithm)); 03041 else 03042 { 03043 info->SignatureAlgorithm.pszObjId = oid; 03044 info->SignatureAlgorithm.Parameters.cbData = 0; 03045 info->SignatureAlgorithm.Parameters.pbData = NULL; 03046 } 03047 info->Issuer.cbData = pSubjectIssuerBlob->cbData; 03048 info->Issuer.pbData = pSubjectIssuerBlob->pbData; 03049 if (pStartTime) 03050 SystemTimeToFileTime(pStartTime, &info->NotBefore); 03051 else 03052 GetSystemTimeAsFileTime(&info->NotBefore); 03053 if (pEndTime) 03054 SystemTimeToFileTime(pEndTime, &info->NotAfter); 03055 else 03056 { 03057 SYSTEMTIME endTime; 03058 03059 if (FileTimeToSystemTime(&info->NotBefore, &endTime)) 03060 { 03061 endTime.wYear++; 03062 SystemTimeToFileTime(&endTime, &info->NotAfter); 03063 } 03064 } 03065 info->Subject.cbData = pSubjectIssuerBlob->cbData; 03066 info->Subject.pbData = pSubjectIssuerBlob->pbData; 03067 memcpy(&info->SubjectPublicKeyInfo, pubKey, 03068 sizeof(info->SubjectPublicKeyInfo)); 03069 if (pExtensions) 03070 { 03071 info->cExtension = pExtensions->cExtension; 03072 info->rgExtension = pExtensions->rgExtension; 03073 } 03074 else 03075 { 03076 info->cExtension = 0; 03077 info->rgExtension = NULL; 03078 } 03079 } 03080 03081 typedef RPC_STATUS (RPC_ENTRY *UuidCreateFunc)(UUID *); 03082 typedef RPC_STATUS (RPC_ENTRY *UuidToStringFunc)(UUID *, unsigned char **); 03083 typedef RPC_STATUS (RPC_ENTRY *RpcStringFreeFunc)(unsigned char **); 03084 03085 static HCRYPTPROV CRYPT_CreateKeyProv(void) 03086 { 03087 HCRYPTPROV hProv = 0; 03088 HMODULE rpcrt = LoadLibraryA("rpcrt4"); 03089 03090 if (rpcrt) 03091 { 03092 UuidCreateFunc uuidCreate = (UuidCreateFunc)GetProcAddress(rpcrt, 03093 "UuidCreate"); 03094 UuidToStringFunc uuidToString = (UuidToStringFunc)GetProcAddress(rpcrt, 03095 "UuidToStringA"); 03096 RpcStringFreeFunc rpcStringFree = (RpcStringFreeFunc)GetProcAddress( 03097 rpcrt, "RpcStringFreeA"); 03098 03099 if (uuidCreate && uuidToString && rpcStringFree) 03100 { 03101 UUID uuid; 03102 RPC_STATUS status = uuidCreate(&uuid); 03103 03104 if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) 03105 { 03106 unsigned char *uuidStr; 03107 03108 status = uuidToString(&uuid, &uuidStr); 03109 if (status == RPC_S_OK) 03110 { 03111 BOOL ret = CryptAcquireContextA(&hProv, (LPCSTR)uuidStr, 03112 MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_NEWKEYSET); 03113 03114 if (ret) 03115 { 03116 HCRYPTKEY key; 03117 03118 ret = CryptGenKey(hProv, AT_SIGNATURE, 0, &key); 03119 if (ret) 03120 CryptDestroyKey(key); 03121 } 03122 rpcStringFree(&uuidStr); 03123 } 03124 } 03125 } 03126 FreeLibrary(rpcrt); 03127 } 03128 return hProv; 03129 } 03130 03131 PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hProv, 03132 PCERT_NAME_BLOB pSubjectIssuerBlob, DWORD dwFlags, 03133 PCRYPT_KEY_PROV_INFO pKeyProvInfo, 03134 PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, PSYSTEMTIME pStartTime, 03135 PSYSTEMTIME pEndTime, PCERT_EXTENSIONS pExtensions) 03136 { 03137 PCCERT_CONTEXT context = NULL; 03138 BOOL ret, releaseContext = FALSE; 03139 PCERT_PUBLIC_KEY_INFO pubKey = NULL; 03140 DWORD pubKeySize = 0,dwKeySpec = AT_SIGNATURE; 03141 03142 TRACE("(%08lx, %p, %08x, %p, %p, %p, %p, %p)\n", hProv, 03143 pSubjectIssuerBlob, dwFlags, pKeyProvInfo, pSignatureAlgorithm, pStartTime, 03144 pExtensions, pExtensions); 03145 03146 if(!pSubjectIssuerBlob) 03147 { 03148 SetLastError(ERROR_INVALID_PARAMETER); 03149 return NULL; 03150 } 03151 03152 if (!hProv) 03153 { 03154 if (!pKeyProvInfo) 03155 { 03156 hProv = CRYPT_CreateKeyProv(); 03157 releaseContext = TRUE; 03158 } 03159 else if (pKeyProvInfo->dwFlags & CERT_SET_KEY_PROV_HANDLE_PROP_ID) 03160 { 03161 SetLastError(NTE_BAD_FLAGS); 03162 return NULL; 03163 } 03164 else 03165 { 03166 HCRYPTKEY hKey = 0; 03167 /* acquire the context using the given information*/ 03168 ret = CryptAcquireContextW(&hProv,pKeyProvInfo->pwszContainerName, 03169 pKeyProvInfo->pwszProvName,pKeyProvInfo->dwProvType, 03170 pKeyProvInfo->dwFlags); 03171 if (!ret) 03172 { 03173 if(GetLastError() != NTE_BAD_KEYSET) 03174 return NULL; 03175 /* create the key set */ 03176 ret = CryptAcquireContextW(&hProv,pKeyProvInfo->pwszContainerName, 03177 pKeyProvInfo->pwszProvName,pKeyProvInfo->dwProvType, 03178 pKeyProvInfo->dwFlags|CRYPT_NEWKEYSET); 03179 if (!ret) 03180 return NULL; 03181 } 03182 dwKeySpec = pKeyProvInfo->dwKeySpec; 03183 /* check if the key is here */ 03184 ret = CryptGetUserKey(hProv,dwKeySpec,&hKey); 03185 if(!ret) 03186 { 03187 if (NTE_NO_KEY == GetLastError()) 03188 { /* generate the key */ 03189 ret = CryptGenKey(hProv,dwKeySpec,0,&hKey); 03190 } 03191 if (!ret) 03192 { 03193 CryptReleaseContext(hProv,0); 03194 SetLastError(NTE_BAD_KEYSET); 03195 return NULL; 03196 } 03197 } 03198 CryptDestroyKey(hKey); 03199 releaseContext = TRUE; 03200 } 03201 } 03202 else if (pKeyProvInfo) 03203 { 03204 SetLastError(ERROR_INVALID_PARAMETER); 03205 return NULL; 03206 } 03207 03208 CryptExportPublicKeyInfo(hProv, dwKeySpec, X509_ASN_ENCODING, NULL, 03209 &pubKeySize); 03210 pubKey = CryptMemAlloc(pubKeySize); 03211 if (pubKey) 03212 { 03213 ret = CryptExportPublicKeyInfo(hProv, dwKeySpec, X509_ASN_ENCODING, 03214 pubKey, &pubKeySize); 03215 if (ret) 03216 { 03217 CERT_INFO info = { 0 }; 03218 CRYPT_DER_BLOB blob = { 0, NULL }; 03219 BYTE serial[16]; 03220 CRYPT_DATA_BLOB serialBlob = { sizeof(serial), serial }; 03221 03222 CryptGenRandom(hProv, sizeof(serial), serial); 03223 CRYPT_MakeCertInfo(&info, &serialBlob, pSubjectIssuerBlob, 03224 pSignatureAlgorithm, pStartTime, pEndTime, pubKey, pExtensions); 03225 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, 03226 &info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &blob.pbData, 03227 &blob.cbData); 03228 if (ret) 03229 { 03230 if (!(dwFlags & CERT_CREATE_SELFSIGN_NO_SIGN)) 03231 context = CRYPT_CreateSignedCert(&blob, hProv,dwKeySpec, 03232 &info.SignatureAlgorithm); 03233 else 03234 context = CertCreateCertificateContext(X509_ASN_ENCODING, 03235 blob.pbData, blob.cbData); 03236 if (context && !(dwFlags & CERT_CREATE_SELFSIGN_NO_KEY_INFO)) 03237 CertContext_SetKeyProvInfo(context, pKeyProvInfo, hProv); 03238 LocalFree(blob.pbData); 03239 } 03240 } 03241 CryptMemFree(pubKey); 03242 } 03243 if (releaseContext) 03244 CryptReleaseContext(hProv, 0); 03245 return context; 03246 } 03247 03248 BOOL WINAPI CertVerifyCTLUsage(DWORD dwEncodingType, DWORD dwSubjectType, 03249 void *pvSubject, PCTL_USAGE pSubjectUsage, DWORD dwFlags, 03250 PCTL_VERIFY_USAGE_PARA pVerifyUsagePara, 03251 PCTL_VERIFY_USAGE_STATUS pVerifyUsageStatus) 03252 { 03253 FIXME("(0x%x, %d, %p, %p, 0x%x, %p, %p): stub\n", dwEncodingType, 03254 dwSubjectType, pvSubject, pSubjectUsage, dwFlags, pVerifyUsagePara, 03255 pVerifyUsageStatus); 03256 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 03257 return FALSE; 03258 } 03259 03260 const void * WINAPI CertCreateContext(DWORD dwContextType, DWORD dwEncodingType, 03261 const BYTE *pbEncoded, DWORD cbEncoded, 03262 DWORD dwFlags, PCERT_CREATE_CONTEXT_PARA pCreatePara) 03263 { 03264 TRACE("(0x%x, 0x%x, %p, %d, 0x%08x, %p)\n", dwContextType, dwEncodingType, 03265 pbEncoded, cbEncoded, dwFlags, pCreatePara); 03266 03267 if (dwFlags) 03268 { 03269 FIXME("dwFlags 0x%08x not handled\n", dwFlags); 03270 return NULL; 03271 } 03272 if (pCreatePara) 03273 { 03274 FIXME("pCreatePara not handled\n"); 03275 return NULL; 03276 } 03277 03278 switch (dwContextType) 03279 { 03280 case CERT_STORE_CERTIFICATE_CONTEXT: 03281 return CertCreateCertificateContext(dwEncodingType, pbEncoded, cbEncoded); 03282 case CERT_STORE_CRL_CONTEXT: 03283 return CertCreateCRLContext(dwEncodingType, pbEncoded, cbEncoded); 03284 case CERT_STORE_CTL_CONTEXT: 03285 return CertCreateCTLContext(dwEncodingType, pbEncoded, cbEncoded); 03286 default: 03287 WARN("unknown context type: 0x%x\n", dwContextType); 03288 return NULL; 03289 } 03290 } Generated on Sun May 27 2012 04:23:11 for ReactOS by
1.7.6.1
|