(2020-02-07 12:18:14 отредактировано Binger)

Как получить кол-во оставшихся попыток на ввод пин-кода от токена?

Доброго времени суток! Подскажите, пожалуйста, как я могу программно получить кол-во оставшихся попыток на ввод пин-кода? Если в Панели управления Рутокен вводить неверный пароль то окно с ошибкой оповещает пользователя об оставшихся попыток до блокировки токена, как получить эту цифру? Хотелось бы с помощью PKCS11 или OpenSSL(программно).

Спасибо

Re: Как получить кол-во оставшихся попыток на ввод пин-кода от токена?

Добрый день.

Можно отправить APDU-команду в токен, например через opensc-tool из пакета opensc.
- для пользователя
>opensc-tool.exe -r 3 -s 00200002
- для администратора
>opensc-tool.exe -r 3 -s 00200001

Параметр -r 3 - это номер ридера, который можно получить через
> opensc-tool.exe -l

В выводе должны быть следующие строки
Sending: 00 20 00 02
Received (SW1=0x63, SW2=0xCA)

последний полубайт в в байте 0xCA - A - и есть количество оставшихся попыток ввода PIN-кода. В данном случае это 10dec.

С уважением, Алексей Лазарев, Компания "Актив"

(2020-02-07 12:57:04 отредактировано Binger)

Re: Как получить кол-во оставшихся попыток на ввод пин-кода от токена?

Алексей Лазарев, меня интересует именно программный вариант. Я пишу программу на C++ и мне нужно на этом уровне как-то получить информацию. Не из терминала

Re: Как получить кол-во оставшихся попыток на ввод пин-кода от токена?

Вот так, например:


#include <Common.h>

