#include ".\opencsp_keyset.h"
#include ".\opencsp_provider.h"
#include ".\opencsp_alg.h"
#include ".\opencsp_hash.h"
#include ".\opencsp_key.h"
#include ".\opencsp_mutex.h"
#include ".\opencsp_cardaccess.h"
extern SHARED_KEYSET_INFO_LIST g_sharedKeysetInfo;
KEYSETNAME_KYESET_MAP OPENCSP_Keyset::_keysetMap; //键值对
//-------------------------------------------------------------------------------------------
OPENCSP_Keyset::OPENCSP_Keyset(const KEYSET_NAME& kn, DWORD flags)
: _keysetName(kn), _flags(flags), _verifyContext(FALSE), _silent(FALSE), _hard(FALSE), _default(FALSE)
{
if (!_flags)
{
_hard = TRUE; // use or create default keyset
}
else
{
if (_flags & CRYPT_SILENT) _silent = TRUE;
if (_flags & CRYPT_VERIFYCONTEXT)
{
_verifyContext = TRUE;
}
else
{
_hard = TRUE;
}
}
_keysetMap.insert(make_pair(_keysetName, this)); //插入密钥容器名
}
OPENCSP_Keyset::~OPENCSP_Keyset(void)
{
HANDLE_PROVIDER_MAP::iterator itr = _provMap.begin();
for (; itr != _provMap.end(); itr++)
{
delete itr->second;
}
_provMap.clear();
_keysetMap.erase(_keysetName);
}
OPENCSP_Keyset* OPENCSP_Keyset::findKeyset(const KEYSET_NAME& kn) //遍历密钥容器,寻找指定密钥容器
{
KEYSETNAME_KYESET_MAP::const_iterator itr = _keysetMap.find(kn);
if (itr != _keysetMap.end())
return itr->second;
else
return NULL;
}
OPENCSP_Provider* OPENCSP_Keyset::findProvider(HCRYPTPROV hProv)
{
KEYSETNAME_KYESET_MAP::iterator itr = _keysetMap.begin();
for (; itr != _keysetMap.end(); itr++)
{
OPENCSP_Keyset *keyset = (itr->second);
HANDLE_PROVIDER_MAP::iterator itrP = keyset->_provMap.find(hProv);
if (itrP != keyset->_provMap.end()) return ((*itrP).second);
}
return NULL;
}
HCRYPTPROV OPENCSP_Keyset::createProvider(OPENCSP_CardAccess* pCard)
{
OPENCSP_Provider* pProv = new OPENCSP_Provider(pCard);
HCRYPTPROV hProv = pProv->getProvHandle();
_provMap.insert(make_pair(hProv, pProv));
return hProv;
}
void OPENCSP_Keyset::deleteProvider(HCRYPTPROV hProv)
{
OPENCSP_Provider* pProv = findProvider(hProv);
if (pProv)
{
delete pProv;
_provMap.erase(hProv);
}
}
void OPENCSP_Keyset::clearKeysetInstance(const KEYSET_NAME& kn) //清除密钥容器实例
{
KEYSETNAME_KYESET_MAP::iterator itr = _keysetMap.find(kn);
if (itr != _keysetMap.end())
{
delete itr->second;
_keysetMap.erase(kn);
}
}
/*
[Eric Merlin says]
CRYPT_VERIFYCONTEXT for SC CSPs means no access to private keys.
With a NULL container, you're not targetting a particular card so it should
only be used to query CSP capabilities.
Otherwise behavior is not really defined/predictable (ranging from acting on
all cards present to first card found).
*/
DWORD OPENCSP_Keyset::getKeyset(const READER_NAME& rn, const KEYSET_NAME& kn, DWORD flags, HCRYPTPROV& hProv)
{
/*
In CSP, keyset name is used to index a keyset object.
So keyset name should have value!
*/
DWORD dwRet = S_OK;
KEYSET_NAME keysetName = kn;
READER_NAME reader = rn;
OPENCSP_Keyset* keyset = NULL;
OPENCSP_CardAccess* card = NULL;
BOOL bSilent = FALSE;
DWORD dwFlags = flags;
if (dwFlags & CRYPT_SILENT)
{
bSilent = TRUE;
dwFlags ^= CRYPT_SILENT;
}
switch(dwFlags)
{
case 0:
{
if (reader.size() == 0)
{
/* reader name is not specified */
card = OPENCSP_CardAccess::getCardInstance(NULL);
if (!card)
{
if (bSilent)
return OPENCSP_CardAccess::getResultCode();
dwRet = OPENCSP_CardAccess::showSCardUIDlg(reader);
if (dwRet != S_OK) return dwRet;
// reconnect to get card access instance
card = OPENCSP_CardAccess::getCardInstance(reader);
if (!card) return OPENCSP_CardAccess::getResultCode();
}
}
else
{
card = OPENCSP_CardAccess::getCardInstance(reader);
if (!card) return OPENCSP_CardAccess::getResultCode();
}
reader = card->getReaderName();
// read keyset id from the card
CARDKEYSETSTATE cks[CARD_KEYSET_MAX] = {{0}};
DWORD dwKeysetId = CARD_KEYSET_MAX;
dwRet = card->readKeysetIds(cks, &dwKeysetId); //获取keysetID
if (dwRet != S_OK) return dwRet;
if (keysetName.size() == 0)
{
// the first keyset id is thought of as the default keyset
BYTE bState = cks[0].state & 0x08;
if ( !bState ) return NTE_BAD_KEYSET_PARAM;
// key set exists
keysetName = cks[0].keysetId;
}
else
{
int i = 0;
for (; i < CARD_KEYSET_MAX; i++)
{
if (cks[i].state & 0x08)
{
if (lstrcmpi(cks[i].keysetId, keysetName.c_str()) == 0)
break;
}
}
if (i >= CARD_KEYSET_MAX) return NTE_BAD_KEYSET_PARAM;
}
keyset = OPENCSP_Keyset::findKeyset(keysetName);
if (keyset)
{
OPENCSP_UsrMutex userMutex;
SHARED_KEYSET_INFO_LIST::iterator it = g_sharedKeysetInfo.begin();
for (; it != g_sharedKeysetInfo.end(); ++it)
{
if ((it->_atr == card->getAtr()) &&
(lstrcmpi(it->_keysetName.c_str(), keyset->_keysetName.c_str()) == 0) &&
(lstrcmpi(it->_readerName.c_str(), card->getReaderName()) == 0))
{
(it->_refCount)++;
break;
}
}
}
else
{
// now create the keyset
keyset = new OPENCSP_Keyset(keysetName, flags);
if (!keyset)
{
return NTE_NO_MEMORY;
}
OPENCSP_UsrMutex userMutex;
SHARED_KEYSET_INFO ski;
memset(&ski, 0, sizeof(SHARED_KEYSET_INFO));
ski._atr = card->getAtr();
ski._keysetName = keyset->_keysetName;
ski._readerName = card->getReaderName();
ski._refCount++;
g_sharedKeysetInfo.insert(g_sharedKeysetInfo.end(), ski);
}
hProv = keyset->createProvider(card);
}
break;
case CRYPT_NEWKEYSET:
{
if (keysetName.size() == 0)
{
// want to create default keyset
keysetName = s_szDefaultContext;
}
keyset = OPENCSP_Keyset::findKeyset(keysetName);
if (keyset) return NTE_EXISTS;
if (reader.size() == 0)
{
/* reader name is not specified */
card = OPENCSP_CardAccess::getCardInstance(NULL);
if (!card)
{
if (bSilent) return OPENCSP_CardAccess::getResultCode();
dwRet = OPENCSP_CardAccess::showSCardUIDlg(reader);
if (dwRet != S_OK) return dwRet;
// reconnect to get card access instance
card = OPENCSP_CardAccess::getCardInstance(reader);
if (!card) return OPENCSP_CardAccess::getResultCode();
}
}
else
{
card = OPENCSP_CardAccess::getCardInstance(reader);
if (!card) return OPENCSP_CardAccess::getResultCode();
}
reader = card->getReaderName();
/* LOGIC:
1) determine the keyset Id is not existed in card; else return NTE_EXISTS;
2) create the keyset Id in card
*/
// read keyset id from the card
CARDKEYSETSTATE cks[CARD_KEYSET_MAX] = {{0}};
DWORD dwKeysetId = CARD_KEYSET_MAX;
dwRet = card->readKeysetIds(cks, &dwKeysetId);
if (dwRet != S_OK) return dwRet;
// the first keyset id is thought of as the default keyset
// but ensure the keyset id not existed
BYTE bState = 0;
DWORD dwIndex = 0;
for (; dwIndex < dwKeysetId; dwIndex ++)
{
bState = cks[dwIndex].state & 0x08;
if (bState)
{
if (dwIndex == 0 && keysetName == KEYSET_NAME(s_szDefaultContext))
{
return NTE_BAD_KEYSET_PARAM;
}
if (lstrcmpi(keysetName.c_str(), cks[dwIndex].keysetId) == 0)
{
return NTE_EXISTS;
}
}
}
// No found, so create it
BOOL bCreated = FALSE;
DWORD fOK = S_OK;
for (dwIndex = 0; dwIndex < dwKeysetId; dwIndex++)
{
bState = cks[dwIndex].state & 0x08;
if (!bState)
{
bCreated = TRUE;
/* PIN cache process */
OPENCSP_CardAccess* pCard = OPENCSP_CardAccess::getCardInstance(reader);
if (!pCard) return OPENCSP_CardAccess::getResultCode();
fOK = pCard->dealPin(bSilent);
if (S_OK != fOK) return fOK;
dwRet = card->writeKeysetId(dwIndex + 1, keysetName.c_str());
if (dwRet != S_OK) return dwRet;
break;
}
}
if (!bCreated) return NTE_TOKEN_KEYSET_STORAGE_FULL;
keyset = new OPENCSP_Keyset(keysetName, flags);
if (!keyset) return NTE_NO_MEMORY;
if (dwIndex == 0)
{
// default key set
keyset->setDefault(TRUE);
}
OPENCSP_UsrMutex userMutex;
SHARED_KEYSET_INFO ski;
memset(&ski, 0, sizeof(SHARED_KEYSET_INFO));
ski._atr = card->getAtr();
ski._keysetName = keyset->_keysetName;
ski._readerName = card->getReaderName();
ski._refCount++;
g_sharedKeysetInfo.insert(g_sharedKeysetInfo.end(), ski);
hProv = keyset->createProvider(card);
}
break;
case CRYPT_VERIFYCONTEXT:
{
if (keysetName.size() != 0)
return NTE_BAD_KEYSET_PARAM;
// want to create verifycontext keyset without hardware attribute(temporary)
keysetName = s_szVerifyContext;
keyset = new OPENCSP_Keyset(keysetName, flags);
if (!keyset)
{
return NTE_NO_MEMORY;
}
hProv = keyset->createProvider(NULL);
}
break;
default:
dwRet = NTE_BAD_FLAGS;
}
return dwRet;
}
DWORD OPENCSP_Keyset::release(HCRYPTPROV hProv)
{
BOOL bFound = FALSE;
READER_NAME readerName;
KEYSETNAME_KYESET_MAP::iterator itr = _keysetMap.begin();
for (; itr != _keysetMap.end(); itr++)
{
OPENCSP_Keyset* keyset = itr->second;
HANDLE_PROVIDER_MAP::iterator itrP = keyset->_provMap.find(hProv);
if (itrP != keyset->_provMap.end())
{
bFound = TRUE;
readerName = itrP->second->getCardInstance()->getReaderName();
keyset->deleteProvider(itrP->first);
if (keyset->isVerifyContext()) break;
OPENCSP_UsrMutex userMutex;
SHARED_KEYSET_INFO_LIST::iterator itr = g_sharedKeysetInfo.begin();
for (; itr != g_sharedKeysetInfo.end(); ++itr)
{
if ((lstrcmpi(itr->_keysetName.c_str(), keyset->_keysetName.c_str()) == 0) &&
(lstrcmpi(itr->_readerName.c_str(), readerName.c_str()) == 0))
{
if (itr->_refCount != 0)
{
--(itr->_refCount);
}
if (itr->_refCount == 0)
{
OPENCSP_Keyset::clearKeysetInstance(itr->_keysetName);
g_sharedKeysetInfo.erase(itr);
goto END;
}
}
}
}
}
END:
if (!bFound) return NTE_BAD_UID;
return S_OK;
}
OPENCSP_Keyset* OPENCSP_Keyset::findKeyset(HCRYPTPROV hProv)
{
BOOL bFound = FALSE;
KEYSETNAME_KYESET_MAP::iterator itr = _keysetMap.begin();
for (; itr != _keysetMap.end(); itr++)
{
OPENCSP_Keyset *keyset = (itr->second);
HANDLE_PROVIDER_MAP::iterator itrP = keyset->_provMap.find(hProv);
if (itrP != keyset->_provMap.end())
{
bFound = TRUE;
break;
}
}
if (bFound) return itr->second;
else return NULL;
}
DWORD OPENCSP_Keyset::deleteKeyset(const READER_NAME& rn, const KEYSET_NAME& kn, BOOL bSilent)
{
DWORD dwRet = S_OK;
BOOL bDefault = FALSE;
OPENCSP_CardAccess* card = NULL;
OPENCSP_Keyset* keyset = NULL;
KEYSET_NAME knToDelete, readerName = rn;
KEYSETNAME_KYESET_MAP::const_iterator itrKeyset;
SHARED_KEYSET_INFO_LIST::iterator itrSharedInfo;
CARDKEYSETSTATE cks[CARD_KEYSET_MAX] = {{0}};
DWORD dwKeysetId = CARD_KEYSET_MAX;
if (!lstrlen(kn.c_str()))
{
// delete default key set(that is, to delete the first key set)
bDefault = TRUE;
for (itrKeyset = _keysetMap.begin(); itrKeyset != _keysetMap.end(); itrKeyset++)
{
if (itrKeyset->second->isDefault())
{
return ERROR_BUSY;
}
}
}
else
{
knToDelete = kn;
itrKeyset = _keysetMap.find(kn);
if (itrKeyset != _keysetMap.end())
return ERROR_BUSY;
}
// Keyset to delete must not be referred before
card = OPENCSP_CardAccess::getCardInstance(readerName);
if (!card)
{
if (bSilent) return OPENCSP_CardAccess::getResultCode();
dwRet = OPENCSP_CardAccess::showSCardUIDlg(readerName);
if (dwRet != S_OK) return dwRet;
// reconnect to get card access instance
card = OPENCSP_CardAccess::getCardInstance(readerName);
if (!card) return OPENCSP_CardAccess::getResultCode();
}
dwRet = card->readKeysetIds(cks, &dwKeysetId);
if (dwRet != S_OK) return dwRet;
if (bDefault)
{
if (!(cks[0].state & 0x08))
{
dwRet = NTE_BAD_KEYSET_PARAM;
goto END;
}
knToDelete = cks[0].keysetId;
}
dwRet = card->dealPin(bSilent);
if (S_OK != dwRet) return dwRet;
dwRet = card->deleteKeyset(knToDelete.c_str()); //删除密钥容器
if (dwRet != S_OK) goto END;
if (keyset) delete keyset;
END:
return dwRet;
}