OpenCSP开源程序解析之OPENCSP_Keyset.cpp

#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;
}

你可能感兴趣的:(opencsp)