int main(void)
{
    HMODULE module;                                    // Хэндл загруженной библиотеки PKCS#11
    CK_SESSION_HANDLE session;                         // Хэндл открытой сессии

    CK_FUNCTION_LIST_PTR functionList;                 // Указатель на список функций PKCS#11, хранящийся в структуре CK_FUNCTION_LIST
    CK_C_GetFunctionList getFunctionList;              // Указатель на функцию C_GetFunctionList

    CK_FUNCTION_LIST_EXTENDED_PTR functionListEx;      // Указатель на список функций расширения PKCS#11, хранящийся в структуре CK_FUNCTION_LIST_EXTENDED
    CK_C_EX_GetFunctionListExtended getFunctionListEx; // Указатель на функцию C_EX_GetFunctionListExtended

    CK_SLOT_ID_PTR slots;                              // Массив идентификаторов слотов
    CK_ULONG slotCount;                                // Количество идентификаторов слотов в массиве

    CK_TOKEN_INFO_EXTENDED tokenInfoEx;                // Структура данных типа CK_TOKEN_INFO_EXTENDED с информацией о токене

    CK_CHAR_PTR tokenName;                             // Указатель на метку токена
    CK_ULONG tokenNameLength;                          // Размер метки токена

    CK_RUTOKEN_INIT_PARAM initParam;                   // Структура данных типа CK_RUTOKEN_INIT_PARAM, содержащая параметры для работы функции C_EX_InitToken

    CK_RV rv;                                          // Код возврата. Могут быть возвращены только ошибки, определенные в PKCS#11

    CK_ULONG i;                                        // Вспомогательная переменная-счетчик в циклах

    int isRutokenS;                                    // Вспомогательная переменная для хранения признака типа токена

    int errorCode = 1;                                 // Флаг ошибки

    /*************************************************************************
    * Выполнить действия для начала работы с библиотекой PKCS#11             *
    *************************************************************************/
    printf("Initialization...\n");

    /*************************************************************************
    * Загрузить библиотеку                                                   *
    *************************************************************************/
    module = LoadLibrary(PKCS11_LIBRARY_NAME);
    CHECK(" LoadLibrary", module != NULL, exit);

    /*************************************************************************
    * Получить адрес функции запроса структуры с указателями на функции      *
    *************************************************************************/
    getFunctionList = (CK_C_GetFunctionList)GetProcAddress(module, "C_GetFunctionList");
    CHECK(" GetProcAddress", getFunctionList != NULL, unload_pkcs11);

    /*************************************************************************
    * Получить адрес функции запроса структуры с указателями на              *
    * расширенные функции                                                    *
    *************************************************************************/
    getFunctionListEx = (CK_C_EX_GetFunctionListExtended)GetProcAddress(module, "C_EX_GetFunctionListExtended");
    CHECK(" GetProcAddress", getFunctionListEx != NULL, unload_pkcs11);

    /*************************************************************************
    * Получить структуру с указателями на функции                            *
    *************************************************************************/
    rv = getFunctionList(&functionList);
    CHECK_AND_LOG(" Get function list", rv == CKR_OK, rvToStr(rv), unload_pkcs11);

    /*************************************************************************
    * Получить структуру с указателями на расширенные функции                *
    *************************************************************************/
    rv = getFunctionListEx(&functionListEx);
    CHECK_AND_LOG(" Get function list extended", rv == CKR_OK, rvToStr(rv), unload_pkcs11);

    /*************************************************************************
    * Инициализировать библиотеку                                            *
    *************************************************************************/
    rv = functionList->C_Initialize(NULL_PTR);
    CHECK_AND_LOG(" C_Initialize", rv == CKR_OK, rvToStr(rv), unload_pkcs11);

    /*************************************************************************
    * Получить количество слотов c подключенными токенами                    *
    *************************************************************************/
    rv = functionList->C_GetSlotList(CK_TRUE, NULL_PTR, &slotCount);
    CHECK_AND_LOG(" C_GetSlotList (number of slots)", rv == CKR_OK, rvToStr(rv), finalize_pkcs11);

    CHECK_AND_LOG(" Checking available tokens", slotCount > 0, " No tokens available", finalize_pkcs11);

    /*************************************************************************
    * Получить список слотов c подключенными токенами                        *
    *************************************************************************/
    slots = (CK_SLOT_ID_PTR)malloc(slotCount * sizeof(CK_SLOT_ID));
    CHECK(" Memory allocation for slots", slots != NULL_PTR, finalize_pkcs11);

    rv = functionList->C_GetSlotList(CK_TRUE, slots, &slotCount);
    CHECK_AND_LOG(" C_GetSlotList", rv == CKR_OK, rvToStr(rv), free_slots);
    printf(" Slots available: %d\n", (int)slotCount);

    printf("Initialization has been completed successfully.\n");

    /*************************************************************************
    * Получить расширенную информацию о подключенном токене                  *
    *************************************************************************/
    printf("\nGetting extended token information...\n");

    tokenInfoEx.ulSizeofThisStructure = sizeof(tokenInfoEx);
    rv = functionListEx->C_EX_GetTokenInfoExtended(slots[0], &tokenInfoEx);
    CHECK_AND_LOG(" C_EX_GetTokenInfoExtended", rv == CKR_OK, rvToStr(rv), free_slots);

    /*************************************************************************
    * Определить класс токена                                                *
    *************************************************************************/
    if (tokenInfoEx.ulTokenClass == TOKEN_CLASS_S) {
        isRutokenS = 1;
    } else {
        isRutokenS = 0;
    }

    printf("Extended token information has been got successfully.\n");

   
    printf(" Max admin retry counter:     0x%8.8x \n", (int)tokenInfoEx.ulMaxAdminRetryCount);
    printf(" Admin retry counter:         0x%8.8x \n", (int)tokenInfoEx.ulAdminRetryCountLeft);
    printf(" Max user retry counter:      0x%8.8x \n", (int)tokenInfoEx.ulMaxUserRetryCount);
    printf(" User retry counter:          0x%8.8x \n", (int)tokenInfoEx.ulUserRetryCountLeft);
   
    printf("\nExtended info test has been completed successfully.\n");

   
    /*************************************************************************
    * Выставить признак успешного завершения программы                       *
    *************************************************************************/
    errorCode = 0;

    /*************************************************************************
    * Выполнить действия для завершения работы с библиотекой PKCS#11         *
    *************************************************************************/
    printf("\nFinalizing... \n");



    /*************************************************************************
    * Очистить память, выделенную под слоты                                  *
    *************************************************************************/
free_slots:
    free(slots);

    /*************************************************************************
    * Деинициализировать библиотеку                                          *
    *************************************************************************/
finalize_pkcs11:
    rv = functionList->C_Finalize(NULL_PTR);
    CHECK_RELEASE_AND_LOG(" C_Finalize", rv == CKR_OK, rvToStr(rv), errorCode);

    /*************************************************************************
    * Выгрузить библиотеку из памяти                                         *
    *************************************************************************/
unload_pkcs11:
    CHECK_RELEASE(" FreeLibrary", FreeLibrary(module), errorCode);

exit:
    if (errorCode) {
        printf("\n\nSome error occurred. Sample failed.\n");
    } else {
        printf("\n\nSample has been completed successfully.\n");
    }

    return errorCode;
}

С уважением, Алексей Лазарев, Компания "Актив"

Re: Как получить кол-во оставшихся попыток на ввод пин-кода от токена?

Алексей Лазарев, именно это и искал. Спасибо))