| RSS



Меню

Bookmark and Share


Статистика
Ваш IP: 3.133.133.251
Вы используете: v





Сейчас на сайте:

Тех поддержка ->

Облако тэгов
ОС видио Tor Обратная сторона антенна 4.6 PHP Эксплоит Windows Server 2008 qip Virtual chroot kernel proc sysctl tune FreeBSD bridge Boot Disk Bluetooth GEO game directx Emulator Python Shell DDoS червь Conficker вирус троян Лаборатория Касперского пиратство apple iPhone ИТ-отрасль Щеголев Microsoft экономический кризис Twitter социальная сеть анонимность Лицензия Open Source ASP.NET MVC уязвимость MySQL база данных файлообмен закон франция пират Skype мобильный Deutsche Telekom Хакер киберпреступник Trend Micro кибератака Германия робот утечка данных персональные данные ноутбук интернет Китай цензура ядро Linux Торвальдс Windows Vista Acer Linux патент браузер Firefox Internet Explorer Opera Net Applications Safari Intel Linux Foundation Moblin Oracle патч банкомат кардер HSM IBM X-Force Cofee сша кибервойна Эстония Dell ИТ-специалист хакерские атаки Pirate Bay контроль кибербезопасность язык программирования The Pirate Bay Пиратская партия утечка информации приговор Mozilla Chrome безопасность Госдума СМИ Windows 8 Баллмер взлом Пентагон ботнет Украина Facebook Cisco cloud Windows XP нетбук торрент музыка биометрический nokia ФБР IP-адрес CIPAV Comcast sms RSA java Google CAPTCHA Symantec спам конфиденциальная информация инсайдер Perimetrix антивирус тест Anti-Malware Windows 7 операционная система Windows провайдер авторское право RapidShare UNIX свиной грипп шантаж дети EFF BluWiki копирайт экстремизм Panda Security cloud computing McAfee Cybercrime Response Unit Bottle Domains HTTPS ICANN студент шпионское ПО Норвегия школьник New York Times XSS YouTube Warner Music кибершпионаж КНДР Ubuntu свободное ПО AMD ATI касперский Россия РФ сервер хостинг фальшивый антивирус Comodo CA Wi-Fi D-Link суд пароль блог фишинг Одноклассники медведев контрафакт мошенник штраф Sony GPS по Gumblar JAVASCRIPT хакеры вредоносное ПО Yahoo ФАС компьютер Софт MPAA кибероружие PandaLabs Red Hat Минкомсвязи сбой ASUSTeK Computer мошенничество Доктор Веб ВКонтакте Cyber-Arc исходный код PCI DSS МВД фильтр порнография BREIN свобода слова Казахстан GEMA Autodesk сисадмин Gmail кредитная карта кибермошенник LiveJournal шифрование криптография Deep Purple банк нанотехнологии Wikipedia zero-day ColdFusion выборы кража данных DNS BIND Android BASIC атака Black Hat Mac OS X Click Forensics Clampi домен фсб Прокуратура Уголовное дело icq Barrelfish киберпреступность Sophos AT&T ошибка Electa Gamma Knife OpenBSD DARPA военные Сайт Visual Studio 2010 .NET Framework 4 Chrome OS электронная почта турция конференция спамер FTC полиция российская ОС Koobface Великобритания БЕЛОРУССИЯ грузия BSA Bittorrent облачные вычисления Azure Европа Dr.Web Билл Гейтс спецслужбы Cryzip Живой Журнал Royal Bank of Scotland смартфон Canonical Pwn2Own F-Secure Symbian Hotmail фильм

Главная » Статьи » Общие Статьи

Crypto API в ядре Linux

А начнем, пожалуй, с подготовки системы. Для начала надо убедится, что система готова к созданию разного рода приложений, а конкретно к разработке модулей ядра. Помимо присутствия GCC надо еще убедиться в том, что ядро было скомпилировано с поддержкой модульности и криптографических API. Про установку GCC и включение модулей написано много мануалов, поэту не будем тратить ни времени, ни чернил, а про то, как создавать эти самые модули, уже не раз писалось на страницах ][, так что мы предполагаем, что читатель уже овладел необходимыми навыками системного программирования (ведь он читает ][ ;-)). Крипто API включаются во вкладке Cryptographic API, которую можно наблюдать если находясь в каталоге с исходниками ядра из консоли набрать "make menuconfig". А самый легкий способ проверки их доступности это попытаться скомпилировать пример, который находится все в тех же исходниках ядра. Заходим в папку с исходниками, дальше (как не трудно догадаться) в директорию crypto и компилируем tcrypt.c. Если он компилируется без фатальных ошибок и даже работает, то собираемся с духом и идем дальше.

Вот из ит

