Включение и определение режима HID

Здравствуйте.

Наш продукт использует ключи Guardant Sign, которые умеют работать в режиме HID.
Для предпродажной подготовки ключей используется собственный софт для прошивки памяти ключа.

С переводом в режим HID я разобрался, надо вызывать GrdProtect с параметром dwGlobalFlags=GrdGF_HID.

Не понятно, как и когда использовать функцию GrdSetDriverMode.
У меня всегда выдает ошибку 1 GrdE_DongleNotFound.
В примерах из SDK нигде не вызывается.
Проблема в том, что ключ Sign, а не Code? Хотелось бы пояснений на этот счет.

Второй вопрос по определению текущего режима ключа Guardant driver/HID.
Утилита grddiag.exe показывает "Глобальные флаги HID".
Как мне программно считать глобальные флаги?
В адресах GrdSAM_... или GrdUAM_... для GrdRead ничего похожего не нашел.

Если я руками в grdutil.exe переключаю Driver/HID в панели инструментов, то вижу, что в .nsd-файле меняется 4 байта со смещением 4 в Data. Как мне в runtime поймать это отличие в памяти ключа?

Re: Включение и определение режима HID

Добрый день.

burlak пишет:

Проблема в том, что ключ Sign, а не Code? Хотелось бы пояснений на этот счет.

Да, все верно. Эта функция работает только с ключами Guardant Code. Более подробно о ней можно узнать на портале документации - GrdSetDriverMode.

burlak пишет:

Как мне программно считать глобальные флаги?

Попробуйте использовать - структуру TGrdFindInfo. Она должна читать поле с глобальными флагами.

typedef struct {
   DWORD   dwPublicCode;           // Общий код доступа в числовом виде
   BYTE    byHrwVersion;           // Аппаратная версия ключа (биты 0 -3: minor, биты 4 - 7: major)
   BYTE    byMaxNetRes;            // Максимальный ресурс лицензий сетевого ключа (программируется компанией "Актив" при продаже ключа)
   WORD    wType;                  // Флаги типа ключа
   DWORD   dwID;                   // ID ключа (программируется компанией "Актив" при продаже ключа)// Соответствующие поля доступны из UAM режима
   BYTE    byNProg;                // Номер программы
   BYTE    byVer;                  // Версия программы
   WORD    wSN;                    // Серийный номер
   WORD    wMask;                  // Битовая маска
   WORD    wGP;                    // Счетчик запусков GP (устаревшая технология, не используется)
   WORD    wRealNetRes;            // Текущий ресурс лицензий сетевого ключа. Задается разработчиком, должен быть <= byMaxNetRes
   DWORD   dwIndex;                // Индекс, используемый утилитами удаленного программирования
   BYTE    abyReservedISEE[0x1C];  // Зарезервированная память для будущего использования
   WORD    wWriteProtectS3;        // SAM-адрес 1-го байта, доступного для записи. Если 0, запреты на запись отсутствуют.
   WORD    wReadProtectS3;         // SAM-адрес 1-го байта, доступного для чтения. Если 0, запреты на чтение отсутствуют.
  WORD    wGlobalFlags;           // Глобальные флаги
   DWORD   dwDongleState;          // Состояние ключа.см.GrdDSF_XXX определение // В наличии с: // 1. Stealth Sign.(Номер прошивки >= 0x01000011h or 01.00.00.11)// 2. Guardant Code.
   DWORD   dwOldMPNum;             // Старый номер прошивки (перед SFU).
   BYTE    abyReservedH[0x100 - 0x1A - 0x1C - 0x0E]; // Зарезервированная память для будущего использования
   DWORD   dwGrDrv_Platform;       // Разрядность драйвера.Платформа (Win32/Win64).
   DWORD   dwGrDrv_Vers;           // Версия драйвера(0х05401234=5.40.12.34)
   DWORD   dwGrDrv_Build;          // Сборка драйвера
   DWORD   dwGrDrv_Reserved;       // Зарезервированое значение
   DWORD   dwRkmUserAddr;          // Адрес начала пользовательской памяти в 2-х байтовых словах
   DWORD   dwRkmAlgoAddrW;         // Адрес таблицы размещения защищенных ячеек в словах
   DWORD   dwPrnPort;              // Адрес LPT-порта (или 0, если ключ - USB)
   DWORD   dwClientVersion;        // Зарезервированная версия клиента ключа // SAP start
   DWORD   dwRFlags;               // Зарезервировано. Тип MCU
   DWORD   dwRProgVer;             // Версия микропрограммы (в MCU)
   DWORD   dwRcn_rc;               // Зарезервированный текущий номер и код ответа
   DWORD   dwNcmps;                // Зарезервированный номер условий сравнения
   DWORD   dwNSKClientVersion;     // Зарезервированная версия клиента (low byte - minor, hi - major)
   DWORD   dwModel;                // Модель ключа
   DWORD   dwMcuType;              // Тип ключа MCU
   DWORD   dwMemoryType;           // Тип памяти ключа  // Зарезервировано для будущего использования
   BYTE    abyReserved[0x200 - 0x100 - 0x28]; // Зарезервированная память для будущего использования.
} TGrdFindInfo;

