Функции для работы с сессиями

Типичное приложение может использовать следующую очередность действий при работе с токеном (любая другая разумная последовательность действий также является допустимой):

  1. Выбрать токен.
  2. Сделать один или несколько вызовов функции C_OpenSession для получения одной или нескольких сессий с токеном соответственно.
  3. Вызвать функцию C_Login для авторизации пользователя на токене. Так как все сессии приложения с токеном имеют общее состояние авторизации, требуется только один вызов функции C_Login для любой из сессий.
  4. Выполнить криптографические операции, использующие сессии с токеном.
  5. Вызвать функцию C_CloseSession для каждой из открытой приложением сессии с токеном или функцию C_CloseAllSessions для закрытия всех открытых сессий приложения одновременно.

Приложение может иметь одновременно несколько сессий с более чем одним токеном. Токен может иметь одновременно несколько сессий с более чем одним приложением.

Для управления сессиями стандартом предоставляются следующие функции.

C_OpenSession()

CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
	CK_SLOT_ID 				slotID,
	CK_FLAGS 				flags,
	CK_VOID_PTR 			pApplication,
	CK_NOTIFY 				Notify,
	CK_SESSION_HANDLE_PTR 	phSession
);

Назначение

Функция открывает сессию между приложением и токеном, подключенным к данному слоту.

Когда открывается сессия с использованием функции C_OpenSession, параметр flags состоит из логического ИЛИ нуля или более битовых флагов, определенных в типе CK_SESSION_INFO. По причинам наследования, флаг CKF_SERIAL_SESSION должен быть всегда выставлен, в противном случае вызов C_OpenSession завершится ошибкой CKR_SESSION_PARALLEL_NOT_SUPPORTED.

Ограничение количества одновременно открываемых сессий: всего, rw, read-only - зависит от токена. При попытке открыть сессию, открытие которой превысит ограничение количества одновременных сессий такого типа, вызов функции завершится с ошибкой  CKR_SESSION_PARALLEL_NOT_SUPPORTED.

Если токен защищен от записи (указывается в структуре CK_TOKEN_INFO), то сессия может быть открыта только для чтения.

Если приложение, вызывающее C_OpenSession, уже имеет открытую R/W SO сессию с токеном, то попытка открытия R/O сессии завершится с ошибкой CKR_SESSION_READ_WRITE_SO_EXISTS.

Функция обратного вызова Notify использует библиотеку для уведомления приложения об определенных событиях. Если приложение не поддерживает обратную связь, параметр Notify должен иметь значение NULL_PTR. В текущей реализации Рутокен значение данного параметра игнорируется.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SESSION_COUNT,

CKR_SESSION_PARALLEL_NOT_SUPPORTED,

CKR_SESSION_READ_WRITE_SO_EXISTS,

CKR_SLOT_ID_INVALID,

CKR_TOKEN_NOT_PRESENT,

CKR_TOKEN_NOT_RECOGNIZED,

CKR_TOKEN_WRITE_PROTECTED.

Расширенные коды ошибок

Пример

к содержанию ↑

C_CloseSession()

CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(
	CK_SESSION_HANDLE	hSession
);

Назначение

Функция закрывает сессию между приложением и токеном.

При закрытии сессии все созданные сессией объекты уничтожаются автоматически, даже если приложение имеет другие сессии, использующие эти объекты.

После закрытия последней сессии между приложением и токеном удачным завершением вызова функции C_CloseSession, состояние "залогиненности" токена для приложения вернется к публичной сессии. Любая новая сессия, открытая приложением, будет публичной сессией типа R/O или R/W.

Возвращаемое значение CKR_SESSION_CLOSED означает, пока функция выполнялась, сессия была закрыта другим вызовом C_CloseSession, завершившимся первым.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID.

Расширенные коды ошибок

Пример


