КриптоПро CSP  

Особенности использования интерфейса уровня ядра в Windows

Общее описание

Интерфейс "КриптоПро CSP 5.0" уровня ядра в Windows реализован в драйвере cpdrvlib.sys. Этот драйвер запускается при инициализации операционной системы (в последовательности SERVICE_SYSTEM_START).

Если функции вашего драйвера существенно зависят от интерфейса уровня ядра "КриптоПро CSP 5.0", вы можете задать вашему драйверу зависимость на загрузку от cpdrvlib.sys, чтобы обеспечить его запуск строго после запуска cpdrvlib.sys.

Для использования интерфейса уровня ядра "КриптоПро CSP 5.0" драйвер-клиент должен получить адреса точек входа. Это делается с помощью отправки запросов ввода/вывода к устройству драйвера с именем CPDRVLIB_NT_DEVICE_NAME. Необходимые коды IOCTL и имя устройства определены в файле cpdrvlib.h. Запрос ввода/вывода должен производиться с кодом IRP_MJ_INTERNAL_DEVICE_CONTROL. Точки входа, предоставляемые cpdrvlib.sys, и соответствующие им коды IOCTL представлены в таблице:

Точка входаКод IOCTL для получения адреса
CPCCreateProviderIOCTL_GETCPCCREATEPROVIDER
CPCGetDefaultConfigIOCTL_GETCPCGETDEFAULTCONFIG
CPCInitMemoryLFIOCTL_GETCPCINITMEMORYLF

Примечания

Адреса остальных функций интерфейса получаются путём вызова CPCCreateProvider.

Для отправки запроса ввода/вывода к устройству драйвера cpdrvlib.sys, драйвер-клиент должен получить указатель на это устройство, например, с помощью функции IoGetDeviceObjectPointer. Вызов этой функции увеличит счётчик ссылок на устройство драйвера cpdrvlib.sys, что предотвратит его отгрузку до закрытия соответствующего файла путём вызова ObDereferenceObject в драйвере-клиенте. Закройте этот файл только после того, как закончите работу с функциями интерфейса уровня ядра, т.к. в противном случае отгрузка драйвера cpdrvlib.sys приведёт к тому, что управление будет передано на неинициализированную страницу памяти или в неизвестный код.

В конфигурации по умолчанию используется максимальные возможности процессора (AVX/SSE3) (они используются при IRQL <= DISPATCH_LEVEL, для изменения функционирования или отключения используйте поля FuncStruct.UsedMask/UsesFunctions и др. в CPC_CONFIG_).

В конфигурации по умолчанию используется R/W блокировки ExAcquireResourceSharedLite/ExAcquireResourceSharedLite совместно с CriticalRegion, поэтому без флага CRYPT_NOSERIALIZE CSP может быть вызван только при IRQL <= APC_LEVEL. Для корректной работы память под объекты из MP_PRIME, MP_PRIME_M, MP_SEC_M должна выделяться в NonPagedPool. Если требуется работа на более высоких IRQL - задайте собственные callback-и синхронизации lockFuncs в CPC_CONFIG_, или, если работа c CSP осуществляется под внешними блокировками, отключите их путём присвоения нулевых указателей.

Пример получения адресов точек входа

Сначала необходимо получить указатель на устройство драйвера cpdrvlib.sys.

	    
 #include <ntddk.h>
 #include <cpdrvlib.h>
 #include <wincspc.h>

 UNICODE_STRING deviceNameUnicodeString;
 PDEVICE_OBJECT CPDevice;
 PFILE_OBJECT CPFile;

 RtlInitUnicodeString(&deviceNameUnicodeString, CPDRVLIB_NT_DEVICE_NAME);
 IoGetDeviceObjectPointer(&deviceNameUnicodeString, FILE_READ_DATA, &CPFile,
        &CPDevice);
	

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

	    
 KEVENT Event;
 IO_STATUS_BLOCK IoStatusBlock;
 PIRP pIrp;
 CPCCreateProvider_t *CreateProvider;

 KeInitializeEvent(&Event, NotificationEvent, FALSE);
 pIrp = IoBuildDeviceIoControlRequest(IOCTL_GETCPCCREATEPROVIDER,
        CPDevice, NULL, 0, &CreateProvider, sizeof(CreateProvider), TRUE,
        &Event, &IoStatusBlock);
 IoCallDriver(CPDevice, pIrp);