Re: Включение и определение режима HID

Спасибо за ответ.

Эта функция работает только с ключами Guardant Code. Более подробно о ней можно узнать на портале документации - GrdSetDriverMode.

Все-таки у меня не складывается полная картина.
Функция GrdSetDriverMode позволяет переключать режим из клиентской программы в рантайм?
Или она изменяет глобальные флаги при прошивке ключа между вызовами GrdInit и GrdProtect?
Флаги указываемые в GrdProtect - это начальное значение или что?

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

А пока остались вопросы по модели Sign.
Как я понял, поддержка HID фиксируется в момент вызова GrdProtect с флагом GrdGF_HID или без него.
При полной прошивке ключа с вызовом GrdInit и последующим формированием памяти ключа все ок.
Т.е. для вновь продаваемых ключей мы научились на выбор делать их с глобальными флагами GrdGF_HID или 0.

Остается проблема с ключами Sign, которые уже находятся на руках у пользователей.
Многие обновляют компьютеры, с включенным модулем TPM драйверы Guardant не работают.
Включение удаленно поддержки HID для таких пользователей - актуальная проблема.
У нас есть собственный механизм удаленной ограниченной записи в ключ на стороне пользователя.
Т.е. потенциально есть возможность указать другое значение глобальных флагов при вызове GrdProtect.

Эксперименты с вызовом GrdProtect без предшествующего GrdInit показали, что флаг GrdGF_HID включается, но указание флагов 0 не отключает HID. Т.е. получается только одностороннее включение HID без возможности отката.
Смысл отказа от вызова GrdInit - не сбрасывать всю память ключа, на стороне пользователя нет возможности сделать полноценную прошивку.

В примере из SDK demo.cpp я добавил такой код:

/*
    printf("Init: ");
    nRet = grdDongle.Init();
    ErrorHandling(nRet);
    */

    uint32_t dwWrProt = 3952;
    uint32_t dwRdProt = 3952;
    uint32_t dwNumFunc = 40;
    uint32_t dwTableLMS = 0;
    uint32_t dwGlobalFlags = 0/*GrdGF_HID*/;

    printf("Protect: ");
    nRet = grdDongle.Protect(dwWrProt, dwRdProt, dwNumFunc, dwTableLMS, dwGlobalFlags);
    ErrorHandling(nRet);

Если раскоментировать dwGlobalFlags = GrdGF_HID, то ключ переводится в режим HID без вызова Init.
А вот когда dwGlobalFlags = 0, то глобальные флаги не обнуляются.
Если добавить вызов Init, то флаги и устанавливаются, и обнуляются, но при этом сбрасывается вся остальная память ключа (чего хотелось бы избежать).

Может я чего-то не понимаю на базовом уровне?
Вызов Protect с флагами dwGlobalFlags = 0 проходит без ошибки, но результат контринтуитивен...

Re: Включение и определение режима HID

Функция GrdSetDriverMode позволяет переключать режим из клиентской программы в рантайм?

