Возможно вы искали: 'Face-Plant Adventures'

May 15 2025 19:33:19
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96111483
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18357
• Обзор The Walking ... 18801
• Обзор DMC: Devil M... 19879
• Обзор на игру Valk... 15877
• Обзор на игру Stars! 17764
• Обзор на Far Cry 3 17948
• Обзор на Resident ... 16024
• Обзор на Chivalry:... 17508
• Обзор на игру Kerb... 17981
• Обзор игры 007: Fr... 16619
Превью о играх
• Превью к игре Comp... 17960
• Превью о игре Mage... 14464
• Превью Incredible ... 14721
• Превью Firefall 13479
• Превью Dead Space 3 16334
• Превью о игре SimC... 14730
• Превью к игре Fuse 15442
• Превью Red Orche... 15542
• Превью Gothic 3 16343
• Превью Black & W... 17354
Главная » Статьи » Разное » Разработка модуля Linux ядра, реализующего алгоритм криптозащиты ГОСТ 28147-89 (linux kernel module crypt gcc)

Разработка модуля Linux ядра, реализующего алгоритм криптозащиты ГОСТ 28147-89 (linux kernel module crypt gcc)

Ключевые слова: linux, kernel, module, crypt, gcc, (найти похожие документы)

From: Bob <ubob at mail.ru>
Newsgroups: email
Date: Fri, 2 Jul 2004 14:31:37 +0000 (UTC)
Subject: Разработка модуля Linux ядра, реализующего алгоритм криптозащиты ГОСТ 28147-89



РАЗРАБОТКА МОДУЛЯ ЯДРА ОПЕРАЦИОННОЙ СИСТЕМЫ LINUX, РЕАЛИЗУЮЩЕГО
АЛГОРИТМ КРИПТОГРАФИЧЕСКОЙ ЗАЩИТЫ ИНФОРМАЦИИ ГОСТ 28147-89


1. Введение
---------------------

Без использования криптографии сегодня немыслимо решение задач по обеспечению
безопасности информации, связанных с конфиденциальностью и целостностью,
аутентификацией и невозможностью отказа от авторства. Если до 1990 г.
криптография обеспечивала защиту исключительно государственных линий связи, то
в наши дни использование криптографических методов получило широкое
распространение благодаря развитию компьютерных сетей и электронного обмена
данными в различных областях: финансах, банковском деле, торговле и т.д.


2. Управление ключами
------------------------
Важнейшую роль в криптографии играет управление ключами. Это основа для
обеспечения конфиденциальности обмена информацией, идентификации и целостности
данных.

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

Для снижения риска компрометации конфиденциальности секретных ключей необходимо
ограничить круг лиц, у которых есть доступ к ключевой информации. Работать с
ключами должен специально подготовленный персонал, имеющий соответствующие
полномочия (допуск).

Исходя из этого требования, разработаем модель системы криптографической защиты
информации (СКЗИ), в которой доступ к ключам имеет только администратор системы.


3. Назначение, состав и алгоритм функционирования СКЗИ
----------------------------------------------------------------

Назначение СКЗИ - криптографическое преобразование (шифрование/расшифрование)
файлов пользователя в соответствии с алгоритмом ГОСТ 28147-89, режим
гаммирования. Описание стандарта ГОСТ 28147-89 можно взять здесь:
http://www.enlight.ru/crypto/articles/vinokurov/gost_i.htm

В состав СКЗИ входят следующие структурные элементы:
- криптографический драйвер (далее драйвер). Непосредственно
выполняет операцию криптографического преобразования информации в соответствии
с алгоритмом ГОСТ 28147-89. Содержит блок криптографического преобразования
(БКП) и блок хранения ключевой информации (БКИ);
- модуль ключевых данных (МКД). Выполняет генерацию ключевых данных и их
последующую запись в БКИ драйвера;
- модуль взаимодействия с драйвером (МВ). Представляет собой приложение
пользователя, и выполняет передачу драйверу информационных блоков, подлежащих
криптопреобразованию.


Алгоритм функционирования СКЗИ следующий:

- модуль МВ считывает из файла блок данных и вызывает системную функцию
sys_gost(), передав ей блок данных в качестве параметра. Но функция sys_gost()
никаких преобразований над данными не выполняет;