Теперь надо немного разобраться - что же все таки мы подключили и где это найти. Исходники этого всего дела лежат в той же директории, что и упомянутый выше tcrypt.c, а сам он является примером в котором показано как использовать все реализованные в Cryptographic API алгоритмы. Пример этот хорошо комментирован, а если что-то остается не совсем понятным, то всегда можно заглянуть в лежащие рядом исходники самих Cryptographic API. Но, как говорится, сказать или даже написать проще чем сделать. На практике довольно часто можно свалиться в штопор в самых неожиданных местах, и потом довольно долго по частям собирать то, что всего пять минут назад летало со скоростью звука. К сожалению ошибки всегда банальны, но постоянны, и каждый раз вспоминать как приклеивается один и тоже кусок становится утомительным. Сделать один раз инструкцию и со временем её дополнять гораздо эффективнее и проще. Относительно наших API можно сказать тоже самое. Нормального мана на русском языке по ним нам найти не удалось, а повторно вкуривать одну и туже траву это не тру. Поэтому хотим оставить своего рода рабочие записки и надеемся, что это еще кому-нибудь поможет.

Литл море

Предположим, мы хотим реализовать немного устаревший, но достаточно быстрый и проверенный алгоритм DES. У этого алгоритма существует несколько режимов:

  • ECB (Electronic Code Book) - режим где все блоки шифруются независимо друг от друга и не сцепляются;
  • CBC (Cipher Block Chaining)- режим, в котором результат шифрования предыдущего блока используется для шифрации текущего.

Под блоками тут подразумевается часть шифротекста (не будем же мы весь текст шифровать за раз в самом деле). А аббревиатуры лучше всего запомнить, чтобы они не сбивали с толку если понадобиться исследовать исходники самих API. Так с виду один и тот же алгоритм может быть реализован в разных режимах. Если кому интересно, то в качестве домашнего задания можно еще самостоятельно покурить CFB и OFB.

Однако, мы отвлеклись от темы. Для своих целей выберем режим CBC как более надежный и приступим, сделав наброски будущего кода.

Как это часто бывает, начнем с написания и описания ключевых структур и переменных:

struct completion comp;
struct scatterlist sg[8];
struct crypto_ablkcipher *tfm;
struct ablkcipher_request *req;

Переменная comp служит для синхронизации выполнения между нашей функцией и непосредственно шифрованием. Суть этого станет ясна чуть ниже. А пока рассмотрим саму структуру. Она объявлена в include/linux/completion.h и содержит всего два поля:

struct completion {
unsigned int done;
wait_queue_head_t wait;
};

Первое это флаг выполнения, а второе указатель на очередь ожидающих задач.

Следующая переменная sg описана в include/linux/scatterlist.h. Это структура платформозависимая, и на i386 платформе она определена следующим образом:

struct scatterlist {
struct page *page;
unsigned int offset;
dma_addr_t dma_address;
unsigned int length;
};

Заполнение полей этой структуры вполне можно поручить функции sg_init_one(). В этой функции определяется страница памяти, с которой "начинается" buf, и определяется смещение указателя buf относительно адреса начала страницы.

tfm и есть наша основная структура, в файле include/linux/crypto.h находится ее описание:

struct crypto_ablkcipher {
struct crypto_tfm base;
};

Не очень информативно, поэтому посмотрим чуть выше, где находится:

struct crypto_tfm {

u32 crt_flags;

union {
struct ablkcipher_tfm ablkcipher;
struct aead_tfm aead;
struct blkcipher_tfm blkcipher;
struct cipher_tfm cipher;
struct hash_tfm hash;
struct compress_tfm compress;
} crt_u;

struct crypto_alg *__crt_alg;

void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
};

Уже что-то, не правда ли? Первым полем идут флаги, о некоторых из них расскажем чуть ниже. Далее объединение более низкоуровневых структур для разных типов криптографических задач, прямой доступ к которым использовался в предыдущих версиях. В crypto_alg содержится указатель на структуру в которой есть все необходимое для корректной работы непосредственно алгоритма шифрования. А именно имя самого алгоритма, приоритет и т.д. (про это можно подробнее отсюда http://diploma-thesis.siewior.net/html/diplomarbeitch4.html).

Следующая переменная, req, содержит указатель на структуру запросов struct ablkcipher_request:

struct ablkcipher_request {
struct crypto_async_request base;

unsigned int nbytes;

void *info;

struct scatterlist *src;
struct scatterlist *dst;

void *__ctx[] CRYPTO_MINALIGN_ATTR;
};

С помощью этой переменной мы обращаемся к страницам памяти где находится шифрованный и расшифрованный текст.

Когда мы разобрались с основными переменными можно приступить к написанию самого кода. Начнем с инициализации переменной comp с помощью функции init_completion():

init_completion(&comp);

Эта функция обнулят флаг done и добавляет comp в голову очереди wait_queue_head_t, о которых рассказывалось выше. Подробнее о механизме работы этой структуры и о том, для чего мы ее используем, будет рассказано еще чуть ниже ;).

