CryptoAPI ядра Linux: розробка та застосування російської криптографії

imageCryptoAPI являє собою реалізацію криптографічних алгоритмів з наданням доступу до них як з самого ядра, так і з прикладного програмного забезпечення. Найбільш яскравими представниками цього програмного забезпечення є IPSEC (VPN ) і dm-crypt (файлова система).

Кінцевою метою даного матеріалу буде створення файлової системи з використанням російських криптографічних алгоритмів:

  • Вироблення значення геш-функції згідно з вимогами ГОСТ Р 34.11-94 / ГОСТ Р 34.11-2012 «Інформаційна технологія. Криптографічний захист інформації. Функція хешування»;
  • Зашифрування/розшифрування даних та обчислення імітовставки у відповідності з вимогами ГОСТ 28147-89 «Системи обробки інформації. Захист криптографічний»;
  • Зашифрування/розшифрування даних алгоритмами шифрування «Коник» (Кузмін, Нечаєв І Компанія) і «Магма» у відповідності з вимогами «ГОСТ Р 34.12-2015 Інформаційна технологія. Криптографічний захист інформації. Блокові шифри» і «ГОСТ Р 34.13-2015 Інформаційна технологія. Криптографічний захист інформації. Режими роботи блокових шифрів».
Подивитися які криптографічні алгоритми можуть використовуватися для створення файлової системи можна подивитися наступними командами:

bash-4.3$ /usr/local/bin64/cryptsetup benchmark
# Tests are approximate using only memory (no storage IO).
PBKDF2-sha1 620459 iterations per second
PBKDF2-sha256 541619 iterations per second
PBKDF2-sha512 357144 iterations per second
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 467,6 MiB/s 1686,1 MiB/s
serpent-cbc 128b 74,5 MiB/s 264,4 MiB/s
aes-cbc 256b 350,1 MiB/s 1333,8 MiB/s
serpent-cbc 256b 74,2 MiB/s 265,3 MiB/s
bash-4.3$ /usr/local/bin64/cryptsetup benchmark -caes-ecb
# Tests are approximate using only memory (no storage IO).
# Algorithm | Key | Encryption | Decryption
aes-ecb 256b 1422,6 MiB/s 1437,6 MiB/s
bash-4.3$

Як видно з цього прикладу для створення файлової системи можуть використовуватися алгоритм шифрування AES в режимах CBC та ECB, а також хеш функції sha1, sha256 і sha512.

Для переходу на російську криптографію нам необхідно додати в ядро Linux модулі, що реалізують гешування за ГОСТ Р 34.11-94, ГОСТ Р 34.11-2012 з довжиною хеша 256 біт (STRIBOG-256) і довжиною хеша 512 біт (STRIBOG-512).

В якості алгоритмів шифрування повинні бути реалізовані ГОСТ 28147-89, він же фактично алгоритм «Магма» (ГОСТ Р 34.12-2015), а також алгоритм «Коник» (ГОСТ Р 34.12-2015). Для перевірки будуть задіяні режими шифрування CBC, ECB.

В якості прототипів цих модулів розглядаються модулі aes-generic та shaxxx-generic. Відповідно для російської криптографії повинні бути реалізовані модулі:

  • gosthash-generic (ГОСТ ДО 34.11-94);
  • stribog256-generic (ГОСТ Р 34.11-2012 з довжиною хеша 256 біт);
  • stribog512-generic (ГОСТ Р 34.11-2012 з довжиною хеша 512 біт);
  • gost-generic (ГОСТ 28147-89, «Магма»);
  • kuznyechik-generic («Коник»).
Головне питання – де взяти реалізацію російських криптографічних алгоритмів? Одним з варіантів є OpenSSL і підтримка ГОСТ-их алгоритмів в engine gost. Проте до цього часу так і підтримується реалізація лише ГОСТ 28147-89 і ГОСТ Р 34.11-94. Більш прийнятним є підтримка російських криптографічних алгоритмів у проекті GCrypt-1.7.0, де вже є підтримка алгоритм «Магма» (ГОСТ Р 34.12-2015) і ГОСТ Р 34.11-2012 з довжиною хеш-а 256 біт (STRIBOG-256) і довжиною хеш-а 512 біт (STRIBOG-512).