CK_SLOT_ID slotID;
CK_BYTE application;
CK_NOTIFY MyNotify;
CK_SESSION_HANDLE hSession;
CK_RV rv;
.
.
application = 17;
MyNotify = &EncryptionSessionCallback;
rv = C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, (CK_VOID_PTR) &application, MyNotify, &hSession);
if (rv == CKR_OK) {
	.
	.
	C_CloseSession(hSession);
}


к содержанию ↑

C_CloseAllSessions()

CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(
	CK_SLOT_ID	slotID
);

Назначение

Функция закрывает все сессии приложения, открытые для данного токена.

При закрытии сессии все созданные сессией объекты уничтожаются автоматически.

После удачного завершения вызова функции C_CloseAllSessions состояние "залогиненности" токена для приложения вернется к публичной сессии. Любая новая сессия, открытая приложением, будет публичной сессией типа R/O или R/W.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SLOT_ID_INVALID,

CKR_TOKEN_NOT_PRESENT.

Расширенные коды ошибок

Пример

CK_SLOT_ID slotID;
CK_RV rv;
.
.
rv = C_CloseAllSessions(slotID);

к содержанию ↑

C_GetSessionInfo()

CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)(
	CK_SESSION_HANDLE hSession,
	CK_SESSION_INFO_PTR pInfo
);

Назначение

Функция получает информацию о сессии.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID.

Расширенные коды ошибок

Пример

CK_SESSION_HANDLE hSession;
CK_SESSION_INFO info;
CK_RV rv;
.
.
rv = C_GetSessionInfo(hSession, &info);
if (rv == CKR_OK) {
	if (info.state == CKS_RW_USER_FUNCTIONS) {
	.
	.
	}
.
.
}

к содержанию ↑

C_GetOperationState()

CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pOperationState,
	CK_ULONG_PTR pulOperationStateLen
);

Назначение

Функция получает копию состояния криптографических операций сессии, представленную строкой байтов, для дальнейшего его восстановления функцией C_SetOperationState.

Если в одну сессию выполняются две криптографические операции одновременно, то состояние криптографических операций будет содержать всю необходимую операцию для восстановления обоих операций.

Попытка сохранить состояние сессии, которая на данный момент не имеет сохраняемых криптографических операций (шифрование, расшифрование, хеширование, подпись без восстановления сообщения и проверка такой подписи, а также комбинации перечисленных операций) приведет к ошибке CKR_OPERATION_NOT_INITIALIZED.

Попытка сохранить состояние сессии, в которой выполняется соответствующая криптографическая операция (или две), но которая по некоторым причинам не может быть удовлетворена (необходимые данные состояния и/или ключевая информация является неизвлекаемыми из памяти токена, например) будет завершена с ошибкой CKR_STATE_UNSAVEABLE.

Функция C_GetOperationState поддерживается библиотекой rtPKCS11 начиная с версии 2.30.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_BUFFER_TOO_SMALL,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_OPERATION_NOT_INITIALIZED,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID,

CKR_STATE_UNSAVEABLE.

Расширенные коды ошибок

Пример

CK_SESSION_HANDLE hSession;
CK_MECHANISM digestMechanism;
CK_ULONG ulStateLen;
CK_BYTE data1[] = {0x01, 0x03, 0x05, 0x07};
CK_BYTE data2[] = {0x02, 0x04, 0x08};
CK_BYTE data3[] = {0x10, 0x0F, 0x0E, 0x0D, 0x0C};
CK_BYTE pDigest[20];
CK_ULONG ulDigestLen;
CK_RV rv;

.
.
/* Инициализация операции хеширования */
rv = C_DigestInit(hSession, &digestMechanism);
assert(rv == CKR_OK);

/* Начало хеширования */
rv = C_DigestUpdate(hSession, data1, sizeof(data1));
assert(rv == CKR_OK);

/* Определение длины состояния криптографических функций */
rv = C_GetOperationState(hSession, NULL_PTR, &ulStateLen);
assert(rv == CKR_OK);

