You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
642 lines
15 KiB
642 lines
15 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: cspenum.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <tchar.h>
|
|
#include <assert.h>
|
|
|
|
#include "initcert.h"
|
|
#include "cscsp.h"
|
|
#include "cspenum.h"
|
|
#include "certmsg.h"
|
|
|
|
|
|
#define __dwFILE__ __dwFILE_OCMSETUP_CSPENUM_CPP__
|
|
|
|
|
|
WCHAR const g_wszRegKeyCSP[] = wszREGKEYCSP;
|
|
WCHAR const g_wszRegKeyEncryptionCSP[] = wszREGKEYENCRYPTIONCSP;
|
|
WCHAR const g_wszRegProviderType[] = wszREGPROVIDERTYPE;
|
|
WCHAR const g_wszRegProvider[] = wszREGPROVIDER;
|
|
WCHAR const g_wszRegHashAlgorithm[] = wszHASHALGORITHM;
|
|
TCHAR const g_wszRegEncryptionAlgorithm[] = wszENCRYPTIONALGORITHM;
|
|
WCHAR const g_wszRegMachineKeyset[] = wszMACHINEKEYSET;
|
|
WCHAR const g_wszRegKeySize[] = wszREGKEYSIZE;
|
|
|
|
|
|
// Hash Enumeration code begins
|
|
// move point to link list top
|
|
CSP_HASH*
|
|
topHashInfoList(CSP_HASH *pHashInfoList)
|
|
{
|
|
while (pHashInfoList->last)
|
|
{
|
|
pHashInfoList = pHashInfoList->last;
|
|
}
|
|
return pHashInfoList;
|
|
}
|
|
|
|
// move point to link list end
|
|
CSP_HASH*
|
|
endHashInfoList(CSP_HASH *pHashInfoList)
|
|
{
|
|
while (pHashInfoList->next)
|
|
{
|
|
pHashInfoList = pHashInfoList->next;
|
|
}
|
|
return pHashInfoList;
|
|
}
|
|
|
|
// add one more CSP_INFO
|
|
void
|
|
addHashInfo(CSP_HASH *pHashInfoList, CSP_HASH *pHashInfo)
|
|
{
|
|
// add
|
|
pHashInfoList->next = pHashInfo;
|
|
pHashInfo->last = pHashInfoList;
|
|
}
|
|
|
|
// add one more CSP_INFO to end
|
|
void
|
|
addHashInfoToEnd(CSP_HASH *pHashInfoList, CSP_HASH *pHashInfo)
|
|
{
|
|
// go to end
|
|
pHashInfoList = endHashInfoList(pHashInfoList);
|
|
// add
|
|
pHashInfoList->next = pHashInfo;
|
|
pHashInfo->last = pHashInfoList;
|
|
}
|
|
|
|
CSP_HASH *
|
|
newHashInfo(
|
|
ALG_ID idAlg,
|
|
CHAR *pszName)
|
|
{
|
|
CSP_HASH *pHashInfo = NULL;
|
|
|
|
if (NULL != pszName)
|
|
{
|
|
pHashInfo = (CSP_HASH*)LocalAlloc(LMEM_FIXED, sizeof(CSP_HASH));
|
|
if (NULL == pHashInfo)
|
|
{
|
|
SetLastError((DWORD) E_OUTOFMEMORY);
|
|
}
|
|
else
|
|
{
|
|
pHashInfo->pwszName = (WCHAR*)LocalAlloc(LMEM_FIXED,
|
|
(strlen(pszName)+1)*sizeof(WCHAR));
|
|
if (NULL == pHashInfo->pwszName)
|
|
{
|
|
LocalFree(pHashInfo);
|
|
SetLastError((DWORD) E_OUTOFMEMORY);
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
// create a new one
|
|
pHashInfo->idAlg = idAlg;
|
|
mbstowcs(pHashInfo->pwszName, pszName, strlen(pszName)+1);
|
|
pHashInfo->last = NULL;
|
|
pHashInfo->next = NULL;
|
|
}
|
|
}
|
|
}
|
|
return pHashInfo;
|
|
}
|
|
|
|
|
|
void
|
|
freeHashInfo(CSP_HASH *pHashInfo)
|
|
{
|
|
if (pHashInfo)
|
|
{
|
|
if (pHashInfo->pwszName)
|
|
{
|
|
LocalFree(pHashInfo->pwszName);
|
|
}
|
|
LocalFree(pHashInfo);
|
|
}
|
|
}
|
|
|
|
void
|
|
freeHashInfoList(
|
|
CSP_HASH *pHashInfoList)
|
|
{
|
|
CSP_HASH *pNext;
|
|
|
|
if (pHashInfoList)
|
|
{
|
|
// go top
|
|
pHashInfoList = topHashInfoList(pHashInfoList);
|
|
do
|
|
{
|
|
pNext = pHashInfoList->next;
|
|
freeHashInfo(pHashInfoList);
|
|
pHashInfoList = pNext;
|
|
} while (pHashInfoList);
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetHashList(
|
|
DWORD dwProvType,
|
|
WCHAR *pwszProvName,
|
|
CSP_HASH **pHashInfoList)
|
|
{
|
|
HRESULT hr;
|
|
HCRYPTPROV hProv = NULL;
|
|
CHAR *pszName = NULL;
|
|
DWORD i;
|
|
ALG_ID *pidAlg;
|
|
DWORD cbData;
|
|
BYTE *pbData;
|
|
DWORD dwFlags;
|
|
|
|
BOOL fSupportSigningFlag = FALSE; // none-ms csp likely
|
|
PROV_ENUMALGS_EX EnumAlgsEx;
|
|
PROV_ENUMALGS EnumAlgs;
|
|
|
|
CSP_HASH *pHashInfo = NULL;
|
|
CSP_HASH *pHashInfoNode;
|
|
|
|
if (NULL == pwszProvName)
|
|
{
|
|
// the reason why I check this because
|
|
// NULL is a valid input for CryptAcquireContext()
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "no provider name");
|
|
}
|
|
if (!myCertSrvCryptAcquireContext(
|
|
&hProv,
|
|
NULL,
|
|
pwszProvName,
|
|
dwProvType,
|
|
CRYPT_VERIFYCONTEXT,
|
|
FALSE))
|
|
{
|
|
hr = myHLastError();
|
|
if (NULL != hProv)
|
|
{
|
|
hProv = NULL;
|
|
_PrintError(hr, "CSP returns a non-null handle");
|
|
}
|
|
_JumpErrorStr(hr, error, "myCertSrvCryptAcquireContext", pwszProvName);
|
|
}
|
|
|
|
// check if csp support signing flag
|
|
if (CryptGetProvParam(hProv, PP_ENUMEX_SIGNING_PROT, NULL, &cbData, 0))
|
|
{
|
|
fSupportSigningFlag = TRUE;
|
|
}
|
|
|
|
dwFlags = CRYPT_FIRST;
|
|
for (i = 0; ; dwFlags = 0, i++)
|
|
{
|
|
DWORD const *pdwProtocols;
|
|
|
|
if (fSupportSigningFlag)
|
|
{
|
|
pdwProtocols = &EnumAlgsEx.dwProtocols;
|
|
pidAlg = &EnumAlgsEx.aiAlgid;
|
|
cbData = sizeof(EnumAlgsEx);
|
|
pbData = (BYTE *) &EnumAlgsEx;
|
|
}
|
|
else
|
|
{
|
|
pdwProtocols = NULL;
|
|
pidAlg = &EnumAlgs.aiAlgid;
|
|
cbData = sizeof(EnumAlgs);
|
|
pbData = (BYTE *) &EnumAlgs;
|
|
}
|
|
ZeroMemory(pbData, cbData);
|
|
if (!CryptGetProvParam(
|
|
hProv,
|
|
fSupportSigningFlag?
|
|
PP_ENUMALGS_EX : PP_ENUMALGS,
|
|
pbData,
|
|
&cbData,
|
|
dwFlags))
|
|
{
|
|
hr = myHLastError();
|
|
if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
|
|
{
|
|
// out of for loop
|
|
break;
|
|
}
|
|
_JumpError(hr, error, "CryptGetProvParam");
|
|
}
|
|
if (ALG_CLASS_HASH == GET_ALG_CLASS(*pidAlg))
|
|
{
|
|
if (fSupportSigningFlag)
|
|
{
|
|
if (0 == (CRYPT_FLAG_SIGNING & *pdwProtocols))
|
|
{
|
|
// this means this hash doesn't support signing
|
|
continue; // skip
|
|
}
|
|
pszName = EnumAlgsEx.szLongName;
|
|
pszName = EnumAlgsEx.szName;
|
|
}
|
|
else
|
|
{
|
|
pszName = EnumAlgs.szName;
|
|
}
|
|
|
|
pHashInfoNode = newHashInfo(*pidAlg, pszName); // 2nd parm: name
|
|
if (NULL == pHashInfoNode)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "newHashInfo");
|
|
}
|
|
|
|
if (NULL == pHashInfo)
|
|
{
|
|
pHashInfo = pHashInfoNode;
|
|
}
|
|
else
|
|
{
|
|
// add to temp list
|
|
addHashInfoToEnd(pHashInfo, pHashInfoNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
// pass it back to caller
|
|
*pHashInfoList = pHashInfo;
|
|
pHashInfo = NULL;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pHashInfo)
|
|
{
|
|
freeHashInfoList(pHashInfo);
|
|
}
|
|
if (NULL != hProv)
|
|
{
|
|
CryptReleaseContext(hProv, 0);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// CSP Enumeration code begins
|
|
// move point to link list top
|
|
CSP_INFO*
|
|
topCSPInfoList(CSP_INFO *pCSPInfoList)
|
|
{
|
|
while (pCSPInfoList->last)
|
|
{
|
|
pCSPInfoList = pCSPInfoList->last;
|
|
}
|
|
return pCSPInfoList;
|
|
}
|
|
|
|
|
|
// move point to link list end
|
|
CSP_INFO*
|
|
endCSPInfoList(CSP_INFO *pCSPInfoList)
|
|
{
|
|
while (pCSPInfoList->next)
|
|
{
|
|
pCSPInfoList = pCSPInfoList->next;
|
|
}
|
|
return pCSPInfoList;
|
|
}
|
|
|
|
// find first matched csp info from the list
|
|
CSP_INFO*
|
|
findCSPInfoFromList(
|
|
CSP_INFO *pCSPInfoList,
|
|
WCHAR const *pwszProvName,
|
|
const DWORD dwProvType)
|
|
{
|
|
while (NULL != pCSPInfoList)
|
|
{
|
|
if (0 == mylstrcmpiL(pCSPInfoList->pwszProvName, pwszProvName) &&
|
|
pCSPInfoList->dwProvType == dwProvType)
|
|
{
|
|
// found it
|
|
break;
|
|
}
|
|
pCSPInfoList = pCSPInfoList->next;
|
|
}
|
|
return pCSPInfoList;
|
|
}
|
|
|
|
// add one more CSP_INFO
|
|
void
|
|
addCSPInfo(CSP_INFO *pCSPInfoList, CSP_INFO *pCSPInfo)
|
|
{
|
|
// add
|
|
pCSPInfoList->next = pCSPInfo;
|
|
pCSPInfo->last = pCSPInfoList;
|
|
}
|
|
|
|
|
|
// add one more CSP_INFO to end
|
|
void
|
|
addCSPInfoToEnd(CSP_INFO *pCSPInfoList, CSP_INFO *pCSPInfo)
|
|
{
|
|
// go to end
|
|
pCSPInfoList = endCSPInfoList(pCSPInfoList);
|
|
// add
|
|
pCSPInfoList->next = pCSPInfo;
|
|
pCSPInfo->last = pCSPInfoList;
|
|
}
|
|
|
|
|
|
void
|
|
freeCSPInfo(CSP_INFO *pCSPInfo)
|
|
{
|
|
if (pCSPInfo)
|
|
{
|
|
if (pCSPInfo->pwszProvName)
|
|
{
|
|
LocalFree(pCSPInfo->pwszProvName);
|
|
}
|
|
if (pCSPInfo->pHashList)
|
|
{
|
|
freeHashInfoList(pCSPInfo->pHashList);
|
|
}
|
|
LocalFree(pCSPInfo);
|
|
}
|
|
}
|
|
|
|
|
|
CSP_INFO *
|
|
newCSPInfo(
|
|
DWORD dwProvType,
|
|
WCHAR *pwszProvName)
|
|
{
|
|
CSP_INFO *pCSPInfo = NULL;
|
|
CSP_HASH *pHashList = NULL;
|
|
|
|
if (NULL != pwszProvName)
|
|
{
|
|
// get all hash algorithms under this csp
|
|
if (S_OK != GetHashList(dwProvType, pwszProvName, &pHashList))
|
|
{
|
|
// certsrv needs csp with hash support
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
pCSPInfo = (CSP_INFO*)LocalAlloc(LMEM_FIXED, sizeof(CSP_INFO));
|
|
if (NULL == pCSPInfo)
|
|
{
|
|
freeHashInfoList(pHashList);
|
|
SetLastError((DWORD) E_OUTOFMEMORY);
|
|
}
|
|
else
|
|
{
|
|
pCSPInfo->pwszProvName = (WCHAR*)LocalAlloc(LMEM_FIXED,
|
|
(wcslen(pwszProvName) + 1) * sizeof(WCHAR));
|
|
if (NULL == pCSPInfo->pwszProvName)
|
|
{
|
|
freeHashInfoList(pHashList);
|
|
LocalFree(pCSPInfo);
|
|
pCSPInfo = NULL;
|
|
SetLastError((DWORD) E_OUTOFMEMORY);
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
// create a new one
|
|
pCSPInfo->dwProvType = dwProvType;
|
|
pCSPInfo->fMachineKeyset = TRUE; // assume???
|
|
wcscpy(pCSPInfo->pwszProvName, pwszProvName);
|
|
pCSPInfo->pHashList = pHashList;
|
|
pCSPInfo->last = NULL;
|
|
pCSPInfo->next = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
done:
|
|
return pCSPInfo;
|
|
}
|
|
|
|
|
|
void
|
|
FreeCSPInfoList(CSP_INFO *pCSPInfoList)
|
|
{
|
|
CSP_INFO *pNext;
|
|
|
|
if (pCSPInfoList)
|
|
{
|
|
// go top
|
|
pCSPInfoList = topCSPInfoList(pCSPInfoList);
|
|
do
|
|
{
|
|
pNext = pCSPInfoList->next;
|
|
freeCSPInfo(pCSPInfoList);
|
|
pCSPInfoList = pNext;
|
|
} while (pCSPInfoList);
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetCSPInfoList(CSP_INFO **pCSPInfoList)
|
|
{
|
|
HRESULT hr;
|
|
long i;
|
|
DWORD dwProvType;
|
|
WCHAR *pwszProvName = NULL;
|
|
CSP_INFO *pCSPInfo = NULL;
|
|
CSP_INFO *pCSPInfoNode;
|
|
|
|
for (i = 0; ; i++)
|
|
{
|
|
// get provider name
|
|
|
|
hr = myEnumProviders(
|
|
i,
|
|
NULL,
|
|
0,
|
|
&dwProvType,
|
|
&pwszProvName);
|
|
if (S_OK != hr)
|
|
{
|
|
hr = myHLastError();
|
|
CSASSERT(
|
|
HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
|
|
NTE_FAIL == hr);
|
|
if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
|
|
NTE_FAIL == hr)
|
|
{
|
|
// no more providers under type, terminate loop
|
|
break;
|
|
}
|
|
|
|
// invalid CSP entry, skip it
|
|
|
|
continue;
|
|
}
|
|
|
|
if (PROV_RSA_FULL == dwProvType ||
|
|
PROV_RSA_SIG == dwProvType ||
|
|
PROV_DSS == dwProvType ||
|
|
PROV_MS_EXCHANGE == dwProvType ||
|
|
PROV_SSL == dwProvType)
|
|
{
|
|
if (NULL == pCSPInfo)
|
|
{
|
|
// first csp info
|
|
pCSPInfo = newCSPInfo(dwProvType, pwszProvName);
|
|
}
|
|
else
|
|
{
|
|
// create a node
|
|
pCSPInfoNode = newCSPInfo(dwProvType, pwszProvName);
|
|
if (NULL != pCSPInfoNode)
|
|
{
|
|
// add to list
|
|
addCSPInfoToEnd(pCSPInfo, pCSPInfoNode);
|
|
}
|
|
}
|
|
}
|
|
LocalFree(pwszProvName);
|
|
pwszProvName = NULL;
|
|
}
|
|
|
|
// pass back to caller
|
|
|
|
*pCSPInfoList = pCSPInfo;
|
|
hr = S_OK;
|
|
|
|
//error:
|
|
if (NULL != pwszProvName)
|
|
{
|
|
LocalFree(pwszProvName);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SetCertSrvCSP(
|
|
IN BOOL fEncryptionCSP,
|
|
IN WCHAR const *pwszCAName,
|
|
IN DWORD dwProvType,
|
|
IN WCHAR const *pwszProvName,
|
|
IN ALG_ID idAlg,
|
|
IN BOOL fMachineKeyset,
|
|
IN DWORD dwKeySize)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hCertSrvKey = NULL;
|
|
HKEY hCertSrvCAKey = NULL;
|
|
HKEY hCertSrvCSPKey = NULL;
|
|
DWORD dwDisposition;
|
|
|
|
hr = RegCreateKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
wszREGKEYCONFIGPATH,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hCertSrvKey,
|
|
&dwDisposition);
|
|
_JumpIfErrorStr(hr, error, "RegCreateKeyEx", wszREGKEYCONFIGPATH);
|
|
|
|
hr = RegCreateKeyEx(
|
|
hCertSrvKey,
|
|
pwszCAName,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hCertSrvCAKey,
|
|
&dwDisposition);
|
|
_JumpIfErrorStr(hr, error, "RegCreateKeyEx", pwszCAName);
|
|
|
|
hr = RegCreateKeyEx(
|
|
hCertSrvCAKey,
|
|
fEncryptionCSP? g_wszRegKeyEncryptionCSP : g_wszRegKeyCSP,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hCertSrvCSPKey,
|
|
&dwDisposition);
|
|
_JumpIfErrorStr(hr, error, "RegCreateKeyEx", g_wszRegKeyCSP);
|
|
|
|
hr = RegSetValueEx(
|
|
hCertSrvCSPKey,
|
|
g_wszRegProviderType,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE const *) &dwProvType,
|
|
sizeof(dwProvType));
|
|
_JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegProviderType);
|
|
|
|
hr = RegSetValueEx(
|
|
hCertSrvCSPKey,
|
|
g_wszRegProvider,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE const *) pwszProvName,
|
|
wcslen(pwszProvName) * sizeof(WCHAR));
|
|
_JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegProvider);
|
|
|
|
hr = RegSetValueEx(
|
|
hCertSrvCSPKey,
|
|
fEncryptionCSP?
|
|
g_wszRegEncryptionAlgorithm :
|
|
g_wszRegHashAlgorithm,
|
|
0,
|
|
REG_DWORD, // questionable???
|
|
(BYTE const *) &idAlg,
|
|
sizeof(idAlg));
|
|
_JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegHashAlgorithm);
|
|
|
|
hr = RegSetValueEx(
|
|
hCertSrvCSPKey,
|
|
g_wszRegMachineKeyset,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE const *) &fMachineKeyset,
|
|
sizeof(fMachineKeyset));
|
|
_JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegMachineKeyset);
|
|
|
|
if (0 != dwKeySize)
|
|
{
|
|
hr = RegSetValueEx(
|
|
hCertSrvCSPKey,
|
|
g_wszRegKeySize,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE const *) &dwKeySize,
|
|
sizeof(dwKeySize));
|
|
_JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegKeySize);
|
|
}
|
|
|
|
error:
|
|
if (NULL != hCertSrvCSPKey)
|
|
{
|
|
RegCloseKey(hCertSrvCSPKey);
|
|
}
|
|
if (NULL != hCertSrvCAKey)
|
|
{
|
|
RegCloseKey(hCertSrvCAKey);
|
|
}
|
|
if (NULL != hCertSrvKey)
|
|
{
|
|
RegCloseKey(hCertSrvKey);
|
|
}
|
|
return(myHError(hr));
|
|
}
|