Да, верно. Функция GrdSetDriverMode предназначена именно для программного переключения режима работы ключа (между драйверным и HID-режимом) из клиентского приложения в реальном времени. Эта функция работает только с ключами Guardant Code.

Флаги, указываемые в GrdProtect — это начальное значение или что?

Параметр dwGlobalFlags в функции GrdProtect — это финальное значение глобальных флагов, которое будет установлено в ключе в момент этого вызова. Это не начальное, а итоговое состояние.

...использование GrdProtect без GrdInit...

Вы правы в своем техническом анализе. Подробное описание функции можно найти у нас на портале документации - https://dev.guardant.ru/display/DOC/GrdProtect. GrdProtect используется на завершающем этапе реорганизации памяти ключа.
Этот процесс включает:

GrdInit — полная инициализация (сброс) памяти ключа.

Запись всех необходимых данных (таблиц, алгоритмов, ячеек).

GrdProtect — финализация конфигурации, установка защит и глобальных флагов.

Поэтому вызов GrdProtect без предварительного GrdInit является некорректным с точки зрения предназначения API.

Re: Включение и определение режима HID

Параметр dwGlobalFlags в функции GrdProtect — это финальное значение глобальных флагов, которое будет установлено в ключе в момент этого вызова. Это не начальное, а итоговое состояние.

В контексте того, что прошивка (и вызов GrdProtect) происходят перед передачей ключа конечному пользователю, а потом глобальные флаги могут быть изменены вызовом GrdSetDriverMode, то это, так сказать, значение по умолчанию получается.
Клиентское приложение может какие-то свои настройки считать и вызвать GrdSetDriverMode для переопределения режима HID, заданного при предпродажной прошивке ключа. Верно?

Поэтому вызов GrdProtect без предварительного GrdInit является некорректным с точки зрения предназначения API.

Увы, я понимаю, что это так.
Но для ключей Sign приходится выбирать - шашечки или ехать.
Однонаправленное включение режима HID на практике работает.

Re: Включение и определение режима HID

Вдогонку.

Подробное описание функции можно найти у нас на портале документации - https://dev.guardant.ru/display/DOC/GrdProtect.

Что-то я в подробном описании не нашел описания параметров для Guardant Code...

Интересно было бы узнать, какие значения для dwGlobalFlags поддерживаются и как согласуются с последующими вызовами GrdSetDriverMode.

Re: Включение и определение режима HID

1. О работе функции GrdSetDriverMode
Вы правильно поняли: функция GrdSetDriverMode действительно предназначена для программного переключения режима работы ключа (между драйверным и HID-режимом) из клиентского приложения в реальном времени. Однако, как мы уже упоминали, эта функция поддерживается только ключами Guardant Code.

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

2. О параметрах функции GrdSetDriverMode
Вот основные параметры функции GrdSetDriverMode:

int GrdSetDriverMode(
  HANDLE hGrd,
  DWORD dwMode,
  void *pReserved
);

Описание параметров:

hGrd — хэндл, через который выполняется операция.

dwMode — флаг, устанавливающий USB-режим использования ключей Guardant Code/Code Time:

GrdDM_GRD_DRV (0) — Guardant driver;

GrdDM_USB_HID (1) — HID driver;

GrdDM_WINUSB (2) — WINUSB driver.

pReserved — зарезервировано.

3. О значениях dwGlobalFlags
Параметр dwGlobalFlags в функции GrdProtect определяет финальное состояние глобальных флагов ключа после выполнения операции. Вот поддерживаемые флаги:

  • GrdGF_ProtectTime = 1 (блокировка вызова GrdSetTime)

  • GrdGF_HID = 2 (ключ работает в HID-режиме)

  • GrdGF_OnlyOneSessKey = 4 (единственный сессионный ключ для Guardant API)

  • GrdGF_2ndSessKey = 8 (единственный сессионный ключ для автозащиты)

4. Дополнительные ресурсы
Для более глубокого изучения API Guardant рекомендуем обратиться к нашему порталу документации:

GrdSetDriverMode

GrdProtect