Не удаляется контейнер 'Aktiv ruToken CSP v1.0' на Rutoken Lite
Доброго времени суток.
После форматирования Rutoken Lite с помощью rtPKCS11ECP.dll невозможно удалить контейнер с помощью криптопровайдера 'Aktiv ruToken CSP v1.0'. Проблемы нет, если форматирование производить с помощью библиотеки rtPKCS11.dll.
При вызове 'CryptAcquireContext(&prov2, full_container_name.c_str(), g_prov_name, g_prov_type, CRYPT_SILENT | CRYPT_DELETEKEYSET)' возникает ошибка 0x8007001f.
Проблема воспроизводится на драйверах:
v.2.100.00.0542_20.11.2014
v.4.0.0.0_31.08.2015
v.4.0.1.0_14.10.2015
v.4.0.2.0_23.10.2015
v.4.0.5.0_30.12.2015
На более ранних версиях ошибка не воспроизводится.
Проверено на операционных системах: windows 7 x64, windows 8.1 x64 и windows 8.1 x86
В примере файл Common.h взят из SDK
Пример:
#include <Windows.h>
#include <WinCrypt.h>
#include <iostream>
#include <string>
#include "Common.h"
#define MAX_ADMIN_RETRY_COUNT 10
#define MAX_USER_RETRY_COUNT 10
DWORD g_prov_type = 0x1;
LPCSTR g_prov_name = "Aktiv ruToken CSP v1.0";
LPCSTR g_token_pass = "12345678";
bool InitTokenEx();
bool InitToken();
bool DeleteContainer(LPCSTR container_name, LPCSTR reader_name);
bool GenerateKeyPair(LPCSTR container_name, LPCSTR reader_name);
int main()
{
    LPCSTR container_name = "Test container!";
    LPCSTR reader_name = "\\\\.\\Aktiv Rutoken lite 0\\";
    //LPCSTR reader_name = "\\\\.\\Aktiv Rutoken ECP 0\\";
    //LPCSTR reader_name = "\\\\.\\Aktiv Co. ruToken 0\\";
    if (!InitTokenEx())
    {
        return 0;
    }
    if (!GenerateKeyPair(container_name, reader_name))
    {
        return 0;
    }
    if (!DeleteContainer(container_name, reader_name))
    {
        return 0;
    }
    std::cout << "Success!" << std::endl;
    return 0;
}
bool InitTokenEx()
{
    HMODULE module = NULL_PTR;
    CK_SESSION_HANDLE session = NULL_PTR;
    CK_FUNCTION_LIST_PTR function_list = NULL_PTR;
    CK_C_GetFunctionList get_function_list_func = NULL_PTR;
    CK_FUNCTION_LIST_EXTENDED_PTR function_list_ex = NULL_PTR;
    CK_C_EX_GetFunctionListExtended get_function_list_func_ex = NULL_PTR;
    CK_SLOT_ID_PTR slots = NULL_PTR;
    CK_ULONG slot_count = 0;
    CK_RV rv = CKR_OK;
    module = LoadLibrary(PKCS11ECP_LIBRARY_NAME);
    if (module == NULL_PTR)
    {
        std::cout << "Function 'LoadLibrary' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    get_function_list_func = (CK_C_GetFunctionList)GetProcAddress(module, "C_GetFunctionList");
    if (get_function_list_func == NULL_PTR)
    {
        std::cout << "Function 'GetProcAddress' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    rv = get_function_list_func(&function_list);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetFunctionList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    get_function_list_func_ex = (CK_C_EX_GetFunctionListExtended)GetProcAddress(module, "C_EX_GetFunctionListExtended");
    if (get_function_list_func == NULL_PTR)
    {
        std::cout << "Function 'GetProcAddress' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    rv = get_function_list_func(&function_list);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetFunctionList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = get_function_list_func_ex(&function_list_ex);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'CK_C_EX_GetFunctionList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_Initialize(NULL_PTR);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_Initialize' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_GetSlotList(CK_TRUE, NULL_PTR, &slot_count);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetSlotList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    if (slot_count == 0)
    {
        std::cout << "Function 'C_GetSlotList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    slots = (CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID));
    memset(slots, 0, (slot_count * sizeof(CK_SLOT_ID)));
    rv = function_list->C_GetSlotList(CK_TRUE, slots, &slot_count);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetSlotList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    static CK_UTF8CHAR NEW_USER_PIN[] = {'1', '2', '3', '4', '5', '6', '7', '8'};
    static CK_UTF8CHAR SO_PIN[] = {'8', '7', '6', '5', '4', '3', '2', '1'};
    static CK_CHAR TOKEN_STD_LABEL[] = {"!!!Sample Rutoken label!!!"};
    CK_RUTOKEN_INIT_PARAM initInfo_st;
    CK_BBOOL bIsRutokenECP = TRUE;
    ::memset(&initInfo_st, 0, sizeof(CK_RUTOKEN_INIT_PARAM));
    initInfo_st.ulSizeofThisStructure = sizeof(CK_RUTOKEN_INIT_PARAM);
    initInfo_st.UseRepairMode = 0;
    initInfo_st.pNewAdminPin = SO_PIN;
    initInfo_st.ulNewAdminPinLen = sizeof(SO_PIN);
    initInfo_st.pNewUserPin = NEW_USER_PIN;
    initInfo_st.ulNewUserPinLen = sizeof(NEW_USER_PIN);
    initInfo_st.ulMinAdminPinLen = bIsRutokenECP ? 6 : 1;
    initInfo_st.ulMinUserPinLen = bIsRutokenECP ? 6 : 1;
    initInfo_st.ChangeUserPINPolicy = (TOKEN_FLAGS_ADMIN_CHANGE_USER_PIN | TOKEN_FLAGS_USER_CHANGE_USER_PIN);
    initInfo_st.ulMaxAdminRetryCount = MAX_ADMIN_RETRY_COUNT;
    initInfo_st.ulMaxUserRetryCount = MAX_USER_RETRY_COUNT;
    initInfo_st.pTokenLabel = TOKEN_STD_LABEL;
    initInfo_st.ulLabelLen = sizeof(TOKEN_STD_LABEL);
    rv = function_list_ex->C_EX_InitToken(slots[0], SO_PIN, arraysize(SO_PIN), &initInfo_st);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_EX_InitToken' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_CloseAllSessions(slots[0]);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_CloseAllSessions' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    return true;
}
bool InitToken()
{
    HMODULE module = NULL_PTR;
    CK_SESSION_HANDLE session = NULL_PTR;
    CK_FUNCTION_LIST_PTR function_list = NULL_PTR;
    CK_C_GetFunctionList get_function_list_func = NULL_PTR;
    CK_SLOT_ID_PTR slots = NULL_PTR;
    CK_ULONG slot_count = 0;
    CK_RV rv = CKR_OK;
    module = LoadLibrary(PKCS11_LIBRARY_NAME);
    if (module == NULL_PTR)
    {
        std::cout << "Function 'LoadLibrary' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    get_function_list_func = (CK_C_GetFunctionList)GetProcAddress(module, "C_GetFunctionList");
    if (get_function_list_func == NULL_PTR)
    {
        std::cout << "Function 'GetProcAddress' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    rv = get_function_list_func(&function_list);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetFunctionList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_Initialize(NULL_PTR);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_Initialize' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_GetSlotList(CK_TRUE, NULL_PTR, &slot_count);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetSlotList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    if (slot_count == 0)
    {
        std::cout << "Function 'C_GetSlotList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    slots = (CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID));
    memset(slots, 0, (slot_count * sizeof(CK_SLOT_ID)));
    rv = function_list->C_GetSlotList(CK_TRUE, slots, &slot_count);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_GetSlotList' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_InitToken(slots[0], SO_PIN, sizeof(SO_PIN), TOKEN_LABEL);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_InitToken' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_OpenSession(slots[0], CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &session);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_OpenSession' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_Login(session, CKU_SO, SO_PIN, sizeof(SO_PIN));
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_OpenSession' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_InitPIN(session, USER_PIN, sizeof(USER_PIN));
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_OpenSession' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_Logout(session);
    if ((rv != CKR_OK) && (rv != CKR_USER_NOT_LOGGED_IN))
    {
        std::cout << "Function 'C_Logout' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    rv = function_list->C_CloseAllSessions(slots[0]);
    if (rv != CKR_OK)
    {
        std::cout << "Function 'C_CloseAllSessions' failed! Error: 0x" << std::hex << rv << std::endl;
        return false;
    }
    return true;
}
bool DeleteContainer(LPCSTR container_name, LPCSTR reader_name)
{
    std::string full_container_name = std::string(reader_name) + std::string(container_name);
    HCRYPTPROV prov = 0;
    if (!::CryptAcquireContext(&prov, reader_name, g_prov_name, g_prov_type, CRYPT_DEFAULT_CONTAINER_OPTIONAL | CRYPT_SILENT))
    {
        std::cout << "Function 'CryptAcquireContext' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    if (!::CryptSetProvParam(prov, PP_KEYEXCHANGE_PIN, (BYTE*)g_token_pass, 0))
    {
        std::cout << "Function 'CryptSetProvParam' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    HCRYPTPROV prov2 = 0;
    if (!::CryptAcquireContext(&prov2, full_container_name.c_str(), g_prov_name, g_prov_type, CRYPT_SILENT | CRYPT_DELETEKEYSET))
    {
        std::cout << "Function 'CryptAcquireContext' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    ::CryptReleaseContext(prov2, 0);
    ::CryptReleaseContext(prov, 0);
    return true;
}
bool GenerateKeyPair(LPCSTR container_name, LPCSTR reader_name)
{
    std::string full_container_name = std::string(reader_name) + std::string(container_name);
    HCRYPTPROV prov = 0;
    if (!::CryptAcquireContext(&prov, reader_name, g_prov_name, g_prov_type, CRYPT_DEFAULT_CONTAINER_OPTIONAL | CRYPT_SILENT))
    {
        std::cout << "Function 'CryptAcquireContext' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    if (!::CryptSetProvParam(prov, PP_KEYEXCHANGE_PIN, (BYTE*)g_token_pass, 0))
    {
        std::cout << "Function 'CryptSetProvParam' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    HCRYPTPROV prov2 = 0;
    HCRYPTKEY key = 0;
    if (!::CryptAcquireContext(&prov2, full_container_name.c_str(),    g_prov_name, g_prov_type, CRYPT_NEWKEYSET | CRYPT_SILENT))
    {
        std::cout << "Function 'CryptAcquireContext' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    if (!::CryptGenKey(prov2, AT_KEYEXCHANGE, 0, &key))
    {
        std::cout << "Function 'CryptGenKey' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    ::CryptDestroyKey(key);
    key = 0;
    if (!::CryptGetUserKey(prov2, AT_KEYEXCHANGE, &key))
    {
        std::cout << "Function 'CryptGetUserKey' failed! Error: 0x" << std::hex << HRESULT_FROM_WIN32(::GetLastError()) << std::endl;
        return false;
    }
    ::CryptDestroyKey(key);
    ::CryptReleaseContext(prov2, 0);
    ::CryptReleaseContext(prov, 0);
    return true;
}