- драйвер после загрузки перехватывает системный вызов sys_gost(), и все обращения
МВ к функции sys_gost() будут обслуживаться драйвером. Если ключевые данные
не введены в БКИ, драйвер также не будет выполнять криптографических
преобразований, возвращая модулю МВ данные в неизмененном виде.
Только после того, как МКД выполнит генерацию ключевых данных и их запись в
БКИ драйвера, данные, передаваемые драйверу, будут поступать на вход БКП.

Сразу отметим, что операции загрузки драйвера и записи в него ключевых данных
являются привилегированными. Выполнить их может только администратор системы,
имеющий права root. Таким образом выполняется требование по ограничению доступа
персонала к ключевой информации.


4. Системный вызов sys_gost
------------------------------------
Как было сказано выше, в состав ядра Linux вводится новый системный вызов.
Методика добавления в ядро новых системных вызовов была рассмотрена здесь:
http://opennet.ru/base/dev/new_linux_syscall.txt.html

- добавляем запись о системном вызове sys_gost() в таблицу системных вызовов

sys_call_table (файл arch/i386/kernel/entry.S):

ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.
.
.
.long SYMBOL_NAME(sys_gost) /* sys_gost call 259 */

Системный вызов sys_gost() имеет порядковый номер 259 (ядро версии 2.4.26).

- в файл include/asm-i386/unistd.h добавляем запись:

#define __NR_gost 259

- в файл /usr/include/bits/syscall.h добавляем запись:

#define SYS_gost __NR_gost

- в файл fs/open.c добавим код, реализующий системный вызов sys_gost():

asmlinkage long sys_gost(unsigned char *block, size_t count, int mode)
{
return 0;
}

Системный вызов sys_gost принимает три параметра: указатель на блок с данными,
размер блока и флаг, информирующий о начале/завершении операции
криптопреобразования.

- в каталоге /usr/include создаем файл gost.h следующего содержания:

#include <sys/types.h>
#include <linux/unistd.h>

#define E_START 1
#define E_STOP 0

static inline _syscall3(int,gost,unsigned char *,block,size_t,count,int,mode)

E_START и E_STOP - флаги, информирующие о начале/завершении операции
криптографического преобразования.

После внесения всех изменений ядро необходимо перекомпилировать.


5. Реализация СКЗИ
----------------------

5.1. Драйвер

Задача драйвера - перехватить все обращения к системной функции sys_gost,
сохранить в БКИ ключевые данные, переданные модулем МКД, и приступить к
выполнению операций криптографического преобразования блоков данных, поступающих
от модуля МВ. Драйвер является символьным устройством. Создадим для него файл
устройства следующей командой:

mknod /dev/gost c 69 0

Адреса всех системных вызовов хранятся в специальной таблице - таблице
системных вызовов (далее ТСВ). Для обращения к той или иной системной функции
ядро извлекает адрес этой функции из ТСВ, и передает управление по этому
адресу.

Для перехвата обращений к системной функции sys_gost() драйверу необходимо в
ТСВ произвести замену адреса функции sys_gost адресом нового обработчика.
Чтобы выполнить эту операцию, драйвер должен знать адрес самой ТСВ. Т.к. все
системные вызовы выполняются через программное прерывание int 0x80, то адрес
таблицы можно извлечь из обработчика этого прерывания - функции system_call.
Определение функции system_call находится в файле arch/i386/kernel/entry.S.

Рассмотрим, как выполняется обращение к системной функции. В функции system_call
это выглядит следующим образом:

ENTRY(system_call)
.
.
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
.

В регистре EAX находится номер системного вызова. Управление передается по
адресу, который находится в ТСВ по смещению ([EAX] * 4) относительно базового
адреса таблицы sys_call_table, т.к. адрес каждого вызова занимает 4 байта.
Данный вызов равнозначен выражению на С:

/* вызов функции в массиве функций */
(sys_call_table[eax])()

Найдем опкод команды обращения к системной функции. Для этого загрузим ядро в
отладчик:

gdb -q /usr/src/linux/vmlinux

и дизассемблируем функцию system_call:

disas system_call

Ищем строку следующего содержания:

0xc0109008 <system_call + 44>: call *0xc0307b50(,%eax,4)

Это и есть обращение к системной функции. Базовый адрес ТСВ равен
0xc0307b50 (у вас числа, скорее всего, будут другие).

Вводим команду:

x/xw system_call + 44

Получаем:

0xc0109008 <system_call + 44>: 0x508514ff