/* Назначение памяти и получение состояния */
pState = (CK_BYTE_PTR) malloc(ulStateLen);
rv = C_GetOperationState(hSession, pState, &ulStateLen);

/* Продолжение хеширования */
rv = C_DigestUpdate(hSession, data2, sizeof(data2));
assert(rv == CKR_OK);

/* Восстановление состояния. Дескрипторы ключей не нужны */
rv = C_SetOperationState(hSession, pState, ulStateLen, 0, 0);
assert(rv == CKR_OK);

/* Продолжение хеширования с сохраненного момента */
rv = C_DigestUpdate(hSession, data3, sizeof(data3));
assert(rv == CKR_OK);

/* Завершение хеширования */
ulDigestLen = sizeof(pDigest);
rv = C_DigestFinal(hSession, pDigest, &ulDigestLen);
if (rv == CKR_OK) {
	/* pDigest[] сейчас содержить хеш-значение 0x01030507100F0E0D0C */
.
.
}

к содержанию ↑

C_SetOperationState()

CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pOperationState,
	CK_ULONG ulOperationStateLen,
	CK_OBJECT_HANDLE hEncryptionKey,
	CK_OBJECT_HANDLE hAuthenticationKey
);

Назначение

Функция восстанавливает состояние криптографических операций сессии из строки байтов, полученных функцией C_SetOperationState.

Состояние не обязательно должно быть получено и восстановлено в одну и ту же сессию. Однако и принимающая, и исходная сессии должны иметь общее состояние сессии (например, CKS_RW_USER_FUNCTIONS) и общий токен. Нет гарантий того, что состояние криптографических операций может быть перенесено через разные "залогиненности" или разные реализации стандарта (библиотеки).

Если функции C_SetOperationState предоставляется сомнительное сохраненное состояние криптографических операций, которое функция определяет как некорректное состояние (или состояние из сессии с другим состоянием сессии, или состояние с другого токена), то функция завершится с ошибкой CKR_SAVED_STATE_INVALID.

Сохраненное состояние, полученное после вызова функции C_GetOperationState может как содержать, так и не содержать ключевую информации для текущих криптографических операций. Если сохраненное состояние содержит операцию шифрования/расшифрования, но не содержит ключ, то он должен быть предоставлен функции аргументом hEncryptionKey, в противном случае C_SetOperationState завершится ошибкой CKR_KEY_NEEDED. Если использующийся для операции ключ сохранен в состоянии, то он может быть также передан в функцию аргументом hEncryptionKey, но это не обязательно.

Аналогично, если состояние содержит операцию хеширования, подписи или проверки подписи, но не содержит ключ, то он должен быть предоставлен функции в аргументе hAuthenticationKey, в противном случае C_SetOperationState завершится ошибкой CKR_KEY_NEEDED. Если использующийся для операции ключ сохранен в состоянии, то он может быть также передан в функцию через аргумент hAuthenticationKey, но это не обязательно.

Если функции передан неподходящий ключ (например, аргумент hEncryptionKey содержит ненулевой дескриптор ключа, но сохраненное состояние не содержит операций шифрования/расшифрования), то C_SetOperationState завершится ошибкой CKR_KEY_NOT_NEEDED.

Если функции аргументом предоставлен ключ, который C_SetOperationState определяется несоответствующим используемому в исходной сессии для предоставляемого состояния (ключ или хеш-значение присутствуют в сохраненном названии, например), то C_SetOperationState завершится ошибкой CKR_KEY_CHANGED.

Необходимость предоставления дескриптора ключа для функции C_SetOperationState определяется состоянием флага CKF_RESTORE_KEY_NOT_NEEDED в поле флагов в структуре CK_TOKEN_INFO. Если флаг выставлен, то для вызова функции C_SetOperationState никогда не потребуется дескриптор ключа, если сброшен - по крайней мере в нескольких случаях будет необходимо предоставить дескриптор ключа функции C_SetOperationState, следовательно, вероятно, что приложение всегда будет предоставлять подходящий дескриптор ключа при восстановлении состояния криптографических операций в сессию.