Що стосується «Коника», то тут допоможе стаття на Habrahabr«ГОСТ Р 34.12-15 на SSE2, або Не так вже й поганий Коник».

Складання модулів проводилася для наступного ядра Linux:

bash-4.3$ uname -sr
Linux 4.4.39-desktop-1.mga5
bash-4.3$

Для інших ядер можуть знадобитися якісь зміни. Складання модулів CryptoAPI, що реалізують російські крипто-алгоритмів, покажемо на прикладі модуля stribog256-generic (ГОСТ Р 34.11-2012 з довжиною хеш-аа 256 біт).

Отже, Makefile:

obj-m := stribog256_generic.o
my-objs := stribog.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KDIR) M=$(PWD) modules_install

Зазначимо також вміст каталогу stribog256_generic:

bash-4.3$ ls 
rypto_mult_table.h
hash_bit.h
Makefile
stribog256_generic.c
stribog256.h
stribog.c
stribog.h
bash-4.3$ 

Для складання модуля досить увійти в каталог stribog256 і виконати команду make:

bash-4.3$ make
make -C /lib/modules/4.4.39-desktop-1.mga5/build M=/home/a513/DM_CRYPT/dm-crypt/modules stribog256
make[1]: вхід в каталог «/usr/src/kernel-4.4.39-desktop-1.mga5»
CC [M] /home/a513/DM_CRYPT/dm-crypt/stribog256/stribog256_generic.o
...
Building modules, stage 2.
MODPOST 1 modules
CC /home/a513/DM_CRYPT/dm-crypt/stribog256/stribog256_generic.mod.o
LD [M] /home/a513/DM_CRYPT/dm-crypt/stribog256/stribog256_generic.ko
make[1]: вихід з каталогу «/usr/src/kernel-4.4.39-desktop-1.mga5»
bash-4.3$ 

Код модуля stribog256_generic.c виглядає наступним чином:

Код модуля stribog256_generic.c виглядає наступним чином:
bash-4.3$ cat stribog256_generic.c 