Опкод команды обращения к системной функции равен xffx14x85. Следующие
4 байта являются адресом ТСВ:

x/xw system_call + 47
0xc010900b <system_call + 47>: 0xc0307b50

Таким образом, чтобы извлечь из функции system_call адрес ТСВ, достаточно найти
в теле функции сигнатуру xffx14x85. Следующие за ней 4 байта будут искомым
адресом таблицы.

Но для того, чтобы выполнить этот поиск, необходимо знать адрес самой функции
system_call. Эта задача решается просто: поскольку функция system_call
является обработчиком прерывания int 0x80, ее адрес находится в таблице
дескрипторов прерываний, Interrupt Descriptor Table (IDT). Адрес IDT хранит
специальный регистр IDTR, получить значение из которого можно при помощи
инструкции SIDT.

Алгоритм поиска адреса таблицы системных вызовов выглядит следующим образом:
- извлечь из регистра IDTR адрес таблицы IDT;
- из таблицы IDT извлечь адрес обработчика программного прерывания int 0x80.
Это будет адрес функции system_call;
- в теле функции system_call выполнить поиск сигнатуры xffx14x85 и считать
следующие за ней 4 байта - искомый адрес ТСВ.

Рассмотрим функцию, реализующую алгоритм поиска адреса ТСВ.


/*
* Листинг 1. Функция определения адреса таблицы системных вызовов
* (файл get_sct_addr.c)
*/

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>

#define SIGN "xffx14x85"
#define INT80_LEN 128

/* Структура дескриптора таблицы IDT */
struct descr_idt {
__u16 off_low; // младшие 16 бит адреса обработчика прерывания
__u16 sel;
__u8 none, flags;
__u16 off_high; // старшие 16 бит адреса обработчика прерывания
} __attribute__ ((packed)) idt;


/* Структура регистра IDTR */
struct {
__u16 limit;
__u32 base; // адрес таблицы IDT
} __attribute__ ((packed)) idtr;


__u32 get_sct_addr()
{
int i;
__u32 sct; // в этой переменной сохраним адрес таблицы
__u32 idt_addr = 0; // адрес таблицы IDT
__u32 sc_addr = 0; // адрес ф-ии system_call
__u8 sc[INT80_LEN]; // сюда скопируем первые 128 байт функции system_call
__u8 p[4]; // вспомогательный буфер

/*
* Определяем адрес таблицы дескрипторов прерываний IDT
*/
__asm__ ("sidt %0":"=m" (idtr));
idt_addr = idtr.base;

/*
* Считываем из IDT дескриптор обработчика int 0x80 - функции system_call
*/
memset((void *)&idt, 0, sizeof(struct descr_idt));
memcpy((void *)&idt, (void *)(idt_addr + 8 * 0x80), sizeof(struct descr_idt));

/*
* Из двух половинок - off_high и off_low - формируем адрес system_call
*/
sc_addr = (idt.off_high << 0x10) | idt.off_low;

/*
* Из функции system_call считываем первые 128 байт
*/
memset((void *)sc, 0, INT80_LEN);
memcpy((void *)sc, (void *)sc_addr, INT80_LEN);

/*
* Выполняем поиск сигнатуры xffx14x85
*/
for(i = 0; i < INT80_LEN; i++) {
memset((void *)p, 0, 4);
memcpy((void *)p, (void *)(sc + i * 4), 4);
if(!(memcmp((void *)p, SIGN, 3))) {
memcpy((void *)&sct, (void *)(sc + i * 4 + 3), 4);
break;
}
}

printk(KERN_INFO "sys_call_table address - 0x%08Xn", sct);

/*
* Возвращаем найденный адрес
*/
return sct;
}




Определим дополнительно заголовочный файл gost_var.h, в котором разместим
вспомогательные переменные и структуры, необходимые для реализации алгоритма
ГОСТ 28147-89. Файл имеет следующее содержание:


/*
* Листинг 2. Файл gost_var.h
*/

#include <linux/types.h>

#ifndef C1
#define C1 0x01010104
#endif

#ifndef C2
#define C2 0x01010101
#endif

__u32 SM1, SM2, N3, N4;

int key_enable; // флаг наличия ключевой информации в БКИ
int key_init; // флаг инициализации ключей

union {
struct {
__u32 N1;
__u32 N2;
} __attribute__ ((packed)) lg;
__u8 N[8];
} nac;