C_SetOperationState может успешно восстановить состояние в текущую сессию, даже если сессия имеет активные криптографические операции или операции поиска объектов в момент вызова C_SetOperationState.

Функция C_SetOperationState поддерживается библиотекой rtPKCS11 начиная с версии 2.30.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_KEY_CHANGED,

CKR_KEY_NEEDED,

CKR_KEY_NOT_NEEDED,

CKR_SAVED_STATE_INVALID,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID.

Расширенные коды ошибок

Пример

CK_SESSION_HANDLE hSession;
CK_MECHANISM digestMechanism;
CK_ULONG ulStateLen;
CK_BYTE data1[] = {0x01, 0x03, 0x05, 0x07};
CK_BYTE data2[] = {0x02, 0x04, 0x08};
CK_BYTE data3[] = {0x10, 0x0F, 0x0E, 0x0D, 0x0C};
CK_BYTE pDigest[20];
CK_ULONG ulDigestLen;
CK_RV rv;

.
.
/* Инициализация операции хеширования */
rv = C_DigestInit(hSession, &digestMechanism);
assert(rv == CKR_OK);

/* Начало хеширования */
rv = C_DigestUpdate(hSession, data1, sizeof(data1));
assert(rv == CKR_OK);

/* Определение длины состояния криптографических функций */
rv = C_GetOperationState(hSession, NULL_PTR, &ulStateLen);
assert(rv == CKR_OK);

/* Назначение памяти и получение состояния */
pState = (CK_BYTE_PTR) malloc(ulStateLen);
rv = C_GetOperationState(hSession, pState, &ulStateLen);

/* Продолжение хеширования */
rv = C_DigestUpdate(hSession, data2, sizeof(data2));
assert(rv == CKR_OK);

/* Восстановление состояния. Дескрипторы ключей не нужны */
rv = C_SetOperationState(hSession, pState, ulStateLen, 0, 0);
assert(rv == CKR_OK);

/* Продолжение хеширования с сохраненного момента */
rv = C_DigestUpdate(hSession, data3, sizeof(data3));
assert(rv == CKR_OK);

/* Завершение хеширования */
ulDigestLen = sizeof(pDigest);
rv = C_DigestFinal(hSession, pDigest, &ulDigestLen);
if (rv == CKR_OK) {
	/* pDigest[] сейчас содержит хеш-значение 0x01030507100F0E0D0C */
.
.
}

к содержанию ↑

C_Login()

CK_DEFINE_FUNCTION(CK_RV, C_Login)(
	CK_SESSION_HANDLE hSession,
	CK_USER_TYPE userType,
	CK_UTF8CHAR_PTR pPin,
	CK_ULONG ulPinLen
);

Назначение

Функция авторизует пользователя на токене.

После успешной авторизации пользователя типа CKU_SO или CKU_USER все сессии приложения примут состояние R/W SO Functions или R/W User Functions или R/O User Functions. Если тип пользователя CKU_CONTEXT_SPECIFIC, то поведение функции зависит от контекста. Неправильное использование этого типа пользователя приведет к возврату значения CKR_OPERATION_NOT_INITIALIZED.

Если сессия приложения имеет активные криптографические операции или операции поиска объектов, и вызванная этим приложениям функция C_Login завершается успешно, то эти операции могут как остаться активными, так и нет. Поэтому перед вызовом функции любые активные операции должны быть завершены.

Если приложение, вызывающее C_Login, имеет открытую сессию "только для чтения" с токеном, то авторизация Администратора токена в сессии невозможна. Попытка это сделать завершится ошибкой CKR_SESSION_READ_ONLY_EXISTS.

