windows-nt/Source/XPSP1/NT/ds/security/base/lsa/server/efscert.cxx
2020-09-26 16:20:57 +08:00

1160 lines
30 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
efscert.cxx
Abstract:
EFS Certificate management code
Author:
Robert Reichel (RobertRe) July 4, 1997
Robert Gu (RobertG) Dec. 4, 1997
Environment:
Revision History:
--*/
#include <lsapch.hxx>
extern "C" {
#include <nt.h>
#include <ntdef.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <wincrypt.h>
#include <efsstruc.h>
#include "lsasrvp.h"
#include "debug.h"
#include "efssrv.hxx"
#include "userkey.h"
}
/////////////////////////////////////////////////////////////////////////////////////
// /
// /
// Helper Functions /
// /
// /
/////////////////////////////////////////////////////////////////////////////////////
PCCERT_CONTEXT
GetCertContextFromCertHash(
IN PBYTE pbHash,
IN DWORD cbHash,
IN DWORD dwFlags
)
/*++
Routine Description:
Finds the cert with the passed cert hash in the user's MY store
and returns a context pointer.
Arguments:
pbHash - Supplies a pointer to the hash to be matched.
cbHash - Supplies the length in bytes of the passed hash.
dwFlags - Supplies flags to CertOpenStore
Return Value:
Returns a pointer to a certificate context, or NULL.
The returned context must be freed via CertFreeCertificateContext()
--*/
{
CRYPT_HASH_BLOB hashBlob;
PCCERT_CONTEXT pCertContext = NULL;
//HCERTSTORE hStore = CertOpenSystemStoreW( NULL, L"MY");
HCERTSTORE hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY_W,
0, // dwEncodingType
0, // hCryptProv,
dwFlags,
L"My"
);
if (hStore != NULL) {
//
// Find our cert via the hash
//
hashBlob.cbData = cbHash;
hashBlob.pbData = pbHash;
pCertContext = CertFindCertificateInStore( hStore,
CRYPT_ASN_ENCODING,
0,
CERT_FIND_HASH,
&hashBlob,
NULL
);
CertCloseStore( hStore, 0 );
}
return( pCertContext );
}
LPWSTR
EfspGetCertDisplayInformation(
IN PCCERT_CONTEXT pCertContext
)
/*++
Routine Description:
Returns the display string from the passed certificate context.
Arguments:
pCertContext - Supplies a pointer to an open certificate context.
Return Value:
On success, pointer to display string. Caller must call
LsapFreeLsaHeap() to free.
NULL on failure.
--*/
{
DWORD rc;
LPWSTR UserDispName = NULL;
rc = EfsGetCertNameFromCertContext(
pCertContext,
&UserDispName
);
if (rc == ERROR_SUCCESS) {
return UserDispName;
} else {
SetLastError(rc);
return NULL;
}
}
PBYTE
GetCertHashFromCertContext(
IN PCCERT_CONTEXT pCertContext,
OUT PDWORD pcbHash
)
/*++
Routine Description:
Helper routine, takes a cert context and extracts the hash.
Arguments:
pCertContext - Supplies the cert context.
pcbHash - Returns the length in bytes of the returned hash.
Return Value:
Returns a pointer to a hash block allocated out of heap memory,
or NULL if either the attempt to get the hash failed or the attempt
to allocate memory failed.
Call GetLastError() for more details in case of failure.
--*/
{
PBYTE pbHash = NULL;
*pcbHash = 0;
if (CertGetCertificateContextProperty(
pCertContext,
CERT_HASH_PROP_ID,
NULL,
pcbHash
)) {
pbHash = (PBYTE)LsapAllocateLsaHeap( *pcbHash );
if (pbHash != NULL) {
if (!CertGetCertificateContextProperty(
pCertContext,
CERT_HASH_PROP_ID,
pbHash,
pcbHash
)) {
LsapFreeLsaHeap( pbHash );
pbHash = NULL;
*pcbHash = 0;
}
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
}
return( pbHash );
}
PCERT_PUBLIC_KEY_INFO
ExportPublicKeyInfo(
IN HCRYPTPROV hProv,
IN DWORD dwKeySpec,
IN DWORD dwCertEncodingType,
IN OUT DWORD *pcbInfo
)
{
PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
if ( CryptExportPublicKeyInfo(
hProv,
dwKeySpec,
dwCertEncodingType,
NULL,
pcbInfo)) {
pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) LsapAllocateLsaHeap(*pcbInfo);
if (pPubKeyInfo) {
if (!CryptExportPublicKeyInfo( hProv,
dwKeySpec,
dwCertEncodingType,
pPubKeyInfo,
pcbInfo)) {
LsapFreeLsaHeap( pPubKeyInfo );
pPubKeyInfo = NULL;
*pcbInfo = 0;
}
}
}
return ( pPubKeyInfo );
}
BOOL
EncodeAndAlloc(
DWORD dwEncodingType,
LPCSTR lpszStructType,
const void * pvStructInfo,
PBYTE * pbEncoded,
PDWORD pcbEncoded
)
{
BOOL b = FALSE;
if (CryptEncodeObject(
dwEncodingType,
lpszStructType,
pvStructInfo,
NULL,
pcbEncoded )) {
*pbEncoded = (PBYTE)LsapAllocateLsaHeap( *pcbEncoded );
if (*pbEncoded) {
if (CryptEncodeObject(
dwEncodingType,
lpszStructType,
pvStructInfo,
*pbEncoded,
pcbEncoded )) {
b = TRUE;
} else {
LsapFreeLsaHeap( *pbEncoded );
*pbEncoded = NULL;
}
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
}
return( b );
}
DWORD
EfsMakeCertNames(
IN PEFS_USER_INFO pEfsUserInfo,
OUT LPWSTR *DispInfo,
OUT LPWSTR *SubjectName,
OUT LPWSTR *UPNName
)
{
DWORD rc = ERROR_SUCCESS;
*DispInfo = NULL;
*UPNName = NULL;
if (pEfsUserInfo->bDomainAccount) {
//
// Domain Account
//
HRESULT hr;
HANDLE hDS = NULL;
DS_NAME_RESULT* UserName = NULL;
hr = DsBind(NULL, NULL, &hDS);
if (hr == NO_ERROR) {
rc = DsCrackNames(
hDS,
DS_NAME_NO_FLAGS,
DS_SID_OR_SID_HISTORY_NAME,
DS_USER_PRINCIPAL_NAME,
1,
&(pEfsUserInfo->lpUserSid),
&UserName
);
if (ERROR_SUCCESS == rc) {
if (UserName->rItems[0].status == DS_NAME_NO_ERROR) {
*UPNName = (LPWSTR) LsapAllocateLsaHeap((wcslen(UserName->rItems[0].pName) + 1) * sizeof (WCHAR));
*DispInfo = (LPWSTR) LsapAllocateLsaHeap(
(wcslen(UserName->rItems[0].pName) +
wcslen(pEfsUserInfo->lpUserName) +
3) * sizeof (WCHAR));
*SubjectName = (LPWSTR) LsapAllocateLsaHeap((wcslen(pEfsUserInfo->lpUserName)+4) * sizeof (WCHAR));
if (*UPNName && *DispInfo && *SubjectName ){
wcscpy(*UPNName, UserName->rItems[0].pName);
wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
wcscat(*DispInfo, L"(");
wcscat(*DispInfo, *UPNName);
wcscat(*DispInfo, L")");
wcscpy(*SubjectName, L"CN=");
wcscat(*SubjectName, pEfsUserInfo->lpUserName);
} else {
if (*UPNName) {
LsapFreeLsaHeap( *UPNName );
*UPNName = NULL;
}
if (*DispInfo) {
LsapFreeLsaHeap( *DispInfo );
*DispInfo = NULL;
}
if (*SubjectName) {
LsapFreeLsaHeap( *SubjectName );
*SubjectName = NULL;
}
rc = ERROR_NOT_ENOUGH_MEMORY;
}
}
if (UserName){
DsFreeNameResult(UserName);
UserName = NULL;
}
}
DsUnBindW( &hDS );
}
}
if (NULL == *UPNName) {
//
// If Local Account, let the UPNNmae be User@Computer. DispInfo be User(User@Computer).
// Else let the UPNName be User@Domain. DispInfo be User(User@Domain)
//
*UPNName = (LPWSTR) LsapAllocateLsaHeap(
(wcslen(pEfsUserInfo->lpUserName) +
wcslen(pEfsUserInfo->lpDomainName) +
2) * sizeof (WCHAR));
*DispInfo = (LPWSTR) LsapAllocateLsaHeap(
(wcslen(pEfsUserInfo->lpDomainName) +
wcslen(pEfsUserInfo->lpUserName) * 2 +
4) * sizeof (WCHAR));
*SubjectName = (LPWSTR) LsapAllocateLsaHeap(
(wcslen(pEfsUserInfo->lpUserName)+
4) * sizeof (WCHAR));
if (*UPNName && *DispInfo && *SubjectName){
wcscpy(*UPNName, pEfsUserInfo->lpUserName);
wcscat(*UPNName, L"@");
wcscat(*UPNName, pEfsUserInfo->lpDomainName);
wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
wcscat(*DispInfo, L"(");
wcscat(*DispInfo, *UPNName);
wcscat(*DispInfo, L")");
wcscpy(*SubjectName, L"CN=");
wcscat(*SubjectName, pEfsUserInfo->lpUserName);
} else {
if (*UPNName) {
LsapFreeLsaHeap( *UPNName );
*UPNName = NULL;
}
if (*DispInfo) {
LsapFreeLsaHeap( *DispInfo );
*DispInfo = NULL;
}
if (*SubjectName) {
LsapFreeLsaHeap( *SubjectName );
*SubjectName = NULL;
}
rc = ERROR_NOT_ENOUGH_MEMORY;
}
}
return rc;
}
#if 0
LPWSTR
MakeDNName(
BOOLEAN RecoveryKey,
IN PEFS_USER_INFO pEfsUserInfo
)
/*++
Routine Description:
Fabricates a display name for a locally built self-signed cert
Arguments:
RecoveryKey - Specifies if this is a recovery key or not.
Return Value:
Returns a string containing a display name, or NULL.
--*/
{
NTSTATUS Status;
LPWSTR DNName = NULL;
LPCWSTR DNNameTemplate = L"CN=%ws,L=EFS,OU=EFS File Encryption Certificate";
DWORD cbDNName = 0;
if (RecoveryKey) {
cbDNName = (wcslen( DNNameTemplate ) + 1) * sizeof( WCHAR ) + (wcslen( EfsComputerName ) + 1) * sizeof( WCHAR );
DNName = (LPWSTR)LsapAllocateLsaHeap( cbDNName );
if (DNName) {
swprintf( DNName, DNNameTemplate, EfsComputerName );
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
} else {
//
// This will be an overestimate, but only by a little.
//
cbDNName = (wcslen( DNNameTemplate ) * sizeof( WCHAR )) + (wcslen( pEfsUserInfo->lpUserName ) + 1) * sizeof( WCHAR );
DNName = (LPWSTR)LsapAllocateLsaHeap( cbDNName );
if (DNName != NULL) {
swprintf( DNName, DNNameTemplate, pEfsUserInfo->lpUserName );
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
}
return( DNName );
}
#endif
DWORD
EfsFindCertOid(
IN LPSTR pEfsCertOid,
IN PCCERT_CONTEXT pCertContext,
OUT BOOL *OidFound
)
/*++
Routine Description:
This routine takes a cert context and an Efs Oid. It will check if the cert has the Efs Oid or not.
Arguments:
pEfsCertOid - Efs Oid to be searched for.
pCertContext - The cert to be searched for.
OidFound - The result. TRUE if the oid is found.
Return Value:
Win32 Error code.
--*/
{
BOOL bRet;
PCERT_ENHKEY_USAGE pUsage;
DWORD pcbUsage = 0;
DWORD rc = ERROR_SUCCESS;
DWORD ii;
*OidFound = FALSE;
bRet = CertGetEnhancedKeyUsage(
pCertContext,
0,
NULL,
&pcbUsage
);
if (bRet) {
pUsage = (PCERT_ENHKEY_USAGE) LsapAllocateLsaHeap(pcbUsage);
if (pUsage) {
bRet = CertGetEnhancedKeyUsage(
pCertContext,
0,
pUsage,
&pcbUsage
);
if (bRet){
for (ii=0; ii<pUsage->cUsageIdentifier;ii++) {
if (!strcmp(pUsage->rgpszUsageIdentifier[ii], pEfsCertOid)){
//
// We found the OID
//
*OidFound = TRUE;
break;
}
}
} else {
rc = GetLastError();
}
LsapFreeLsaHeap(pUsage);
} else {
rc = ERROR_NOT_ENOUGH_MEMORY;
}
} else {
rc = GetLastError();
}
return rc;
}
DWORD
GetKeyInfoFromCertHash(
IN OUT PEFS_USER_INFO pEfsUserInfo,
IN PBYTE pbHash,
IN DWORD cbHash,
OUT HCRYPTKEY * hKey OPTIONAL,
OUT HCRYPTPROV * hProv OPTIONAL,
OUT LPWSTR * ContainerName OPTIONAL,
OUT LPWSTR * ProviderName OPTIONAL,
OUT LPWSTR * DisplayInformation OPTIONAL,
OUT PBOOLEAN pbIsValid OPTIONAL
)
/*++
Routine Description:
This routine takes a certificate hash and extracts from it information
about the key it represents. If the key information from this
cert does not exist in the current context, it will return an error.
Arguments:
pEfsUserInfo - User Information
pbHash - Takes a pointer to the certificate hash.
cbHash - The length in bytes of the certificate hash.
hKey - Returns the handle to the key corresponding to this
certificate. Must be passed of hProv is passed.
hProv - Returns the handle to the context corresponding to this
certificate. Must be passed of hKey is passed.
ContainerName - Returns a string with the name of the container of the
key in this certificate.
ProviderName - Returns a string with the name of the provider of the
key in this certificate.
DisplayInformation - Returns the display information for the certificate.
pbIsValid - If present, causes the cert to be validity checked and the
results returned.
Return Value:
ERROR_SUCCESS - The passed certificate is in the current user's MY
store and the key it represents is in his context.
!ERROR_SUCCESS - Either the certificate could not be found in the
user's MY store, or the key in the certificate could not be
instantiated.
--*/
{
PCCERT_CONTEXT pCertContext;
//
// Don't trust CryptoAPI to set last error properly,
// keep track of success and failure on our own.
//
BOOLEAN b = TRUE;
BOOLEAN CreateCache = FALSE;
BOOLEAN LocalCertValidated = FALSE;
BOOLEAN DataNotCached = TRUE;
DWORD rc = ERROR_SUCCESS;
DWORD rc2 = ERROR_SUCCESS;
HCRYPTKEY hLocalKey = NULL;
HCRYPTPROV hLocalProv = NULL;
LPWSTR LocalContainerName = NULL;
LPWSTR LocalProviderName = NULL;
LPWSTR LocalDisplayInformation = NULL;
//
// Output parameters
//
if (ARGUMENT_PRESENT(ContainerName)) {
*ContainerName = NULL;
}
if (ARGUMENT_PRESENT(ProviderName)) {
*ProviderName = NULL;
}
if (ARGUMENT_PRESENT(DisplayInformation)) {
*DisplayInformation = NULL;
}
if (ARGUMENT_PRESENT(hProv)) {
*hProv = NULL;
}
if (ARGUMENT_PRESENT(hKey)) {
*hKey = NULL;
}
if (ARGUMENT_PRESENT( pbIsValid )){
*pbIsValid = FALSE;
}
//
// Check if a cache node is available
//
if (!pEfsUserInfo->UserCacheStop) {
if (pEfsUserInfo->pUserCache) {
//
// The user has a cache, check if the Hash matches
//
if ( pEfsUserInfo->pUserCache->cbHash == cbHash ) {
if(RtlEqualMemory( pEfsUserInfo->pUserCache->pbHash, pbHash, cbHash)){
//
// Cache is valid. Use the cache
//
if (ARGUMENT_PRESENT( pbIsValid )){
*pbIsValid = (pEfsUserInfo->pUserCache->CertValidated == CERT_VALIDATED);
}
return ERROR_SUCCESS;
}
//
// User might use an old key, do not put in the cache.
//
}
} else {
CreateCache = TRUE;
}
}
//
// Find our cert via the hash
//
pCertContext = GetCertContextFromCertHash(
pbHash,
cbHash,
CERT_SYSTEM_STORE_CURRENT_USER
);
if (pCertContext != NULL) {
PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
if (pCryptKeyProvInfo != NULL) {
//
// Copy out the container name and provider name if requested.
//
if (pCryptKeyProvInfo->pwszContainerName) {
LocalContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
if (LocalContainerName != NULL) {
wcscpy( LocalContainerName, pCryptKeyProvInfo->pwszContainerName );
} else {
rc = ERROR_NOT_ENOUGH_MEMORY;
b = FALSE;
}
}
if (b && pCryptKeyProvInfo->pwszProvName) {
LocalProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
if (LocalProviderName != NULL) {
wcscpy( LocalProviderName, pCryptKeyProvInfo->pwszProvName );
}
else {
rc = ERROR_NOT_ENOUGH_MEMORY;
b = FALSE;
}
}
if (!(LocalDisplayInformation = EfspGetCertDisplayInformation( pCertContext ))) {
//
// At least for now, we do not accept Cert without display name
//
rc = GetLastError();
b = FALSE;
}
//
// Get the key information
//
if (b) {
if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
if (!CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
rc = GetLastError();
b = FALSE;
}
} else {
rc = GetLastError();
b = FALSE;
}
}
if (b) {
if ( ARGUMENT_PRESENT( pbIsValid ) || CreateCache ) {
//
// Do cert validity checking. Check time and usage.
//
if ( CertVerifyTimeValidity(
NULL,
pCertContext->pCertInfo
)){
rc2 = CERT_E_EXPIRED;
//b = FALSE;
} else {
//
// Test the cert usage here.
// CERT_E_WRONG_USAGE
//
BOOL OidFound;
rc = EfsFindCertOid(
szOID_KP_EFS,
pCertContext,
&OidFound
);
if (ERROR_SUCCESS == rc) {
if (OidFound) {
LocalCertValidated = TRUE;
}
} else {
b = FALSE;
}
}
if (ARGUMENT_PRESENT( pbIsValid )) {
//
// We need the validation info.
//
*pbIsValid = LocalCertValidated;
}
}
if ( CreateCache ) {
DWORD certFlag;
//
// Todetermine if we can put the data in cache.
//
if (CurrentHashOK(pEfsUserInfo, pbHash, cbHash, &certFlag)) {
//
// This pbHash is in the user's key or has been put in. Let's create the cache node.
//
PUSER_CACHE pCacheNode;
PBYTE pbWkHash;
DWORD ImpersonationError = 0;
if (certFlag != CERTINLMTRUSTEDSTORE) {
DWORD sevRc;
//
// The cert is not in the LM Trusted store. Upgrade system from Win2K, or Beta 1 Whistler.
//
if (ERROR_SUCCESS == (sevRc = EfsAddCertToTrustStoreStore(pCertContext, &ImpersonationError))) {
EfsMarkCertAddedToStore(pEfsUserInfo);
} else {
if (ImpersonationError) {
//
// Got in trouble. We could not impersonate back.
//
ASSERT(FALSE);
rc = sevRc;
b = FALSE;
}
}
}
if (!ImpersonationError) {
pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
pbWkHash = (PBYTE) LsapAllocateLsaHeap(cbHash);
if (pCacheNode && pbWkHash) {
memset( pCacheNode, 0, sizeof( USER_CACHE ));
RtlCopyMemory(pbWkHash, pbHash, cbHash);
if (NT_SUCCESS( NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
if (EfspInitUserCacheNode(
pCacheNode,
pbWkHash,
cbHash,
LocalContainerName,
LocalProviderName,
LocalDisplayInformation,
pCertContext,
hLocalKey,
hLocalProv,
&(pEfsUserInfo->AuthId),
LocalCertValidated? CERT_VALIDATED:CERT_VALIDATION_FAILED
)){
//
// Cache node created and ready for use. Do not delete or close the info
// we just got.
//
LocalContainerName = NULL;
LocalProviderName = NULL;
LocalDisplayInformation = NULL;
hLocalKey = NULL;
hLocalProv = NULL;
pEfsUserInfo->pUserCache = pCacheNode;
pCertContext = NULL;
DataNotCached = FALSE;
rc = ERROR_SUCCESS;
b = TRUE; // We can have a non-validated cache node for the use of open file
} else {
LsapFreeLsaHeap(pCacheNode);
LsapFreeLsaHeap(pbWkHash);
pbWkHash = NULL;
pCacheNode = NULL;
}
} else {
LsapFreeLsaHeap(pCacheNode);
LsapFreeLsaHeap(pbWkHash);
pbWkHash = NULL;
pCacheNode = NULL;
}
} else {
if (pCacheNode) {
LsapFreeLsaHeap(pCacheNode);
pCacheNode = NULL;
}
if (pbWkHash) {
LsapFreeLsaHeap(pbWkHash);
pbWkHash = NULL;
}
}
}
}
}
if (DataNotCached && b) {
//
// We need to returned the data to outside
//
if (ARGUMENT_PRESENT(ContainerName)) {
*ContainerName = LocalContainerName;
LocalContainerName = NULL;
}
if (ARGUMENT_PRESENT(ProviderName)) {
*ProviderName = LocalProviderName;
LocalProviderName = NULL;
}
if (ARGUMENT_PRESENT(DisplayInformation)) {
*DisplayInformation = LocalDisplayInformation;
LocalDisplayInformation = NULL;
}
if (ARGUMENT_PRESENT(hKey)) {
*hKey = hLocalKey;
hLocalKey = NULL;
}
if (ARGUMENT_PRESENT(hProv)) {
*hProv = hLocalProv;
hLocalProv = NULL;
}
}
}
LsapFreeLsaHeap( pCryptKeyProvInfo );
} else {
rc = GetLastError();
b = FALSE;
}
if (pCertContext) {
CertFreeCertificateContext( pCertContext );
}
} else {
rc = GetLastError();
b = FALSE;
}
if (!b) {
ASSERT( rc != ERROR_SUCCESS );
//
// Something failed, cleanup the stuff we were going to return
//
if ( LocalContainerName) {
LsapFreeLsaHeap( LocalContainerName );
}
if (LocalProviderName) {
LsapFreeLsaHeap( LocalProviderName );
}
if (LocalDisplayInformation) {
LsapFreeLsaHeap( LocalDisplayInformation );
}
if (hLocalKey) {
CryptDestroyKey( hLocalKey );
}
if (hLocalProv) {
CryptReleaseContext( hLocalProv, 0 );
}
}
if (ARGUMENT_PRESENT( pbIsValid ) && !LocalCertValidated ) {
if (rc == ERROR_SUCCESS) {
rc = rc2;
}
}
return( rc );
}
PCRYPT_KEY_PROV_INFO
GetKeyProvInfo(
PCCERT_CONTEXT pCertContext
)
/*++
Routine Description:
This routine will extract the Key Provider Information from
the passed certificate context.
Arguments:
pCertContext - Supplies a pointer to a certificate context.
Return Value:
Returns a pointer to a PCRYPT_KEY_PROV_INFO structure on success,
otherwise returns NULL, which usually means that the certificate
did not have the context property we were looking for (meaning
that it probably isn't an EFS certificate).
--*/
{
DWORD cbData = 0;
BOOL b;
PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
b = CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbData
);
if (b) {
pCryptKeyProvInfo = (PCRYPT_KEY_PROV_INFO)LsapAllocateLsaHeap( cbData );
if (pCryptKeyProvInfo != NULL) {
b = CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
pCryptKeyProvInfo,
&cbData
);
if (!b) {
LsapFreeLsaHeap( pCryptKeyProvInfo );
pCryptKeyProvInfo = NULL;
}
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
}
return ( pCryptKeyProvInfo );
}