В некоторых случаях требуется организовать хранение небольших объемов секретных данных внутри энергонезависимой памяти Рутокен.
Наилучшим и наиболее стандартизованным способом доступа к хранилищу данных Рутокен является интерфейс PKCS#11 (подробно).
Объекты в Рутокен с точки зрения стандарта PKCS#11 выглядят следующим образом (подробно).
Уровни доступа к объектам в памяти Рутокен
Гостевой уровень позволяет просматривать, создавать, модифицировать и удалять только публичные (несекретные) объекты.
Для получения гостевого доступа не требуется знание ПИН-кода.
Пользовательский уровень позволяет просматривать, создавать, модифицировать и удалять как публичные (несекретные), так и приватные (секретные) объекты.
Пользовательский уровень предполагает знание ПИН-кода Пользователя.
Уровень Администратора (офицера безопасности) предполагает знание ПИН-кода Администратора.
Администратор имеет доступ только к публичным объектам. Кроме того, Администратор обладает возможностью очистить память Рутокен, полностью включая приватные (секретные) объекты.
Типы объектов в хранилище данных Рутокен
Публичные (несекретные) объекты - объекты, видимые и доступные для чтения и записи с любым уровнем доступа.
Приватные (секретные) объекты - объекты, видимые и доступные для чтения и записи только с уровнем доступа "пользователь".
Двухфакторный доступ к секретной информации
Первый фактор - физическое наличие устройства.
Второй фактор - знание пользовательского пин-кода.
Пример записи файла через интерфейс PKCS#11
CK_BBOOL ckTrue = CK_TRUE;
CK_BBOOL ckFalse = CK_FALSE;
CK_OBJECT_CLASS ocData = CKO_DATA;
CK_BYTE ckLabel[] = {'f','i','l','e','n','a','m','e','.','t','x','t'};
CK_BYTE ckValue[] = {'t','o','p','s','e','c','r','e','t','i','n','f','o'};
CK_UTF8CHAR ckUserPIN[] = {'1','2','3','4','5','6','7','8'};
CK_ATTRIBUTE DataObject[] = {
{CKA_CLASS, &ocData, sizeof(CK_OBJECT_CLASS) }, // признак объекта данных
{CKA_TOKEN, &ckTrue, sizeof(CK_BBOOL) }, // объект будет создан на токене
{CKA_PRIVATE, &ckTrue, sizeof(CK_BBOOL) }, // объект будет доступен по PIN-коду
{CKA_LABEL, ckLabel, sizeof(ckLabel) }, // метка объекта
{CKA_VALUE, ckValue, sizeof(ckValue) }, // тело объекта
};
CK_RV rv;
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE ckHandle;
.
.
rv = functionList->C_Login(hSession,
CKU_USER,
ckUserPIN,
sizeof(ckUserPIN));
.
.
rv = functionList->C_CreateObject(hSession,
&DataObject,
sizeof(DataObject)/sizeof(CK_ATTRIBUTE),
&ckHandle);
.
.
Пример чтения файла через интерфейс PKCS#11
CK_OBJECT_CLASS ocData = CKO_DATA;
CK_BYTE label[] = {'f','i','l','e','n','a','m','e','.','t','x','t'};;
CK_BBOOL ckTrue = CK_TRUE;
CK_BBOOL ckFalse = CK_FALSE;
CK_OBJECT_HANDLE_PTR objects; // Массив найденных объектов
CK_ULONG objectCount; // Количество хэндлов объектов в массиве
CK_RV rv = CKR_OK;
CK_UTF8CHAR ckUserPIN[] = {'1','2','3','4','5','6','7','8'};
CK_ATTRIBUTE attrDataReadTmpl[] = {
{CKA_CLASS, &ocData, sizeof(ocData)},
{CKA_LABEL, label, sizeof(label) - 1},
{CKA_PRIVATE, &ckTrue, sizeof(ckTrue)}, // Файл доступен по PIN-коду
{CKA_TOKEN, &ckTrue, sizeof(ckTrue)} // хранить файл на токене
};
rv = C_Login(hSession,
CKU_USER,
ckUserPIN,
sizeof(ckUserPIN));
if (rv != CKR_OK)
return;
rv = findObjects(functionList, session, attrDataReadTmpl, arraysize(attrDataReadTmpl), &objects, &objectCount);
.
.
if (objectCount == 1) {
CK_ATTRIBUTE attrValue = { CKA_VALUE, NULL_PTR, 0 };
rv = functionList->C_GetAttributeValue(session, // Хэндл открытой с правами Пользователя сессии
objects[0], // Хэндл объекта из поиска
&attrValue, // Шаблон получения значения атрибута
1); // Количество атрибутов в шаблоне
if (rv != CKR_OK)
return;
/* Выделить необходимое количество памяти для значения атрибута */
attrValue.pValue = (CK_BYTE*)malloc(attrValue.ulValueLen);
if (attrValue.pValue == NULL)
return;
memset(attrValue.pValue, 0, (attrValue.ulValueLen * sizeof(CK_BYTE)));
/* Получить значение объекта */
printf("Getting object value");
rv = functionList->C_GetAttributeValue(session, // Хэндл открытой с правами Пользователя сессии
objects[0], // Хэндл объекта
&attrValue, // Шаблон получения значения атрибута
1); // Количество атрибутов в шаблоне
if (rv != CKR_OK)
return;
/* Распечатать буфер со значением объекта */
printf("Data is:\n");
printf("%.*s", attrValue.ulValueLen, (const char*)attrValue.pValue);
free(attrValue.pValue);
}
Устройства Рутокен, сертифицированные ФСБ, не поддерживают создание (импорт) ключей функцией C_CreateObject по алгоритмам ГОСТ 28147-89, ГОСТ 34.10-2001 и ГОСТ 34.10-2012 в долговременную память (с флагом CKA_TOKEN = TRUE).
1 Comment
Anonymous
sizeof bracket is missing