Функция C_Login может вызываться неоднократно, без вызова функции C_Logout в промежутках, только (и если только) существует ключ с атрибутом CKA_ALWAYS_AUTHENTICATE равным CK_TRUE, и пользователю необходимо выполнить криптографические операции с его использованием.

 

Обработка входных параметров функции происходит следующим образом.

 

  1. Если ulPinLen != 0 и pPin != NULL_PTR, то проверяется длина PIN-кода. Если длина не является допустимой, то возвращается значение CKR_ARGUMENTS_BAD. Если длина удовлетворяет условиям проверки, то проверяются права доступа для пользователя с идентификатором userType.
  2. Если ulPinLen != 0 и pPin == NULL_PTR, то возвращается ошибка CKR_ARGUMENTS_BAD.
  3. Если ulPinLen == 0 и pPin != NULL_PTR, то возвращается ошибка CKR_ARGUMENTS_BAD.
  4. Если ulPinLen == 0 и pPin == NULL_PTR, то возвращается ошибка CKR_ARGUMENTS_BAD.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_CANCELED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_OPERATION_NOT_INITIALIZED,

CKR_PIN_INCORRECT,

CKR_PIN_LOCKED,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID,

CKR_SESSION_READ_ONLY_EXISTS,

CKR_USER_ALREADY_LOGGED_IN,

CKR_USER_ANOTHER_ALREADY_LOGGED_IN,

CKR_USER_PIN_NOT_INITIALIZED,

CKR_USER_TOO_MANY_TYPES,

CKR_USER_TYPE_INVALID.

Расширенные коды ошибок

Пример

CK_SESSION_HANDLE hSession;
CK_UTF8CHAR userPIN[] = {"MyPIN"};
CK_RV rv;

rv = C_Login(hSession, CKU_USER, userPIN, sizeof(userPIN)-1);
if (rv == CKR_OK) { 
	.
	.
	rv == C_Logout(hSession);
	if (rv == CKR_OK) {
		.
		.
	}
}

к содержанию ↑

C_Logout()

CK_DEFINE_FUNCTION(CK_RV, C_Logout)(
	CK_SESSION_HANDLE hSession
);

Назначение

Функция завершает авторизацию пользователя на токене.

В зависимости от текущего типа пользователя, если вызов функции завершится успешно, каждая из сессий перейдет в состояние "R/W Public Session" или “R/O Public Session”.

После успешного завершения функции дескрипторы закрытых объектов становятся некорректными (даже если позднее пользователь зарегистрируется на токене, эти дескрипторы останутся некорректными). Кроме того, все закрытые объекты сессии, принадлежащей приложению, будут уничтожены.

Если сессия приложения имеет активные криптографические операции или операции поиска объектов, и вызванная этим приложениям функция C_Logout завершается успешно, то эти операции могут как остаться активными, так и нет. Поэтому перед вызовом функции любые активные операции должны быть завершены.

Возвращаемые значения

CKR_OK – функция выполнена успешно.

Стандартные коды ошибок:

CKR_ARGUMENTS_BAD,

CKR_CRYPTOKI_NOT_INITIALIZED,

CKR_DEVICE_ERROR,

CKR_DEVICE_MEMORY,

CKR_DEVICE_REMOVED,

CKR_FUNCTION_FAILED,

CKR_GENERAL_ERROR,

CKR_HOST_MEMORY,

CKR_SESSION_CLOSED,

CKR_SESSION_HANDLE_INVALID,

CKR_USER_NOT_LOGGED_IN.

Расширенные коды ошибок

Пример

CK_SESSION_HANDLE hSession;
CK_UTF8CHAR userPIN[] = {"MyPIN"};
CK_RV rv;

rv = C_Login(hSession, CKU_USER, userPIN, sizeof(userPIN)-1);
if (rv == CKR_OK) { 
	.
	.
	rv == C_Logout(hSession);
	if (rv == CKR_OK) {
		.
		.
	}
}

к содержанию ↑