/*
* Структура для хранения ключевой информации, переданной модулем МКД.
* В соответствии с алгоритмом (см. п. 2), данная структура является БКИ
*/
struct key_info {
__u8 key_d[64];
__u32 X[8];
__u8 sp[8];
} keys;




Значения C1 и C2 определены ГОСТ 28147-89. Переменные SM1 и SM2, в соответствии
с терминологией ГОСТ, назовем сумматорами, а N1, N2, N3, N4 - накопителями.

Поиск адреса таблицы системных вызовов будет выполнен во время инициализации
драйвера. Рассмотрим следующий листинг:


/*
* Листинг 3. Функция инициализации драйвер и загрузки ключей в БКИ
* (файл sys_call_gost.c)
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <sys/syscall.h>
#include <asm/uaccess.h>
#include "gost_var.h"

#define GOST_MAJOR 69 // старший номер устройства

/*
* Прототипы функций поиска адреса ТСВ и нового обработчика системного
* вызова sys_gost
*/
__u32 get_sct_addr();
int new_gost(__u8 *, size_t, int);

__u32 old_sys_gost_addr = 0; // здесь сохраним старый адрес sys_gost
__u32 sct = 0; // адрес ТСВ


/*
* Функция записи в устройство. В процессе записи драйверу передается структура
* типа struct key_info (см. Листинг 2), содержащая ключевую информацию
*/
static ssize_t write_gost(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
if(count != sizeof(struct key_info)) return -EINVAL;
copy_from_user((char *)&keys, buf, count);

/*
* Устанавливаем флаг наличия ключевой информации в БКИ
*/
key_enable = 1;
return count;
}

/*
* Функция открытия файла устройства
*/
static int open_gost(struct inode *inode, struct file *file)
{
if(MOD_IN_USE) return -EBUSY;
if (MINOR(inode->i_rdev) != 0) return -ENODEV;

/*
* Проверяем режим открытия файла устройства. Файл должен быть
* открыт в режиме "Только для записи"
*/
if ((file->f_flags & O_ACCMODE) != O_WRONLY) return -EACCES;

memset(&keys, 0, sizeof(struct key_info));
key_enable = 0;

MOD_INC_USE_COUNT;
return 0;
}

/*
* Функция закрытия файла устройства. Ничего не выполняет,
* просто уменьшает счетчик использования драйвера
*/
static int close_gost(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}

struct file_operations gost_fops = {
write: write_gost,
open: open_gost,
release: close_gost,
};

/*
* Функция инициализация драйвера. Выполняет регистрацию устройства
* в системе и производит замену адресов в ТСВ
*/
static int __init init_gost()
{
if(register_chrdev(GOST_MAJOR, "/dev/gost", &gost_fops)) return -EIO;

/*
* Определяем адрес ТСВ и заменяем адрес системного вызова sys_gost
* адресом нового обработчика - функции new_gost. Адрес "старого" вызова
* сохраняем в переменной old_sys_gost_addr
*/
sct = get_sct_addr();
old_sys_gost_addr = *(__u32 *)(sct + SYS_gost * 4);
*(__u32 *)(sct + SYS_gost * 4) = (__u32)&new_gost;

key_enable = 0;
key_init = 0;

return 0;
}


/*
* При выгрузке модуля восстанавливаем адрес системного вызова
* sys_gost в ТСВ
*/
static void __exit exit_gost()
{
*(__u32 *)(sct + SYS_gost * 4) = old_sys_gost_addr;
memset(&keys, 0, sizeof(struct key_info));
unregister_chrdev(GOST_MAJOR, "/dev/gost");

return;
}

module_init(init_gost);
module_exit(exit_gost);




Рассмотрим функцию new_gost, которая заменит системный вызов sys_gost.
Эта функция непосредственно выполняет операции криптографического преобразования
блоков данных, переданных драйверу модулем МВ.



/*
* Листинг 4. Функция, выполняющая операции криптографического преобразования
* информации (файл gost.c)
*/

#include <linux/module.h>
#include <linux/slab.h>
#include <limits.h>
#include "gost_var.h"

void simple_replace_crypt(void);
void op(int);
void init_key();
__u32 block(__u32, __u8 *, __u32);