Теперь выделим память для нашей основной переменной:

tfm = crypto_alloc_ablckhipher ("cbc(des)", 0, CRYPO_TFM_REQ_WEAK_KEY);

В качестве первого параметра мы передаем имя алгоритма, второй параметр это тип шифрования (вспомните объединение crt_u в описании структуры), третьим параметром мы передаем флаги. Переданный флаг означает, что алгоритм должен принимать даже слабые ключи.

Далее выделяем память для ablkcipher_request:

req = ablkcipher_request_alloc (tfm, GFP_KERNEL);

С первым параметром думаю все понятно и так. Непосредственно память под структуру выделяется функцией kmalloc, которая в качестве параметра принимает флаг, говорящий о том как именно стоит выделять память. Флаг GFP_KERNEL (GFP - Get Free Page) резервирует блок памяти, выделяя страницы памяти по мере обращения к ним. Существует и другие флаги например:

  • GFP_ATOMIC выделяет требуемую память немедленно (при необходимости вытесняя другие страницы на диск);
  • GFP_BUFFER никогда не вытесняет другие страницы, и если запрошенная память недоступна, с выделением наступает облом.

Фактически приходится выбирать между GFP_ATOMIC и GFP_KERNEL. Обычно используют GFP_KERNEL, так как он ведет себя не столь агрессивно.

Потом установим ключ которым будем шифровать:

ret = crypto_ablkcopher_sekey (tfm, key, strlen(key));

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

Теперь позаботимся о расположении текста который будем шифровать:

sg_init_one (&sg[0], text, strlen(text));

Стоит отметить, что текст должен быть кратен восьми, иначе при попытке зашифровать\дешифровать получите ошибку -21 (что означает «некорректные входные данные»). То, как с этим бороться, можно посмотреть в приложенном коде. Сама же функция просто заполняет страницы памяти текстом, который собираемся зашифровать или дешифровать :).

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

u8 iv = {0xff, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
ablkcipher_request_set_crypt (req, sg, sg, strlen(text), iv);

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

Теперь приступаем непосредствнно к шифрованию:

ret = enc ? crypto_ablkcipher_encrypt (req) : crypto_ablkcipher_decrypt(req);

Сами функции и их параметр в пояснении думаю не нуждаются, если не понятно перечитайте еще раз внимательно о req. Ну с ret все совсем понятно скажите вы. А вот и нет :). Да, ret в случае удачного выполнения действительно будет равна 0. Но вот остальные значения не всегда означают ошибку.

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

switch (ret) {
case 0:
break;

case -EINPROGRESS: case -EBUSY:
printk ("\nwait\n");
ret = wait_for_completion_interruptible (&comp);
if (!ret) {
INIT_COMPLETION(comp);
break;
}

default:
printk ("failred err=%d", -ret);
goto out;

}

Вспомните описание структуры completion, непонятные слова, которые мы говорили о флаге выполнения и очереди задач. Дело в том, что криптоалгоритмы не так быстры как хотелось бы. Но как же так, скажите вы, как мы можем вернутся в вызвавшую функцию до того, как завершилась вызываемая? Дело в том, что авторы этой библиотеки очень хитрые люди и оптимизировали работу криптоалгоритмов в расчете на распараллеливание вашего алгоритма и с учетом того, что к шифруемым/дешифруемым данным будут обращаться другие алгоритмы. Поэтому и получилось так, что мы можем вернутся в вызвавшую функцию до того, как шифрование/дешифрование завершится. Для того, чтобы избежать обращения к еще не зашифрованным/не расшифрованным данным, мы и используем структуру completion. Механизм работы этой структуры и функций, с ней связанных, чрезвычайно идентичен механизму работы блокирующих семафоров. Когда работа криптоалгоритма будет завершена он выставит поле done в 1 и наша функция продолжит работу. Если вы знакомы с семафорами, то вопросов не возникнет, если нет - настоятельно рекомендуем познакомится.

Ду ит нау

Сам модуль можно найти в приложении к данной статье. Код подробно прокомментирован и не должен вызывать затруднений. По сути он добавляет свою фукцию (nethook) по обработке полученных и отправленных пакетов на определенное устройство, символьное имя которого задается параметром device_name. А за шифрование/дешифрование отвечает функция my_des, в ней применено все то, о чем мы писали выше. Инструкция по сборке и установке лежит рядом. Дерзайте ;)

Категория: Общие Статьи | Добавил: aka_kludge (26.01.2009)
Просмотров: 2051 | Комментарии: 1 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
    Главная      
...
На службе : дней

22:10
Обновить


Пользователи
aka_kludge
qwerty
LeadyTOR
aka_Atlantis
AdHErENt
mAss
Sissutr
hiss
DrBio
tHick

Поиск


Copyright tHR - TeAM 2024 г. admin: aka_kludge (ICQ:334449009) Moderator's: LeadyTOR, ... Яндекс.Метрика