//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: wthelper.cpp // // Contents: Microsoft Internet Security Trust Provider // // Functions: WTHelperGetProvPrivateDataFromChain // WTHelperGetProvSignerFromChain // WTHelperGetFileHandle // WTHelperGetFileName // WTHelperOpenKnownStores // WTHelperGetProvCertFromChain // WTHelperCheckCertUsage // WTHelperIsInRootStore // WTHelperProvDataFromStateData // WTHelperGetAgencyInfo // // *** local functions *** // _FindKeyUsage // // History: 01-Jun-1997 pberkman created // //-------------------------------------------------------------------------- #include "global.hxx" #include "pkialloc.h" BOOL _FindKeyUsage(PCERT_ENHKEY_USAGE pUsage, LPCSTR pszRequestedUsageOID); CRYPT_PROVIDER_PRIVDATA * WINAPI WTHelperGetProvPrivateDataFromChain(CRYPT_PROVIDER_DATA *pProvData, GUID *pgProviderID) { if (!(pProvData) || !(pgProviderID)) { return(NULL); } for (int i = 0; i < (int)pProvData->csProvPrivData; i++) { if (memcmp(&pProvData->pasProvPrivData[i].gProviderID, pgProviderID, sizeof(GUID)) == 0) { return(&pProvData->pasProvPrivData[i]); } } return(NULL); } CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner, DWORD idxCounterSigner) { if (!(pProvData) || (idxSigner >= pProvData->csSigners)) { return(NULL); } if (fCounterSigner) { if (idxCounterSigner >= pProvData->pasSigners[idxSigner].csCounterSigners) { return(NULL); } return(&pProvData->pasSigners[idxSigner].pasCounterSigners[idxCounterSigner]); } return(&pProvData->pasSigners[idxSigner]); } CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert) { if (!(pSgnr) || (idxCert >= pSgnr->csCertChain)) { return(NULL); } return(&pSgnr->pasCertChain[idxCert]); } HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *pWintrustData) { switch (pWintrustData->dwUnionChoice) { case WTD_CHOICE_FILE: return(pWintrustData->pFile->hFile); case WTD_CHOICE_CATALOG: return(pWintrustData->pCatalog->hMemberFile); } return(INVALID_HANDLE_VALUE); } WCHAR * WINAPI WTHelperGetFileName(WINTRUST_DATA *pWintrustData) { switch (pWintrustData->dwUnionChoice) { case WTD_CHOICE_FILE: return((WCHAR *)pWintrustData->pFile->pcwszFilePath); case WTD_CHOICE_CATALOG: if (!(pWintrustData->pCatalog->pcwszCatalogFilePath) || !(pWintrustData->pCatalog->pcwszMemberTag)) { return(NULL); } return((WCHAR *)pWintrustData->pCatalog->pcwszMemberFilePath); case WTD_CHOICE_CERT: if (pWintrustData->pCert->pcwszDisplayName) return (WCHAR *) pWintrustData->pCert->pcwszDisplayName; else return L"Certificate"; case WTD_CHOICE_BLOB: if (pWintrustData->pBlob->pcwszDisplayName) return (WCHAR *) pWintrustData->pBlob->pcwszDisplayName; else return L"Blob"; } return(NULL); } BOOL WINAPI WTHelperOpenKnownStores(CRYPT_PROVIDER_DATA *pProvData) { DWORD i; DWORD cs; HCERTSTORE *pas; if ((pProvData->pWintrustData) && (pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CERT) && (_ISINSTRUCT(WINTRUST_CERT_INFO, pProvData->pWintrustData->pCert->cbStruct, dwFlags))) { HCERTSTORE hStore; if (pProvData->pWintrustData->pCert->dwFlags & WTCI_DONT_OPEN_STORES) { if (hStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)) { AddToStoreChain(hStore, &pProvData->chStores, &pProvData->pahStores); return(TRUE); } return(FALSE); } if (pProvData->pWintrustData->pCert->dwFlags & WTCI_OPEN_ONLY_ROOT) { if (hStore = StoreProviderGetStore(pProvData->hProv, WVT_STOREID_ROOT)) { AddToStoreChain(hStore, &pProvData->chStores, &pProvData->pahStores); return(TRUE); } return(FALSE); } } cs = 0; TrustOpenStores(pProvData->hProv, &cs, NULL, 0); if (cs > 0) { if (!(pas = new HCERTSTORE[cs])) { pProvData->dwError = ERROR_NOT_ENOUGH_MEMORY; pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] = TRUST_E_SYSTEM_ERROR; return(FALSE); } if (TrustOpenStores(pProvData->hProv, &cs, pas, 0)) { for (i = 0; i < cs; i++) { AddToStoreChain(pas[i], &pProvData->chStores, &pProvData->pahStores); } } else { cs = 0; } delete pas; } if (cs > 0) { return(TRUE); } return(FALSE); } BOOL WINAPI WTHelperGetAgencyInfo(PCCERT_CONTEXT pCert, DWORD *pcbAgencyInfo, SPC_SP_AGENCY_INFO *pAgencyInfo) { PCERT_EXTENSION pExt; PSPC_SP_AGENCY_INFO pInfo; DWORD cbInfo; if (!(pCert) || !(pcbAgencyInfo)) { SetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } *pcbAgencyInfo = 0; if (!(pExt = CertFindExtension(SPC_SP_AGENCY_INFO_OBJID, pCert->pCertInfo->cExtension, pCert->pCertInfo->rgExtension))) { return(FALSE); } CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, pcbAgencyInfo); if (*pcbAgencyInfo == 0) { return(FALSE); } if (!(pAgencyInfo)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return(FALSE); } if (!(CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT, pExt->Value.pbData, pExt->Value.cbData, 0, pAgencyInfo, pcbAgencyInfo))) { return(FALSE); } return(TRUE); } BOOL WINAPI WTHelperCheckCertUsage(PCCERT_CONTEXT pCertContext, LPCSTR pszRequestedUsageOID) { PCERT_ENHKEY_USAGE pUsage; DWORD cbUsage; int i; cbUsage = 0; CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage); if (cbUsage > 0) { if (!(pUsage = (PCERT_ENHKEY_USAGE)new BYTE[cbUsage])) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } if (!(CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &cbUsage))) { delete pUsage; return(FALSE); } // // the cert has enhanced key usage extensions, check if we find ours // if (!(_FindKeyUsage(pUsage, pszRequestedUsageOID))) { SetLastError(CERT_E_WRONG_USAGE); delete pUsage; return(FALSE); } delete pUsage; } // // OK... either we have NO EXTENSION or we found our OID in the list in the EXTENSION. // now, make sure if we have properties that it has been enabled. // cbUsage = 0; CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage); if (cbUsage > 0) { if (!(pUsage = (PCERT_ENHKEY_USAGE)new BYTE[cbUsage])) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } if (!(CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &cbUsage))) { delete pUsage; return(FALSE); } // // the cert has properties, first check if we're disabled // if (_FindKeyUsage(pUsage, szOID_YESNO_TRUST_ATTR)) { SetLastError(CERT_E_WRONG_USAGE); delete pUsage; return(FALSE); } if (!(_FindKeyUsage(pUsage, pszRequestedUsageOID))) { SetLastError(CERT_E_WRONG_USAGE); delete pUsage; return(FALSE); } delete pUsage; } return(TRUE); } BOOL _FindKeyUsage(PCERT_ENHKEY_USAGE pUsage, LPCSTR pszRequestedUsageOID) { int i; for (i = 0; i < (int)pUsage->cUsageIdentifier; i++) { if (strcmp(pUsage->rgpszUsageIdentifier[i], pszRequestedUsageOID) == 0) { return(TRUE); // OK found it! } } return(FALSE); } BOOL WINAPI WTHelperIsInRootStore(CRYPT_PROVIDER_DATA *pProvData, PCCERT_CONTEXT pCertContext) { if (pProvData->chStores < 1) { return(FALSE); } // // check the fast way first! // if (pCertContext->hCertStore == pProvData->pahStores[0]) { // // it's in the root store! // return(TRUE); } // // can't do it the fast way -- do it the slow way! // BYTE *pbHash; DWORD cbHash; CRYPT_HASH_BLOB sBlob; PCCERT_CONTEXT pWorkContext; cbHash = 0; if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, NULL, &cbHash))) { return(FALSE); } if (cbHash < 1) { return(FALSE); } if (!(pbHash = (BYTE *)WVTNew(cbHash))) { return(FALSE); } if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, pbHash, &cbHash))) { delete pbHash; return(FALSE); } sBlob.cbData = cbHash; sBlob.pbData = pbHash; pWorkContext = CertFindCertificateInStore(pProvData->pahStores[0], pProvData->dwEncoding, 0, CERT_FIND_SHA1_HASH, &sBlob, NULL); delete pbHash; if (pWorkContext) { CertFreeCertificateContext(pWorkContext); return(TRUE); } return(FALSE); } typedef struct _ENUM_OID_INFO_ARG { DWORD cOidInfo; PCCRYPT_OID_INFO *ppOidInfo; } ENUM_OID_INFO_ARG, *PENUM_OID_INFO_ARG; static BOOL WINAPI EnumOidInfoCallback( IN PCCRYPT_OID_INFO pOidInfo, IN void *pvArg ) { PENUM_OID_INFO_ARG pEnumOidInfoArg = (PENUM_OID_INFO_ARG) pvArg; PCCRYPT_OID_INFO *ppNewOidInfo; DWORD cOidInfo = pEnumOidInfoArg->cOidInfo; // DSIE: Bug 152473. for (DWORD i = 0; i < cOidInfo; i++) { if (0 == wcscmp(pOidInfo->pwszName, pEnumOidInfoArg->ppOidInfo[i]->pwszName)) { return TRUE; } } if (ppNewOidInfo = (PCCRYPT_OID_INFO *) PkiRealloc( pEnumOidInfoArg->ppOidInfo, (cOidInfo + 2) * sizeof(PCCRYPT_OID_INFO))) { ppNewOidInfo[cOidInfo] = pOidInfo; ppNewOidInfo[cOidInfo + 1] = NULL; pEnumOidInfoArg->cOidInfo = cOidInfo + 1; pEnumOidInfoArg->ppOidInfo = ppNewOidInfo; } return TRUE; } BOOL WINAPI WTHelperGetKnownUsages(DWORD fdwAction, PCCRYPT_OID_INFO **pppOidInfo) { if (!(pppOidInfo)) { SetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } if (fdwAction == WTH_FREE) { PkiFree(*pppOidInfo); *pppOidInfo = NULL; return(TRUE); } if (fdwAction == WTH_ALLOC) { ENUM_OID_INFO_ARG EnumOidInfoArg; memset(&EnumOidInfoArg, 0, sizeof(EnumOidInfoArg)); CryptEnumOIDInfo( CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, // dwFlags &EnumOidInfoArg, EnumOidInfoCallback ); return (NULL != (*pppOidInfo = EnumOidInfoArg.ppOidInfo)); } SetLastError(ERROR_INVALID_PARAMETER); *pppOidInfo = NULL; return(FALSE); } CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData) { return((CRYPT_PROVIDER_DATA *)hStateData); }