/*
* Функция new_gost принимает три параметра - указатель на блок данных,
* подлежащих криптопреобразованию, размер блока и флаг управления режимом
*/
int new_gost(__u8 *block, size_t count, int flag)
{
int i;

/*
* Если ключи не загружены, флаг key_enable установлен в 0. В этом
* случае драйвер никаких криптопреобразований не выполняет
*/
if(!key_enable) {
printk(KERN_INFO "Keys not loadedn");
return 1;
}

/*
* Проверяем значения флагов flag и key_enable. Если оба флага установлены,
* приступаем к выполнению операции криптопреобразования блока данных
*/
if((flag && key_enable)) {

/*
* Все дальнейшие операции выполняются в соответствии с алгоритмом
* ГОСТ 28147-89, режим гаммирования.
*
* Инициализируем ключи
*/
if(!key_init) init_key();

/*
* Суммируем значение накопителя N4 и константы C1 по модулю (2^32-1)
*/
__asm__ __volatile__ (
" addl %3,%%eax nt"
" jnc 1f nt"
" incl %%eax nt"
"1: cmpl %2,%%eax nt"
" jnz 2f nt"
" xorl %%eax,%%eax nt"
"2:"
:"=a"(N4)
:"0"(N4),"b"(ULONG_MAX),"d"(C1)
);

/*
* Суммируем значение накопителя N3 и константы C2 по модулю (2^32)
*/
N3 += C2;

nac.lg.N1 = N3;
nac.lg.N2 = N4;

/*
* Шифруем содержимое накопителей N1 и N2 в режиме простой замены
* алгоритма ГОСТ 28147-89
*/
simple_replace_crypt();

/*
* Выполняем криптопреобразование блока данных и возвращаем модулю МВ
* размер этого блока
*/
for(i = 0; i < count; i++) block[i] ^= nac.N[i];

return count;
}

/*
* Если установлен флаг завершения операции криптопреобразования
* (flag = E_STOP), сбрасываем флаг инициализации ключей и возвращаем
* нулевое значение модулю МВ
*/
key_init = 0;
return 0;
}

/*
* Функция simple_replace_crypt() выполняет операцию шифрования в режиме
* простой замены алгоритма ГОСТ 28147-89
*/
void simple_replace_crypt()
{
int i,n;

/*
* В соответствии с алгоритмом ГОСТ 28147-89, выполняем 31 цикл преобразования
*/
for(n = 1; n < 4; n++) {
for(i = 0; i < 8; i++) op(i);
}
for(i = 7; i > 0; i--) op(i);

/*
* 32-й цикл
*/
SM1 = nac.lg.N1 + keys.X[0];
SM2 = block(SM1, keys.key_d, nac.lg.N2);
nac.lg.N2 = SM2;

return;
}

/*
* Циклы преобразования реализованы в функции op(int)
*/
void op(int i)
{

/*
* Суммируем значение накопителя N1 и 4-х байтового вектора X[i]
* в сумматоре SM1
*/
SM1 = nac.lg.N1 + keys.X[i];

/*
* Выполняем преобразование значения, находящегося в сумматоре SM1,
* в блоке подстановки
*/
SM2 = block(SM1, keys.key_d, nac.lg.N2);
nac.lg.N2 = nac.lg.N1;
nac.lg.N1 = SM2;
}

/*
* Функция init_key() выполняет процедуру инициализации ключевых данных
*/
void init_key()
{

/*
* Копируем значение синхропосылки с накопители N1 и N2
*/
memset(&nac, 0, sizeof(nac));
memcpy(nac.N, keys.sp, 8);

/*
* Шифруем содержимое накопителей N1 и N2 в режиме простой замены
* алгоритма ГОСТ 28147-89
*/
simple_replace_crypt();

N3 = nac.lg.N1;
N4 = nac.lg.N2;

/*
* Устанавливаем значение флага инициализации ключей в 1
*/
key_init = 1;
return;
}


