Конференция "WinAPI" » самописный CSP [WinXP]
 
  • василий иванович (15.06.09 14:49) [0]
    Реализую собственный криптопровайдер для тестовых целей(так надо)
    Написал DLL, реализовал все функции CP*** из этого списка http://msdn.microsoft.com/en-us/library/aa382022(VS.85).aspx

    Затем пропатчил advapi32.dll, подписал длл и зарегистрировал все в реестре.

    В тестовом приложении вызываю CryptAcquireContext для моего провайдера.
    После этого я вижу (по текстовому логу), что криптоапи загрузило мою длл и вызвало из нее CPAcquireContext
    внутри CPAcquireContext я вижу правильные значения всех инпут параметров, которые передаю из тестового приложения.
    Проблема:
    Значение, присваиваемое вар-параметру hProv не возвращается наружу (в хост-приложение)
    Причем похоже на то, что криптоапи само затирает это значение (я его перед вызовом CryptAcquireContext устанавливаю в некое отличное от нуля значение)

    Т.е внутрь длл оно приходит уже как нулевое, я его изменяю на другое, отличное от нуля, но в хост-приложение оно не попадает.

    Чего я еще не учел?
  • KSergey © (15.06.09 15:01) [1]
    Может беда в банальном неправильно описанном интерфейсе? как описана CPAcquireContext в дельфи?
  • василий иванович (15.06.09 15:07) [2]
    Перепробовал несколько вариантов
    вот два последних

    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;
  • Сергей М. © (15.06.09 15:12) [3]

    > изменяю на другое, отличное от нуля, но в хост-приложение
    > оно не попадает


    Покажи соотв.фрагмент тестового хост-приложения..
  • василий иванович (15.06.09 15:17) [4]
    Вот вызов:

    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 - тип моего фэйкового провайдера

    Внутри самого провайдера я все эти параметры получаю благополучно.
  • Сергей М. © (15.06.09 16:19) [5]
    hProv - это у тебя локальная переменная или статическая ?
  • василий иванович (15.06.09 17:20) [6]
    Это локальная переменная обработчика OnButton1Click.
    Все происходит в нем.
  • Сергей М. © (15.06.09 17:56) [7]
    Тогда утверждение

    > внутрь длл оно приходит уже как нулевое

    не обязано соответствовать действительности.

    Явно эту переменную перед передачей параметром вызова ты не инициализируешь, а содержимое ее не определено, ибо она в стеке.

    Вот если ты явно инициализируешь ее перед вызовом, например, "шахматами" ($5A5A5A5A), и получишь эти же самые  "шахматы" в своем провайдере, вот тогда можно утвершжать, что прямая передача факт.параметра осуществилась успешьно. Только после этого можно рассуждать, возвращает ли твой провайдер это самое тестовое 1234 и передает ли его КриптоАПИ назад без искажений
  • василий иванович (15.06.09 18:23) [8]
    на самом деле была и инициализация перед вызовом.
    но это уже просто от безысходности.
    Внутри провайдера я при этом читал ноль.

    А вообще инициализация hProv не требуется.
    Главная засада в том, что присвоенное вутри провайдера значение контекста не транслируется в вызывающий код.
  • Сергей М. © (15.06.09 18:30) [9]

    > на самом деле была и инициализация перед вызовом
    > но ..Внутри провайдера я при этом читал ноль


    Т.е. инициализировал заведомо не нулем, а получил ноль ?
    И адреса при этом совпадают ?
  • Сергей М. © (15.06.09 18:32) [10]

    > пропатчил advapi32.dll


    Кстати, есть смутные подозрения, а не напортачил ли ты чего с этим "патчем"..
  • василий иванович (15.06.09 23:52) [11]
    Адреса параметров перед вызовом и внутри длл не совпадают.
    Но это ничего нам не дает.
    Приложение вызывает CryptAcquireContext
    А далее уже криптоапи вызывает CPAcquireContext.

    И как именно там криптоапи обходится с вар-параметром нам неизвестно.
    Она может использовать свой аргумент для передачи в CPAcquireContext и копировать его значение в аргумент переданный ей самой в CryptAcquireContext.

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

    пропатченные версии своих длл публикует сама ms в своем csp sdk
  • Сергей М. © (16.06.09 09:47) [12]
    Ну пока у меня остается только одно предположение - КриптоАПИ рассматривает возвращенное тобой значение как инвалидный хэндл ..
  • Сергей М. © (16.06.09 10:00) [13]
    http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2004-10/0287.html

    Попробуй так:

    function CPAcquireContext(AProv : PHCRYPTPROV; PContainer : PChar; Flags : DWORD; VTable : PVTableProvStruc) : boolean; stdcall;
    begin
     AProv^ := SysGetMem(4); //возвращаемый хэндл контекста - валидный указатель на некий блок данных, содержащих запрашиваемый контекст
     Result := True;
    end;

  • василий иванович (16.06.09 11:34) [14]
    Пробовал и так, с той разницей, что создавал экземпляр 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;
  • Сергей М. © (16.06.09 12:14) [15]

    > потом вдруг меня осенило


    А что принципиально изменилось ?

    if Result then AProv := h;

    На месте h с тем же "успехом" ты писал и 1234)..
  • василий иванович (16.06.09 12:22) [16]
    Принципально конечно ничего не изменилось.
    За исключением того, что контекст (ненулевой) теперь возвращается в тестовое приложение.

    Раньше же когда в тестовом проекте я вызывал последовательно CryptAcquire CryptReleaseContext, то криптоапи даже не дергало мою реализацию CPReleaseContext (упроавление туда просто не передавалось)

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

    В общем механизма все же завелась и поехала.
    Спасибо за участие.

    :)
 
Конференция "WinAPI" » самописный CSP [WinXP]
Есть новые Нет новых   [134434   +28][b:0][p:0.001]