
Министерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР)
Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)
ЗНАКОМСТВО С ETOKEN API
Отчет по лабораторной работе №4
по дисциплине «Программно-аппаратные средства защиты информации»
-
Студент гр. 731-2
__________
Руководитель
Преподаватель каф. КИБЭВС
__________
Введение
Цель работы: ознакомиться с сертификатами X.509, изучить функции eToken API, связанные с импортом сертификатов на eToken, научиться производить операцию входа пользователя на eToken.
1 Ход работы
Первоочередно был импортирован сертификат преподавателя, что представлено на рисунках 1.1 – 1.2.
Рисунок 1.1 – Процесс импорта сертификата
Рисунок 1.2 – Успешный импорт сертификата
Далее был создан сертификат студента с помощью утилиты makecert.exe, что представлено на рисунках 1.3 – 1.4.
Рисунок 1.3 – Процесс создания сертификата
Рисунок 1.4 – Отображение созданного сертификата
Далее был загружен проект работы и добавлены в него заголовки функций и глобальные переменные, что представлено на рисунке 1.5.
Рисунок 1.5 – Заголовки функций
Далее были добавленые функции ReadCertFromFile, которая обеспечивает чтение файла с сертификатом, GetX509Subject, которая предназначена для получения темы сертификата, CreateCertFromBlob, которая предназначена для создания файла с сертификатом на eToken, что представлено на рисунках 1.6 – 1.8.
Рисунок 1.6 – Функция ReadCertFromFile
Рисунок 1.7 – Функция GetX509Subject
Рисунок 1.8 – Функция CreateCertFromBlob
Для получения идентификатора слота, к которому подключен eToken используется функция GetFirstSlotId, представленная на рисунке 1.9.
Рисунок 1.9 – Функция GetFirstSlotId
Далее была разработана функция импорта сертификата в которой используются все вышеописанные функции, а также была добавлена функция C_Login, отвечающая за вход под ролью пользователя на токен, что представлено на рисунке 1.10.
Рисунок 1.10 – Функция ImportCertificate
После была разработана функция main и ее вывод как в консольном виде так и через eToken, что представлено на рисунках 1.11 – 1.14.
Рисунок 1.11 – Описание функции main
Рисунок 1.12 – Вывод функции main
Рисунок 1.13 – Информация о сертификатах после выполнения программы
Рисунок 1.14 – Информация о сертификатах после выполнения программы
Заключение
В ходе выполнения лабораторной работы было произведено ознакомление с сертификатами X.509, изучены функции eToken API, связанные с импортом сертификатов на eToken, получены навыки производить операцию входа пользователя на eToken.
Приложение 1
#include "stdlib.h"
#include "stdio.h"
#include "include\eTPkcs11.h"
#include <windows.h>
using namespace std;
void init();
void leave(const char*);
static bool ReadCertFromFile(const char* fileName, CK_BYTE_PTR* cert, DWORD* certSize);
static void GetX509Subject(CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR* subject, int* subjectSize);
static bool CreateCertFromBlob(CK_SESSION_HANDLE hSession, CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR subject, int subjSize);
// Глобальные переменные
CK_FUNCTION_LIST_PTR pFunctionList = NULL;
CK_C_GetFunctionList pGFL = 0;
bool wasInit = false;
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.");
}
// Инициализируем библиотеку PKCS#11
if (CKR_OK != pFunctionList->C_Initialize(0))
{
leave("C_Initialize failed...");
}
wasInit = true;
}
static void leave(const char* message)
{
if (message) printf("%s\n", message);
if (wasInit)
{
// Закрываем библиотеку PKCS#11
if (CKR_OK != pFunctionList->C_Finalize(0))
{
printf("C_Finalize failed...\n");
}
wasInit = false;
}
exit(message ? -1 : 0);
}
static bool ReadCertFromFile(const char* fileName, CK_BYTE_PTR* cert, DWORD* certSize)
{
HANDLE hFile = CreateFileA(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Failed to open file: %s\n", fileName);
return false;
}
*certSize = GetFileSize(hFile, NULL);
if (*certSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
printf("Failed to get file size\n");
return false;
}
*cert = (CK_BYTE_PTR)malloc(*certSize);
if (*cert == NULL)
{
CloseHandle(hFile);
printf("Memory allocation failed for certificate\n");
return false;
}
DWORD bytesRead;
bool nFile = ReadFile(hFile, *cert, *certSize, &bytesRead, NULL);
CloseHandle(hFile);
if (!nFile || bytesRead != *certSize)
{
free(*cert);
*cert = NULL;
printf("Failed to read file contents\n");
return false;
}
return true;
}
static void GetX509Subject(CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR* subject, int* subjectSize)
{
unsigned int i;
unsigned char* current = cert;
unsigned char* prev;
unsigned char* end = cert + certSize;
unsigned char tags[] = {0x30, 0, 0x30, 0, 0xa0, 1, 0x02, 1, 0x30, 1, 0x30, 1, 0x30, 1, 0x30, 1};
*subject = NULL;
*subjectSize = 0;
for (i = 0; i < sizeof(tags); i += 2)
{
unsigned char v;
unsigned int length = 0;
prev = current;
if (current + 2 > end) return;
if (*current++ != tags[i]) return;
v = *current++;
if ((v & 0x80) == 0) length = v;
else
{
unsigned char lenlen = v & 0x7f;
if (current + lenlen > end) return;
for (v = 0; v < lenlen; v++) length = (length << 8) + *current++;
}
if (tags[i + 1]) current += length;
}
*subject = prev;
*subjectSize = (int)(current - prev);
}
static bool CreateCertFromBlob(CK_SESSION_HANDLE hSession, CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR subject, int subjSize)
{
CK_OBJECT_CLASS classAttr = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE certType = CKC_X_509;
unsigned long certCategory = 2;
CK_BBOOL trueVal = CK_TRUE;
CK_OBJECT_HANDLE hObject;
CK_ATTRIBUTE templateArray[] =
{
{CKA_CLASS, &classAttr, sizeof(classAttr)},
{CKA_CERTIFICATE_TYPE, &certType, sizeof(certType)},
{CKA_TOKEN, &trueVal, sizeof(trueVal)},
{CKA_SUBJECT, subject, subjSize},
{CKA_VALUE, (void*)cert, certSize},
{CKA_CERTIFICATE_CATEGORY, (void*)&certCategory, sizeof(certCategory)},
};
int sizeOfTemplate = sizeof(templateArray) / sizeof(CK_ATTRIBUTE);
CK_RV rv = pFunctionList->C_CreateObject(hSession, templateArray, sizeOfTemplate, &hObject);
if (rv != CKR_OK)
{
printf("Failed to create certificate object\n");
return false;
}
return true;
}
static CK_ULONG GetFirstSlotId()
{
CK_ULONG slotID = -1;
CK_ULONG ulCount = 0;
CK_SLOT_ID_PTR pSlotIDs = NULL_PTR;
CK_ULONG i;
if (pFunctionList->C_GetSlotList(TRUE, NULL_PTR, &ulCount) == CKR_OK)
{
if (ulCount > 0)
{
pSlotIDs = new CK_SLOT_ID[ulCount];
if (pFunctionList->C_GetSlotList(TRUE, pSlotIDs, &ulCount) == CKR_OK)
{
for (i = 0; i < ulCount; i++)
{
CK_SLOT_INFO info;
if (pFunctionList->C_GetSlotInfo(pSlotIDs[i], &info) == CKR_OK)
{
if (info.flags & (CKF_HW_SLOT | CKF_TOKEN_PRESENT))
{
slotID = pSlotIDs[i];
break;
}
}
}
}
}
}
if (pSlotIDs)
{
delete[] pSlotIDs;
pSlotIDs = NULL_PTR;
}
return slotID;
}
static void ImportCertificate(const char* fileName, const char* password)
{
CK_BYTE_PTR cert = NULL;
DWORD certSize = 0;
CK_BYTE_PTR subject = NULL;
int subjSize = 0;
if (!ReadCertFromFile(fileName, &cert, &certSize) || cert == NULL || certSize == 0)
{
leave("Failed to read certificate from file.");
}
GetX509Subject(cert, certSize, &subject, &subjSize);
if (subject == NULL || subjSize == 0)
{
leave("Failed to extract subject from certificate.");
}
CK_SESSION_HANDLE hSession;
CK_RV rv = pFunctionList->C_OpenSession(GetFirstSlotId(), CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &hSession);
if (rv != CKR_OK)
{
leave("Failed to open session.");
}
rv = pFunctionList->C_Login(hSession, CKU_USER, (LPBYTE)password, strlen(password));
if (rv != CKR_OK)
{
pFunctionList->C_CloseSession(hSession);
switch(rv)
{
case CKR_PIN_INCORRECT:
leave("Incorrect PIN code.");
break;
case CKR_USER_ALREADY_LOGGED_IN:
leave("User is already logged in.");
break;
default:
leave("Failed to login with unknown error.");
break;
}
}
if (!CreateCertFromBlob(hSession, cert, certSize, subject, subjSize))
{
pFunctionList->C_Logout(hSession);
pFunctionList->C_CloseSession(hSession);
leave("Failed to create certificate.");
}
pFunctionList->C_Logout(hSession);
pFunctionList->C_CloseSession(hSession);
}
int main()
{
init();
char path[128] = "C:\\Users\\Admin\\Documents\\Лаб2\\KAD.cer";
char pin_code[5];
printf("Enter PIN code: ");
gets(pin_code);
ImportCertificate(path, pin_code);
leave(NULL);
return 0;
}
Томск 2025