/*
* В функции block об`единены блок подстановки (главный структурный элемент
* алгоритма) и регистр сдвига. Параметры функции:
* - значение сумматора SM1
* - указатель на блок данных, содержащих долговременный ключ
* - значение накопителя N2
* Результат, возвращаемый функцией block, будет помещен в сумматор SM2
*/
__u32 block(__u32 SM1, __u8 *k, __u32 N2)
{
__u32 SM2;

__asm__ __volatile__ (
" cld nt"
" pushl %%edx nt"
" xorl %%ecx,%%ecx nt"
" xorl %%edx,%%edx nt"
" movw $4,%%cx nt"
"1: pushl %%esi nt"
" pushw %%cx nt"
" pushl %%eax nt"
" pushl %%edx nt"
" xorl %%edi,%%edi nt"
" xorw %%cx,%%cx nt"
" movl %%esi,%%edi nt"
" addl $8,%%edi nt"
" xorl %%ebx,%%ebx nt"
" xorw %%dx,%%dx nt"
" pushw %%ax nt"
" shlb $4,%%al nt"
" shrb $4,%%al nt"
" movb %%al,%%dl nt"
" popw %%ax nt"
" shrb $4,%%al nt"
" movb %%al,%%dh nt"
" xorl %%eax,%%eax nt"
" movb %%dl,%%bl nt"
" btw $0,%%bx nt"
" jnc 2f nt"
" decb %%bl nt"
" shrb $1,%%bl nt"
" movw (%%esi,%%ebx),%%ax nt"
" jmp 3f nt"
"2: shrb $1,%%bl nt"
" movw (%%esi,%%ebx),%%ax nt"
" shlb $4,%%al nt"
"3: shrb $4,%%al nt"
" movb %%al,%%cl nt"
" xorl %%ebx,%%ebx nt"
" movb %%dh,%%bl nt"
" btw $0,%%bx nt"
" jnc 4f nt"
" decb %%bl nt"
" shrb $1,%%bl nt"
" movw (%%edi,%%ebx),%%ax nt"
" shrb $4,%%al nt"
" jmp 5f nt"
"4: shrb $1,%%bl nt"
" movw (%%edi,%%ebx),%%ax nt"
"5: shlb $4,%%al nt"
" orb %%cl,%%al nt"
" popl %%edx nt"
" movb %%al,%%dl nt"
" popl %%eax nt"
" popw %%cx nt"
" rorl $8,%%edx nt"
" shrl $8,%%eax nt"
" xorl %%esi,%%esi nt"
" popl %%esi nt"
" addl $16,%%esi nt"
" decw %%cx nt"
" jz 6f nt"
" jmp 1b nt"
"6: movl %%edx,%%eax nt"
" roll $11,%%eax nt"
" popl %%edx nt"
" xorl %%edx,%%eax nt"
:"=a" (SM2)
:"0"(SM1),"S"(k),"d"(N2)
:"ebx","ecx","edi");

return SM2;
}



Для сборки загружаемого модуля ядра создадим Makefile следующего содержания:

.PHONY = clean

MOD_NAME = gost
CFLAGS = -O2 -Wall
LINUX = /usr/src/linux
MODFLAGS = -D__KERNEL__ -DMODULE -I$(LINUX)/include
OBJ = sys_call_gost.o get_sct_addr.o gost.o

$(MOD_NAME): $(OBJ)
ld $^ -r -o $@

%.o: %.c
gcc $(CFLAGS) $(MODFLAGS) -c $^

clean:
rm -f *.o
rm -f ./gost


Загрузка драйвера выполняется командой: insmod ./gost



5.2. Модуль ключевых данных
---------------------------

Модуль ключевых данных (МКД) выполняет две задачи:
- генерацию ключевых данных;
- запись ключевых данных в БКИ драйвера.

Ключевые данные представляют собой три файла фиксированного размера:
- файл долговременного ключа key_d длиной 64 байт;
- файл сеансового ключа key_s длиной 32 байт;
- файл синхропосылки key_sp длиной 8 байт.

В соответствии с выполняемыми функциями, в состав МКД будут входить:
- генератор ключевых данных;
- модуль записи ключевых данных в БКИ драйвера.

Рассмотрим код генератора ключевых данных.




