📜 ⬆️ ⬇️

CryptoAPI of the Linux kernel: development and application of Russian cryptography

image CryptoAPI is an implementation of cryptographic algorithms that provide access to them from both the kernel itself and application software. The most prominent representatives of this software are IPSEC (VPN) and dm-crypt (encrypted file system).

The ultimate goal of this material will be to create an encrypted file system using Russian cryptographic algorithms:


You can see which cryptographic algorithms can be used to create an encrypted file system by the following commands:

bash-4.3$ /usr/local/bin64/cryptsetup benchmark # Tests are approximate using memory only (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 memory only (no storage IO). # Algorithm | Key | Encryption | Decryption aes-ecb 256b 1422,6 MiB/s 1437,6 MiB/s bash-4.3$ 

As you can see from this example, the AES encryption algorithm in CBC and ECB modes, as well as the hash functions sha1, sha256 and sha512 can be used to create an encrypted file system.
')
To switch to Russian cryptography, we need to add modules to the Linux kernel that implement hash according to GOST R 34.11-94, GOST R 34.11-2012 with a hash length of 256 bits (STRIBOG-256) and a hash length of 512 bits (STRIBOG-512).

As encryption algorithms, GOST 28147-89 should be implemented, it is actually the Magma algorithm (GOST R 34.12-2015), as well as the Grasshopper algorithm (GOST R 34.12-2015). For verification, CBC and ECB encryption modes will be used.

As prototypes of these modules are considered modules aes-generic and shaxxx-generic. Accordingly, for Russian cryptography the following modules should be implemented:


The main question is where to get the implementation of Russian cryptographic algorithms? One option is OpenSSL and support for GOST-s algorithms in engine gost. However, until now, the implementation of GOST 28147-89 and GOST R 34.11-94 is supported only. It is more acceptable to support Russian cryptographic algorithms in the GCrypt-1.7.0 project , where there is already support for the Magma algorithm (GOST R 34.12-2015) and GOST R 34.11-2012 with a hash length of 256 bits (STRIBOG-256) and length 512-bit hash (STRIBOG-512).

As for the "Grasshopper", the article on Habrahabr "GOST R 34.12-15 on SSE2, or the Grasshopper is Not So Bad" will help here.

Modules were built for the following Linux kernel:

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

Other kernels may require some changes. We will show the assembly of CryptoAPI modules implementing Russian crypto-algorithms using the example of the stribog256-generic module (GOST R 34.11-2012 with a hash length of 256 bits).

So, the 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 

We also indicate the contents of the stribog256_generic catalog:

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

To build a module, it is enough to enter the stribog256 directory and issue the make command:

 bash-4.3$ make make -C /lib/modules/4.4.39-desktop-1.mga5/build M=/home/a513/DM_CRYPT/dm-crypt/stribog256 modules 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$ 

The code for the stribog256_generic.c module looks like this:

The code for the stribog256_generic.c module looks like this:
 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); // Wipe context 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$ 


In a similar way, other modules are prepared and assembled:

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

Now they can be loaded into the system:

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

Now let's see what algorithms CryptoAPI supports:

 bash-4.3$ /usr/local/bin64/cryptsetup benchmark # Tests are approximate using memory only (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$ 

In order for GOST algorithms to appear during testing (benchmark parameter), it is enough to make changes to the following files in the cryptsetup utility:

1. ./cryptsetup/src/cryptsetup.c (lines added for testing team only)

 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 } }; 

You can not make these changes, but then you need to test the algorithms with an explicit indication of the cipher and mode (mode). Moreover, this is the only way that we can check the GOST ciphers in ECB mode:

 bash-4.3$ /usr/local/bin64/cryptsetup benchmark -cgost-ecb # Tests are approximate using memory only (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 memory only (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 memory only (no storage IO). bash-4.3$ # Algorithm | Key | Encryption | Decryption aes-ecb 256b 1361,8 MiB/s 1381,5 MiB/s bash-4.3$ 

And so we dealt with the modules. Now you can create a secure file system with encryption on GOST. First, let's create a test.bin file:

 # 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]# 

We will create the encrypted file system in this file:

 [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]# 

File system connection:

 #cryptsetup luksOpen </> volume1 

And so we connect our secure FS to volume1:

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

Next, we work with the device / dev / mapper / volume1 as with a regular hard disk partition.

View file system settings:

 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]# 

After that, it is enough to create a file system (FS) on the device / dev / mapper / volume1:

 #mkfs.ext4 /dev/mapper/volume1 # 

Mount the FS and work with it:

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

Everything, now we can create encrypted FSs in the GOST 28147-89 (aka GOST R 34.12-2015 Magma) and GOST R 34.12-2015 Grasshopper) in the CBC, ECB modes. As a hashing algorithm, GOST R 34.11-94, stribog256 (GOST R 34.11-2012 256 bits) and stribog512 (GOST R 34.11-2012 512bit) can be used.

Source: https://habr.com/ru/post/320966/


All Articles