Болтушкин Л.С., группа 712-2, лабораторная 3
.docxМинистерство науки и высшего образования Российской Федерации
Федеральное государственное автономное образовательное учреждение высшего образования
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР)
Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)
ЗНАКОМСТВО С ETOKEN API
Отчет по лабораторной работе №3
по дисциплине «Программно-аппаратные средства защиты информации»
Выполнил:
Студент гр. 712-2
_______ Л.С. Болтушкин
_______ 2026
Руководитель
Преподаватель кафедры КИБЭВС
_______ С.А. Пашкевич
_______ 2026
Введение
Целью данной лабораторной работы является ознакомление с основами работы с eToken API, изучение базовых функций, связанные с определением наличия eToken в системе, научиться получать информацию о подключенном eToken.
1 ХОД РАБОТЫ
Для начала был загружен проект «Lab1» в Visual Studio и добавлен заголовочный файл «eTPkcs11.h» и следующий код, представленный на рисунке 1.1.
Рисунок 1.1 – Добавление заголовочного файла и инициализация методов и глобальных переменных
Далее для использования функции библиотеки PKCS#11 была произведена ее инициализация, а также добавлена функция выдачи сообщение о соответствующей ошибке и завершение работы программы (рисунок 1.2 – 1.3).
Рисунок 1.2 – Функция инициализации библиотеки
Рисунок 1.3 – Функция выхода из программы
Для того, чтобы получить информацию о библиотеке PKCS#11 была написана функция (рисунок 1.4).
Рисунок 1.4 – Описание функции отображения информации о библиотеке
На рисунке 1.5 представлено выведение в консоль информации о библиотеке PKCS#11.
Рисунок 1.5 – Вывод выполнения функции
Далее была написана функция для отображения информации о подключенном eToken путем опознания идентификатора виртуального слота (рисунок 1.6 – 1.7).
Рисунок 1.6 – Описание функции отображения информации о eToken, часть 1
Рисунок 1.7 – Описание функции отображения информации о eToken, часть 2
Также написана функция, проверяющая возникновение событий подключения и отключения eToken к компьютеру (рисунок 1.8).
Рисунок 1.8 – Описание функции проверки наличия eToken
Последним шагом было дополнение функции main, чтобы в ней производилась инициализация библиотеки, выводилась информация о библиотеке, запускался поток ожидания событий и завершалась работа библиотеки (рисунок 1.9).
Рисунок 1.9 – Описание функции main
На рисунке 1.10 изображен полный вывод функции main с информацией о библиотеке, токене и информации, согласно индивидуальному варианту №3 – label, serialNumber, ulSessionCount, ulMaxRwSessionCount, ulTotalPublicMemory, ulFreePublicMemory, CKF_RNG и CKF_LOGIN_REQUIRED.
Рисунок 1.10 – Вывод функции main
Полный код программы представлен в Приложении А.
Заключение
В ходе выполнения данной лабораторной работы было произведено ознакомление с основами работы с eToken API, изучены базовые функции, связанные с определением наличия eToken в системе, обучены получать информацию о подключенном eToken.
Приложение А
(обязательное)
Листинг программы
#include "stdlib.h"
#include "stdio.h"
#include <windows.h>
#include "include\eTPkcs11.h"
using namespace std;
// Прототипы
void init();
void leave(const char*);
void displayLibraryInfo();
void displayTokenInfo(CK_SLOT_ID slotId);
void checkAllSlots();
// Глобальные переменные
CK_FUNCTION_LIST_PTR pFunctionList = NULL;
CK_C_GetFunctionList pGFL = 0;
bool wasInit = false;
static HANDLE hThread = 0;
// Инициализация
void init()
{
// Загружаем dll
HINSTANCE hLib = LoadLibraryA("etpkcs11.DLL");
if (hLib == NULL)
{
leave("Cannot load DLL.");
}
// Ищем точку входа для C_GetFunctionList
(FARPROC&)pGFL = GetProcAddress(hLib, "C_GetFunctionList");
if (pGFL == NULL)
{
leave("Cannot find GetFunctionList().");
}
// Берем список функций
if (CKR_OK != pGFL(&pFunctionList))
{
leave("Can't get function list. \n");
}
// Инициализируем библиотеку PKCS#11
if (CKR_OK != pFunctionList->C_Initialize(0))
{
leave("C_Initialize failed...\n");
}
wasInit = true;
}
// Завершение работы
static void leave(const char* message)
{
if (message) printf("%s ", message);
if(wasInit)
{
// Закрываем библиотеку PKCS#11
if (CKR_OK != pFunctionList->C_Finalize(0))
{
printf("C_Finalize failed...\n");
}
// Ждем завершения работы потока, иначе убиваем его.
WaitForSingleObject(hThread, 5000);
if (hThread)
{
TerminateThread(hThread, 0);
CloseHandle(hThread);
}
hThread = 0;
wasInit = false;
}
exit(message ? -1 : 0);
}
// Информация о библиотеке
void displayLibraryInfo()
{
CK_INFO lib_info;
if (CKR_OK != pFunctionList->C_GetInfo(&lib_info))
{
printf("C_GetInfo failed.\n");
return;
}
printf("<Common Library Information>\n");
printf("Version - %d.%d\n", lib_info.cryptokiVersion.major, lib_info.cryptokiVersion.minor);
printf("Manufacturer - %.*s\n", 32, lib_info.manufacturerID);
printf("Description eToken PKCS - %.*s\n", 32, lib_info.libraryDescription);
printf("Library version - %d.%d\n\n", lib_info.libraryVersion.major, lib_info.libraryVersion.minor);
}
// Информация о токене (3 вариант)
void displayTokenInfo(CK_SLOT_ID slotId)
{
CK_SLOT_INFO slotInfo;
CK_TOKEN_INFO tokenInfo;
// Получаем информацию о слоте
if (CKR_OK != pFunctionList->C_GetSlotInfo(slotId, &slotInfo))
{
printf("\n----- Event on Slot ID: %lu -----\n", slotId);
printf("C_GetSlotInfo failed.\n");
return;
}
printf("\n----- Event on Slot ID: %lu -----\n", slotId);
printf("Slot description: %.*s\n", 64, slotInfo.slotDescription);
printf("Manufacturer ID: %.*s\n", 32, slotInfo.manufacturerID);
if (!(slotInfo.flags & CKF_TOKEN_PRESENT))
{
printf("Token NOT present in this slot.\n");
return;
}
// Получаем информацию о токене
if (CKR_OK != pFunctionList->C_GetTokenInfo(slotId, &tokenInfo))
{
printf("C_GetTokenInfo failed.\n");
return;
}
printf("\n========== TOKEN INFO (Variant 3) ==========\n");
// 1. label
printf("Label: %.*s\n", 32, tokenInfo.label);
// 2. serialNumber
printf("Serial Number: %.*s\n", 16, tokenInfo.serialNumber);
// 3. ulSessionCount
printf("Session Count: %lu\n", tokenInfo.ulSessionCount);
// 4. ulMaxRwSessionCount
printf("Max Read/Write Sessions: %lu\n", tokenInfo.ulMaxRwSessionCount);
// 5. ulTotalPublicMemory
printf("Total Public Memory: %lu bytes\n", tokenInfo.ulTotalPublicMemory);
// 6. ulFreePublicMemory
printf("Free Public Memory: %lu bytes\n", tokenInfo.ulFreePublicMemory);
// 7. CKF_RNG
printf("CKF_RNG (Random Generator): %s\n",
(tokenInfo.flags & CKF_RNG) ? "Present" : "Not present");
// 8. CKF_LOGIN_REQUIRED
printf("CKF_LOGIN_REQUIRED: %s\n",
(tokenInfo.flags & CKF_LOGIN_REQUIRED) ? "Yes" : "No");
printf("============================================\n\n");
}
// Проверка всех слотов
void checkAllSlots()
{
CK_ULONG slotCount;
CK_SLOT_ID_PTR pSlotList = NULL;
// Получаем количество слотов
if (CKR_OK != pFunctionList->C_GetSlotList(TRUE, NULL, &slotCount))
{
printf("Failed to get slot list\n");
return;
}
if (slotCount == 0)
{
printf("\nNo tokens found\n");
return;
}
pSlotList = (CK_SLOT_ID_PTR)malloc(slotCount * sizeof(CK_SLOT_ID));
if (pSlotList == NULL)
{
printf("Memory allocation failed\n");
return;
}
if (CKR_OK != pFunctionList->C_GetSlotList(TRUE, pSlotList, &slotCount))
{
printf("Failed to get slot list\n");
free(pSlotList);
return;
}
printf("\n=== Currently connected tokens ===\n");
for (CK_ULONG i = 0; i < slotCount; i++)
{
displayTokenInfo(pSlotList[i]);
}
free(pSlotList);
}
// Поток ожидания событий
static DWORD __stdcall TokenNotifyThread(void*)
{
while (true)
{
CK_SLOT_ID slotId;
int res = pFunctionList->C_WaitForSlotEvent(0, &slotId, 0);
if (res == CKR_OK)
{
displayTokenInfo(slotId);
}
else
{
break;
}
}
return 0;
}
// Главная функция
int main()
{
// Устанавливаем UTF-8 для консоли
SetConsoleOutputCP(CP_UTF8);
printf("Laba №3 - Variant 3\n");
printf("==============================\n");
init();
displayLibraryInfo();
printf("Checking for tokens...\n");
checkAllSlots();
// Запуск потока
hThread = CreateThread(NULL, 0, TokenNotifyThread, NULL, 0, NULL);
if (hThread == NULL)
{
leave("Failed to create thread");
}
printf("\nWaiting for token events... Press any key to exit.\n");
getchar();
leave(NULL);
return 0;
}
Томск 2026