/*
* Листинг 5. Генератор ключевых данных (файл creat_key.c)
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#define MOUNT_DIR "./"

int main()
{
struct struct_key {
char *k_name;
int k_size;
};

struct struct_key k[3] = {
{ MOUNT_DIR"/key_d", 64},
{ MOUNT_DIR"/key_s", 32},
{ MOUNT_DIR"/key_sp", 8},
};

int i = 0, fdkey, rnd;
char buf[64];

rnd = open("/dev/urandom", O_RDONLY);
if(rnd < 0) {
perror("open");
return -1;
}

for(; i < 3; i++) {

fdkey = open(k[i].k_name, O_CREAT|O_WRONLY, 0600);
if(fdkey < 0) {
perror("open");
return -1;
}

memset(buf, 0, 64);
if(read(rnd, buf, k[i].k_size) != k[i].k_size) {
close(fdkey);
perror("read");
return -1;
}

if(write(fdkey, buf, k[i].k_size) != k[i].k_size) {
perror("write");
return -1;
}
close(fdkey);
}
close(rnd);
printf("nKeys generation is complitenn");
return 0;
}



Код очень простой, поэтому приводится без комментариев. Для получения
случайной последовательности мы воспользовались файлом /dev/urandom.



/*
* Листинг 6. Модуль записи ключевых данных в БКИ драйвера (файл write_key.c)
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>

#define KEYDIR "./" // ключи будут находиться в текущем каталоге

/*
* Структура struct key_struct будет передана драйверу для записи в БКИ
*/
struct key_struct {
char key_d[64];
unsigned long X[8];
char sp[8];
} __attribute ((packed)) keys;

char tmp_buff[104];

struct struct_key {
char *k_name;
int k_size;
} __attribute__ ((packed));

struct struct_key k_st[3] = {
{ KEYDIR"/key_d", 64},
{ KEYDIR"/key_s", 32},
{ KEYDIR"/key_sp", 8},
};

int main()
{
int i = 0, fdkey, gost, pos = 0;

memset((void *)tmp_buff, 0, sizeof(tmp_buff));

for(; i < 3; i++) {

fdkey = open(k_st[i].k_name, O_RDONLY);
if(fdkey < 0) {
perror("open");
return -1;
}

if(read(fdkey, (tmp_buff + pos), k_st[i].k_size) != k_st[i].k_size) {
perror("read");
return -1;
}

pos += k_st[i].k_size;

close(fdkey);
}

memset((void *)&keys, 0, sizeof(struct key_struct));
memcpy((void *)&keys, tmp_buff, sizeof(tmp_buff));

gost = open("/dev/gost", O_WRONLY);
if(gost < 0) {
perror("open");
return -1;
}

if(write(gost, (char *)&keys, sizeof(struct key_struct)) < 0) {
perror("write");
} else printf("nKeys has been loaded successfulynn");

memset((void *)&keys, 0, sizeof(struct key_struct));
close(gost);
return 0;
}


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



5.3. Модуль взаимодействия с драйвером
--------------------------------------

Модуль взаимодействия с драйвером (МВ) представляет собой приложение
пользователя. Его задача - обмен информационными блоками с драйвером и
сохранение результатов в файле.



/*
* Листинг 7. Модуль взаимодействия с драйвером (файл test_gost.c)
*/
#include <stdio.h>
#include <gost.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
int in, n;
unsigned char buff[8];

/*
* Параметром модуля МВ является имя файла, содержание которого подлежит
* криптографическому преобразованию
*/
if(argc != 2) {
printf("ntUsage: gost [input file]nn");
return 0;
}

/*
* Открываем файл
*/
in = open(argv[1], O_RDWR);
if(in < 0) {
perror("open");
return -1;
}

memset((void *)buff, 0, 8);

/*
* Считываем из входного файла блоки данных длиной 8 байт
*/
while((n = read(in, buff, 8)) > 0) {

/*
* Вызываем системную функцию sys_gost для выполнения операции
* криптографического преобоазования. Результат записываем в тот же файл
*/
gost(buff, n, E_START);
lseek(in, -n, SEEK_CUR);
write(in, buff, n);
}

/*
* Информируем драйвер о завершении операции криптопреобразования
*/
gost(0, 0, E_STOP);
close(in);
return 0;
}



6. Порядок работы с СКЗИ
--------------------------

Для подготовки СКЗИ к работе администратор должен выполнить следующие
действия:
- загрузить криптографический драйвер
- сгенерировать ключевые данные и записать их в БКИ драйвера

После этого пользователь может приступить к выполнению операций
криптографической защиты информации. Для этого ему достаточно запустить на
выполнение модуль МВ (файл test_gost), указав в командной строке имя
преобразуемого файла. Результат преобразования будет записан в тот же файл.
1210 Прочтений •  [Разработка модуля Linux ядра, реализующего алгоритм криптозащиты ГОСТ 28147-89 (linux kernel module crypt gcc)] [08.05.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• Разработка модуля Linux ядра, реали... Ukraine Vova 08.05.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка