-
Реализую собственный криптопровайдер для тестовых целей(так надо) Написал DLL, реализовал все функции CP*** из этого списка http://msdn.microsoft.com/en-us/library/aa382022(VS.85).aspx Затем пропатчил advapi32.dll, подписал длл и зарегистрировал все в реестре. В тестовом приложении вызываю CryptAcquireContext для моего провайдера. После этого я вижу (по текстовому логу), что криптоапи загрузило мою длл и вызвало из нее CPAcquireContextвнутри CPAcquireContext я вижу правильные значения всех инпут параметров, которые передаю из тестового приложения. Проблема: Значение, присваиваемое вар-параметру hProv не возвращается наружу (в хост-приложение) Причем похоже на то, что криптоапи само затирает это значение (я его перед вызовом CryptAcquireContext устанавливаю в некое отличное от нуля значение) Т.е внутрь длл оно приходит уже как нулевое, я его изменяю на другое, отличное от нуля, но в хост-приложение оно не попадает. Чего я еще не учел?
-
Может беда в банальном неправильно описанном интерфейсе? как описана CPAcquireContext в дельфи?
-
Перепробовал несколько вариантов вот два последних
function CPAcquireContext(var AProv : HCRYPTPROV; PContainer : PChar; Flags : DWORD; VTable : PVTableProvStruc) : boolean; stdcall;
function CPAcquireContext(AProv : PHCRYPTPROV; PContainer : PChar; Flags : DWORD; VTable : PVTableProvStruc) : boolean; stdcall; begin Log('CPAcquireContext',Format('%s dwFlags : %d prov type %d',[PChar(PContainer),Flags,VTable.dwProvType])); AProv^ := 1234; Result := True; end;
-
> изменяю на другое, отличное от нуля, но в хост-приложение > оно не попадает
Покажи соотв.фрагмент тестового хост-приложения..
-
Вот вызов:
var hProv : HCRYPTPROV; begin if CryptAcquireContext(@hProv,'Вася','Fake CryptoProvider',100,0) then begin Edit1.Text := IntToStr(hProv); end else RaiseLastWin32Error;
Вот прототип : function CryptAcquireContextA(phProv :PHCRYPTPROV; pszContainer :PAnsiChar; pszProvider :PAnsiChar; dwProvType :DWORD; dwFlags :DWORD) :BOOL;stdcall;
'Вася' - имя контейнера 100 - тип моего фэйкового провайдера
Внутри самого провайдера я все эти параметры получаю благополучно.
-
hProv - это у тебя локальная переменная или статическая ?
-
Это локальная переменная обработчика OnButton1Click. Все происходит в нем.
-
Тогда утверждение
> внутрь длл оно приходит уже как нулевое
не обязано соответствовать действительности.
Явно эту переменную перед передачей параметром вызова ты не инициализируешь, а содержимое ее не определено, ибо она в стеке.
Вот если ты явно инициализируешь ее перед вызовом, например, "шахматами" ($5A5A5A5A), и получишь эти же самые "шахматы" в своем провайдере, вот тогда можно утвершжать, что прямая передача факт.параметра осуществилась успешьно. Только после этого можно рассуждать, возвращает ли твой провайдер это самое тестовое 1234 и передает ли его КриптоАПИ назад без искажений
-
на самом деле была и инициализация перед вызовом. но это уже просто от безысходности. Внутри провайдера я при этом читал ноль.
А вообще инициализация hProv не требуется. Главная засада в том, что присвоенное вутри провайдера значение контекста не транслируется в вызывающий код.
-
> на самом деле была и инициализация перед вызовом > но ..Внутри провайдера я при этом читал ноль
Т.е. инициализировал заведомо не нулем, а получил ноль ? И адреса при этом совпадают ?
-
> пропатчил advapi32.dll
Кстати, есть смутные подозрения, а не напортачил ли ты чего с этим "патчем"..
-
Адреса параметров перед вызовом и внутри длл не совпадают. Но это ничего нам не дает. Приложение вызывает CryptAcquireContext А далее уже криптоапи вызывает CPAcquireContext.
И как именно там криптоапи обходится с вар-параметром нам неизвестно. Она может использовать свой аргумент для передачи в CPAcquireContext и копировать его значение в аргумент переданный ей самой в CryptAcquireContext.
Патч библиотеки необходим для обхода проверки эцп нового криптопровайдера. Путей два: либо два компьютера и кернел дебуг режим, либо правка четырех байт самой библиотеки.
пропатченные версии своих длл публикует сама ms в своем csp sdk
-
Ну пока у меня остается только одно предположение - КриптоАПИ рассматривает возвращенное тобой значение как инвалидный хэндл ..
-
-
Пробовал и так, с той разницей, что создавал экземпляр TObject и возвращал его адрес. Не прокатывает. В том числе и с SysGetMem.
А потом вдруг меня осенило :)
function CPAcquireContext(var AProv : HCRYPTPROV; PContainer : PChar; Flags : DWORD; VTable : PVTableProvStruc) : boolean; stdcall; var h : HCRYPTPROV; begin Result := False; Log('CPAcquireContext',Format('%s dwFlags : %d prov type %d',[PChar(PContainer),Flags,VTable.dwProvType])); Result := CryptAcquireContext(@h,nil,nil,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT); if Result then AProv := h; end;
-
> потом вдруг меня осенило
А что принципиально изменилось ?
if Result then AProv := h;
На месте h с тем же "успехом" ты писал и 1234)..
-
Принципально конечно ничего не изменилось. За исключением того, что контекст (ненулевой) теперь возвращается в тестовое приложение.
Раньше же когда в тестовом проекте я вызывал последовательно CryptAcquire CryptReleaseContext, то криптоапи даже не дергало мою реализацию CPReleaseContext (упроавление туда просто не передавалось)
Теперь же я внутри своего ксп получаю "честный" контекст от любого первого попавшегося провайдера с типом PROV_RSA_FULL и криптоапи уже начинает "верить" в то, что мой фэйковый ксп возвращает валидный криптоконтекст.
В общем механизма все же завелась и поехала. Спасибо за участие.
:)
|