/
*
* Cryptographic API.
*
* Stribog256 Secure Hash Algorithm.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <crypto/internal/hash.h>
#include "stribog256.h"
#include "stribog.c"
static int stribog256_init(struct shash_desc *desc)
{
struct stribog_ctx *sctx = shash_desc_ctx(desc);
GOSTR3411_2012_256_Init(sctx);
return 0;
}
int crypto_stribog256_update(struct shash_desc *desc, const u8 *data,
u32 len)
{
struct stribog_ctx *sctx = shash_desc_ctx(desc);
GOSTR3411_2012_Update(sctx, data, len); 
return 0;
}
EXPORT_SYMBOL(crypto_stribog256_update);
/* Add padding and return the message digest. */
static int stribog256_final(struct shash_desc *desc, u8 *out)
{
struct stribog_ctx *sctx = shash_desc_ctx(desc);
GOSTR3411_2012_256_Final(sctx, out);
// Context Wipe 
memset(sctx, 0, sizeof(*sctx));
return 0;
}
static int stribog256_export(struct shash_desc *desc, void *out)
{
struct stribog_ctx *sctx = shash_desc_ctx(desc);
memcpy(out, sctx, sizeof(*sctx));
return 0;
}
static int stribog256_import(struct shash_desc *desc, const void *in)
{
struct stribog_ctx *sctx = shash_desc_ctx(desc);
memcpy(sctx, in, sizeof(*sctx));
return 0;
}
static struct shash_alg alg = {
.digestsize = STRIBOG256_DIGEST_SIZE,
.init = stribog256_init,
.update = crypto_stribog256_update,
.final = stribog256_final,
.export = stribog256_export,
.import = stribog256_import,
.descsize = sizeof(struct stribog_ctx),
.statesize = sizeof(struct stribog_ctx),
.base = {
.cra_name = "stribog256",
.cra_driver_name= "stribog256-generic",
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
.cra_blocksize = STRIBOG_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
};
static int __init stribog256_generic_mod_init(void)
{
return crypto_register_shash(&alg);
}
static void __exit stribog256_generic_mod_fini(void)
{
crypto_unregister_shash(&alg);
}
module_init(stribog256_generic_mod_init);
module_exit(stribog256_generic_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Stribog256 Secure Hash Algorithm");
MODULE_ALIAS_CRYPTO("stribog256");
MODULE_ALIAS_CRYPTO("stribog256-generic");

bash-4.3$


За аналогічною схемою готуються і збираються і інші модулі:

bash-4.3$ ls -C1
gost_generic.ko
gosthash_generic.ko
kuznyechik_generic.ko
stribog256_generic.ko
stribog512_generic.ko
bash-4.3$

Тепер їх можна вантажити в систему:

bash-4.3#insmod ./ stribog256_generic.ko
bash-4.3#

Тепер подивимося які алгоритми підтримує CryptoAPI:

bash-4.3$ /usr/local/bin64/cryptsetup benchmark
# Tests are approximate using only memory (no storage IO).
PBKDF2-sha1 679129 iterations per second
PBKDF2-sha256 544431 iterations per second
PBKDF2-sha512 355208 iterations per second
PBKDF2-gosthash 138994 iterations per second
PBKDF2-stribog256 123187 iterations per second
PBKDF2-stribog512 91275 iterations per second
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 468,0 MiB/s 1700,7 MiB/s
serpent-cbc 128b 74,0 MiB/s 266,9 MiB/s
aes-cbc 256b 349,2 MiB/s 1349,4 MiB/s
serpent-cbc 256b 72,8 MiB/s 259,1 MiB/s
gost-cbc 256b 38,3 MiB/s 46,8 MiB/s
kuznyechik-cbc 256b 3,6 MiB/s 3,2 MiB/s
bash-4.3$ 

Для того, щоб ГОСТ нові алгоритми з'явилися при тестуванні (benchmark) в утиліту cryptsetup достатньо внести зміни в наступні файли:

1. ./cryptsetup/src/cryptsetup.c (рядки додані тільки для команди тестування)

static struct {
const char *cipher;
const char *mode;
size_t key_size;
size_t iv_size;
} bciphers[] = {
{ "aes", "cbc", 16, 16 },
{ "serpent", "cbc", 16, 16 },
{ "aes", "cbc", 32, 16 },
{ "serpent", "cbc", 32, 16 },
/*ГОСТ*/
{ "gost", "cbc", 32, 8 },
{ "gost", "ecb", 32, 8 },
{ "gost", "crt", 32, 8 },
{ "kuznyechik", "cbc", 32, 16 },

{ NULL, NULL, 0, 0 }
};

2. ./cryptsetup/lib/crypto_backend/crypto_cipher_kernel.c

static struct cipher_alg cipher_algs[] = {
{ "cipher_null", 16 },
{ "aes", 16 },
{ "serpent", 16 },
{ "twofish", 16 },
{ "anubis", 16 },
{ "blowfish", 8 },
{ "camellia", 16 },
{ "cast5", 8 },
{ "cast6", 16 },
{ "des", 8 },
{ "des3_ede", 8 },
{ "khazad", 8 },
{ "seed", 16 },
{ "tea", 8 },
{ "xtea", 8 },
/*ГОСТ*/
{ "gost", 8 },
{ "kuznyechik", 8 },

{ NULL, 0 }
};

3. ./cryptsetup/lib/crypto_backend/crypto_kernel.c

static struct hash_alg hash_algs[] = {
{ "sha1", "sha1", 20, 64 },
/*ГОСТ*/
{ "gosthash", "gosthash", 32, 64 },
{ "stribog256", "stribog256", 32, 128 },
{ "stribog512", "stribog512", 64, 128 },
{ "sha256", "sha256", 32, 64 },
{ "sha512", "sha512", 64, 128 },
{ "ripemd160", "rmd160", 20, 64 },
{ "whirlpool", "wp512", 64, 64 },
{ NULL, NULL, 0, 0 }
};

Можна ці зміни не вносити, але тоді потрібно буде тестувати алгоритми з явним зазначенням шифру і режиму (моди). Більш того саме так і тільки так ми можемо перевірити ГОСТ-ті шифри в режимі ECB:

bash-4.3$ /usr/local/bin64/cryptsetup benchmark -cgost-ecb
# Tests are approximate using only memory (no storage IO).
# Algorithm | Key | Encryption | Decryption
gost-ecb 256b 50,4 MiB/s 49,2 MiB/s
bash-4.3$ /usr/local/bin64/cryptsetup benchmark -ckuznyechik-ecb
# Tests are approximate using only memory (no storage IO).
# Algorithm | Key | Encryption | Decryption
kuznyechik-ecb 256b 3,4 MiB/s 3,2 MiB/s
bash-4.3$# Tests are approximate using only memory (no storage IO).
bash-4.3$ 
# Algorithm | Key | Encryption | Decryption
aes-ecb 256b 1361,8 MiB/s 1381,5 MiB/s
bash-4.3$ 

І так з модулями ми розібралися. Тепер можна створювати захищену файлову систему з шифруванням на ГОСТ-ах. Для початку створимо файл test.bin:

# dd if=/dev/zero of=/tmp/test.bin bs=10M count=50
50+0 записів отримано
50+0 записів відправлено
скопійовано 524288000 байт (524 MB), 0,44706 c, 1,2 GB/c
[root@VOrlov_64 tmp]#

Шифровану файлову систему будемо створювати саме в цьому файлі:

[root@VOrlov_64 tmp]# /usr/local/bin64/cryptsetup - kuznyechik-ecb -h stribog256 -y luksFormat /tmp/test.bin

WARNING!
========
This will overwrite data on /tmp/test.bin irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 01234567
Verify passphrase: 01234567
[root@VOrlov_64 tmp]#

Підключення файлової системи:

#cryptsetup luksOpen <пристрій/файл> volume1

І так підключаємо нашу захищену ФС до того volume1:

[root@VOrlov_64 tmp]# /usr/local/bin64/cryptsetup luksOpen /tmp/test.bin volume1
Enter passphrase for /tmp/test.bin: 
[root@VOrlov_64 tmp]#

Далі працюємо з пристроєм /dev/mapper/volume1 як із звичайним розділом жорсткого диска.

Показати параметри файлової системи:

root@VOrlov_64 tmp]# /usr/local/bin64/cryptsetup status /dev/mapper/volume1
/dev/mapper/volume1 is active.
type: LUKS1
cipher: kuznyechik-ecb
keysize: 256 bits
device: /dev/loop0
loop: /tmp/test.bin
offset: 4096 sectors
size: 1019904 sectors
mode: read/write
[root@VOrlov_64 tmp]# 

Після цього досить створити файлову систему (ФС) на пристрої /dev/mapper/volume1:

#mkfs.ext4 /dev/mapper/volume1
#

Монтуємо ФС і працюємо з нею:

#mount /dev/mapper/volume1 /mount/TEST_DM_CRYPT_GOST
#

Все, тепер ми можемо створювати шифровані ФС на ГОСТ 28147-89 (він же ГОСТ Р 34.12-2015 Магма) і ГОСТ Р 34.12-2015 Коник) в режимах CBC, ECB. В якості алгоритму хешування можуть використовуватися ГОСТ Р 34.11-94), stribog256 (ГОСТ Р 34.11-2012 256 біт) і stribog512 (ГОСТ Р 34.11-2012 512бит).
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.