Краткие теоретические сведения. API-интерфейс системы HASP SRM представляет собой мощное средство для защиты программного обеспечения
API-интерфейс системы HASP SRM представляет собой мощное средство для защиты программного обеспечения. Уровень защиты всецело зависит от объема используемых функций. Соответственно, чем более сложной будет структура защиты, тем надежнее она будет. Перед тем как приступать к практике, рекомендуется внимательно ознакомиться с функционалом HASP SRM Run-time API. Для защиты приложения с помощью HASP SRM API в исходный код защищаемого приложения следует вставить вызовы ключа HASP SRM. Можно вставить проверки наличия ключа в любое место приложения, а также определить его реакцию в зависимости от полученного ответа. Если требуемый ключ не обнаружен, приложение может прекратить работу или перейти в демонстрационный режим. HASP SRM API позволяет контролировать наличие ключа и определенные данные в его памяти, а также осуществлять шифрование и дешифрование данных. Все API-функции HASP SRM условно разделяются на пять категорий: • сессионные функции; • функции памяти; • функции шифрования; • функции времени; • функции управления.
Сессионные функции
Для выполнения большинства API-функций HASP SRM необходимо предварительно выполнить вызов login и получить, таким образом, доступ к лицензии, хранящейся на определенном аппаратном ключе. Каждый вызов login должен сопровождаться по окончании сеанса вызовом logout. Все остальные функции выполняются только в рамках установленного сеанса.
Функции шифрования
После успешного соединения с ключом HASP SRM становятся доступными функции шифрования данных в буфере данных с помощью встроенного крипто-процессора, использующего симметричное шифрование, которое предусматривает использование одного ключа, как для шифрования, так и для дешифрования.
Функции памяти
HASP SRM API может применяться для: • чтение данных из буфера в памяти ключа HASP SRM; • запись данных в буфер в памяти ключа HASP SRM. Размер буфера данных ограничивается размером памяти используемой модели ключа. Рекомендуется использовать память аппаратного ключа для хранения информации, которая может использоваться для проверки и идентификации конечного пользователя, а также задействовать память для хранения данных, используемых приложением во время его работы. Доступ к этой конфиденциальной информации является частью общей схемы защиты.
Функции времени
Ключи HASP HL Time или HASP HL NetTime имеют встроенные таймеры, которые также управляются посредством API-функций HASP SRM. Например, можно считывать и изменять время. В числе API-функций HASP SRM есть две, которые позволяют преобразовывать значения даты и времени.
Функции управления
В состав HASP SRM API входят две функции, возвращающие данные о системных компонентах, текущем сеансе, ключе HASP SRM и дополнениях к лицензии. В частном случае эти функции могут использоваться для установки обновлений. Для этого не обязательно иметь открытый сеанс.
Рассмотрим некоторые функции подробней:
· function hasp_login (feature_id: hasp_feature_t; vendor_code: hasp_vendor_code_t; var handle: hasp_handle_t): hasp_status_t; stdcall; Входные параметры: feature_id - уникальный идентификатор feature, vendor_code - указатель на секретный код ключа handle - указатель на сеанс
Возвращаемые значения:
· function hasp_logout (handle: hasp_handle_t): hasp_status_t; stdcall; Входные параметры: handle - указатель на сеанс Возвращаемые значения:
· function hasp_write (handle: hasp_handle_t; fileid: hasp_fileid_t; offset: hasp_size_t; length: hasp_size_t; var buffer): hasp_status_t; stdcall; Входные параметры: handle - указатель на сеанс fileid - идентификатор файла для записи offset - сдвиг в файле length - длина записи buffer - записываемые данные Возвращаемые значения:
· function hasp_read(handle: hasp_handle_t; fileid: hasp_fileid_t; offset: hasp_size_t; length: hasp_size_t; var buffer): hasp_status_t; stdcall;
Входные параметры: handle - указатель на сеанс fileid - идентификатор файла для записи offset - сдвиг в файле length - длина записи buffer - считываемые данные
Возвращаемые значения:
Описание остальных функций HASP API можно найти в каталоге: C: \Users\< Имя пользователя> Documents\Aladdin\Sentinel HASP 5.10\Samples\Runtime\Delphi в файле hasp_unit.pas. 1. До написания кода программы, необходимо выполнить следующие подготовительные действия: · из папки C: \Users\< Имя пользователя> \Documents\Aladdin\Sentinel HASP 5.10\API\Runtime\Delphi скопировать файлы hasp_unit.pas и hasp_windows_delphi_< серия ключа>.obj, где серия ключа – пятизначное число, например 81718, в папку с будущей программой; · в файле hasp_unit.pas найти строку {$L hasp_windows_delphi_demo.obj} и заменить ее на {$L hasp_windows_delphi_< серия ключа>.obj }; · из папки C: \Users\< Имя пользователя> \Documents\Aladdin\Sentinel HASP 5.10\Samples\Runtime\Delphi скопировать файл hasp_vcode.inc в папку с будущей программой. В этом файле содержится секретный код ключа DEMOMA (ключ демонстрационной серии). Необходимо открыть файл и заменить код на код используемого ключа (например, для ключей серии разработчика CRAXZ, ключ содержится в файле CRAXZ.hvc в каталоге C: \Users\< Имя пользователя> \Documents\Aladdin\Sentinel HASP 5.10\VendorCodes).
Рисунок 48 – макет пользовательского интерфейса программы
2. После подключения дополнительных файлов можно приступать к разработке программы. Программа выполняет следующие действия: · проверяет доступность ключа HASP HL; · при успешной проверке вычисляет определенный интеграл функции на заданном интервале; · генерирует последовательность чисел Фибоначчи и записывает/считывает их из памяти ключа. 3.На этом шаге создается в папке с программой проект Borland Delphi, размещаются на форме программы необходимые элементы, как показано на рис. 48. 4. После этого создаются процедуры procedure TForm1.FormCreate(Sender: TObject) и procedure TForm1.Button1Click(Sender: TObject). 5. Текст программного модуля unit1.pas: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, hasp_unit; type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; Edit2: TEdit; Memo1: TMemo; Edit3: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Edit4: TEdit; Label4: TLabel; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; const AES_MIN_DATA_LEN = 16; {минимальная длина данных для AES шифрования} MAX_MEMORY = 128; {Макс. размер памяти, который будет обрабатываться} CUSTOM_FEATURE = 42; DEMO_MEMBUFFER_SIZE = 8; SCOPE_VIEW_MAXSIZE = (1024 * 128); var Form1: TForm1; a, b, s, s1, d, e, raz, m: real; n, i, x: integer; data: array[0..16] of byte = ($74, $65, $73, $74, $20, $73, $74, $72, $69, $6e, $67, $20, $31, $32, $33, $34, 0); membuffer: array [0..DEMO_MEMBUFFER_SIZE] of byte; datalen: hasp_size_t; implementation {$R *.dfm} {$I hasp_vcode.inc } function f(x, m: real): real; begin f: =x*x; end; procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Clear(); end; procedure TForm1.Button1Click(Sender: TObject); const SCOPE_VIEW_MAXSIZE = (1024 * 128); var status: hasp_status_t; handle: hasp_handle_t; handle2: hasp_handle_t; fsize: hasp_size_t; time: hasp_time_t; info: pchar; feature: integer; day, month, year, hour, minute, second: cardinal; scope: Array[0..SCOPE_VIEW_MAXSIZE-1] of char; view: Array[0..SCOPE_VIEW_MAXSIZE-1] of char; begin Memo1.Clear(); feature: = 50; status: = hasp_login(feature, @vendor_code[1], handle); if status = HASP_STATUS_OK then begin Memo1.Lines.Add('Проверка завершена успешно'); raz: =100; e: =StrToFloat(Edit4.Text); n: =100; s1: =0; s: =200; a: =StrToFloat(Edit1.Text); b: =StrToFloat(Edit2.Text); m: =b-1; d: =(b-a)/n; while raz> e do begin for i: =0 to n do S1: =S1+d*(F(a + I*d, m) + F(a + (I+1)*d, m))/2; raz: =abs(s-s1); s: =s1; s1: =0; Memo1.Lines.Add(FloatToStr(s)); n: =n*2; d: =(b-a)/n; end; Edit3.Text: =FloatToStr(s); end else if status = HASP_FEATURE_NOT_FOUND then Showmessage('Невозможно подключиться к feature') else if status = HASP_CONTAINER_NOT_FOUND then Showmessage('HASP ключ с данным кодом не найден') else if status = HASP_OLD_DRIVER then Showmessage('Устаревшая версия драйвера аппаратного ключа защиты') else if status = HASP_NO_DRIVER then Showmessage('Драйвер ключа не установлен') else if status = HASP_INV_VCODE then Showmessage('Ошибка в коде ключа') else Showmessage('Подключение к feature' + IntToStr(feature) + 'закончилось неудачей, статус' + IntToStr(status)); n: =1; x: =0; for i: =1 to DEMO_MEMBUFFER_SIZE do begin membuffer[i]: =x; x: =x+n; n: =membuffer[i]; end; status: = hasp_write(handle, HASP_FILEID_RW, 0, fsize, membuffer); status: = hasp_read(handle, HASP_FILEID_RW, 0, fsize, membuffer); case status of HASP_STATUS_OK: begin Memo1.Lines.Add('Чтение памяти выполнено успешно'); for i: =1 to DEMO_MEMBUFFER_SIZE do Memo1.Lines.Add(IntToStr(membuffer[i])); end; else begin Memo1.Lines.Add('Чтение памяти не было произведено'); end; end; status: = hasp_logout(handle); case status of HASP_STATUS_OK: begin Memo1.Lines.Add('Сеанс работы с ключом успешно завершен! '); end; else begin Memo1.Lines.Add('Сеанс не был открыт'); end; end; end; end.
6. На этом завершающем шаге необходимо скомпилировать программу и проверить ее работоспособность при подключенном и отсутствующем ключе HASP HL. Полученную информацию о работе с программой отразить в отчете о выполненной работе.
Контрольные вопросы 1. Что такое Sentinel HASP API? Какие возможности он предоставляет? 2. Как можно классифицировать функции Sentinel HASP API? 3. Перечислите вспомогательные файлы HASP API, необходимые для функционирования защиты? 4. Возможно ли добавление в код программы функций различных категорий? 5. Где храниться идентификатор ключа HASP?
|