CryptoAPI Linux kernel: development and application of Russian cryptography
CryptoAPI is an implementation of cryptographic algorithms with access to them both from the kernel itself and from 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 with the following commands:
As can be seen 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 a 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, the encryption modes CBC, ECB will be used.
Aes-generic and shaxxx-generic modules are considered as prototypes of these modules. Accordingly, the following modules should be implemented for Russian cryptography:
The main question is where to get the implementation of Russian cryptographic algorithms? One option is OpenSSL and support for GOST algorithms in engine gost. However, to date, the implementation of only GOST 28147-89 and GOST R 34.11-94 is supported. More acceptable is the support of Russian cryptographic algorithms in the GCrypt-1.7.0 project , which already has 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 a length 512 bit hash (STRIBOG-512).
As for Grasshopper, the article on Habrahabr “GOST R 34.12-15 on SSE2, or Grasshopper Is Not So Bad” will help here .
The modules were assembled for the following Linux kernel:
Other kernels may require some changes. We will show the assembly of CryptoAPI modules that implement Russian crypto algorithms using the stribog256-generic module as an example (GOST R 34.11-2012 with a hash length of aaa 256 bits).
So the Makefile:
We also list the contents of the stribog256_generic directory:
To build the module, just enter the stribog256 directory and run the make command:
The code for the stribog256_generic.c module is as follows:
According to a similar scheme, the remaining modules are prepared and assembled:
Now they can be loaded into the system:
Now let's see what algorithms CryptoAPI supports:
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 are added only for the testing team)
2. ./cryptsetup/lib/crypto_backend/crypto_cipher_kernel.c
3. ./cryptsetup/lib/crypto_backend/crypto_kernel.c
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 and only way we can check the GOST ciphers in ECB mode:
And so we figured out the modules. Now you can create a secure file system with encryption on GOST. First, create the test.bin file:
We will create the encrypted file system in this file:
File System Connection:
And so we connect our protected FS to volume1:
Next, we work with the device / dev / mapper / volume1 as with a regular hard disk partition.
View file system options:
After that, just create a file system (FS) on the device / dev / mapper / volume1:
We mount the FS and work with it:
That's it, now we can create encrypted FS on GOST 28147-89 (aka GOST R 34.12-2015 Magma) and GOST R 34.12-2015 Grasshopper) in CBC, ECB modes. As a hashing algorithm, GOST R 34.11-94), stribog256 (GOST R 34.11-2012 256 bit) and stribog512 (GOST R 34.11-2012 512 bit) can be used.
The ultimate goal of this material will be to create an encrypted file system using Russian cryptographic algorithms:
- The development of the value of the hash function in accordance with the requirements of GOST R 34.11-94 / GOST R 34.11-2012 “Information technology. Cryptographic information security. Hashing Function ”;
- Encrypting / decrypting data and calculating the insert in accordance with the requirements of GOST 28147-89 “Information processing systems. Cryptographic protection ”;
- Encryption / decryption of data by encryption algorithms “Grasshopper” (KUZmin, NECHAEV AND COMPANY) and “Magma” in accordance with the requirements of “GOST R 34.12-2015 Information technology. Cryptographic information security. Block Ciphers ”and“ GOST R 34.13-2015 Information Technology. Cryptographic information security. Operating modes of block ciphers. "
You can see which cryptographic algorithms can be used to create an encrypted file system with 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 can be seen 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 a 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, the encryption modes CBC, ECB will be used.
Aes-generic and shaxxx-generic modules are considered as prototypes of these modules. Accordingly, the following modules should be implemented for Russian cryptography:
- gosthash-generic (GOST K 34.11-94);
- stribog256-generic (GOST R 34.11-2012 with a hash length of 256 bits);
- stribog512-generic (GOST R 34.11-2012 with a hash length of 512 bits);
- gost-generic (GOST 28147-89, Magma);
- kuznyechik-generic ("Grasshopper").
The main question is where to get the implementation of Russian cryptographic algorithms? One option is OpenSSL and support for GOST algorithms in engine gost. However, to date, the implementation of only GOST 28147-89 and GOST R 34.11-94 is supported. More acceptable is the support of Russian cryptographic algorithms in the GCrypt-1.7.0 project , which already has 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 a length 512 bit hash (STRIBOG-512).
As for Grasshopper, the article on Habrahabr “GOST R 34.12-15 on SSE2, or Grasshopper Is Not So Bad” will help here .
The modules were assembled 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 that implement Russian crypto algorithms using the stribog256-generic module as an example (GOST R 34.11-2012 with a hash length of aaa 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 list the contents of the stribog256_generic directory:
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 the module, just enter the stribog256 directory and run 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 is as follows:
The code for the stribog256_generic.c module is as follows:
/
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
#include
#include
#include
#include
#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$
According to a similar scheme, the remaining 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 are added only for the testing team)
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 and only way 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 figured out the modules. Now you can create a secure file system with encryption on GOST. First, create the 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 protected 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 options:
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, just create a file system (FS) on the device / dev / mapper / volume1:
#mkfs.ext4 /dev/mapper/volume1
#
We mount the FS and work with it:
#mount /dev/mapper/volume1 /mount/TEST_DM_CRYPT_GOST
#
That's it, now we can create encrypted FS on GOST 28147-89 (aka GOST R 34.12-2015 Magma) and GOST R 34.12-2015 Grasshopper) in CBC, ECB modes. As a hashing algorithm, GOST R 34.11-94), stribog256 (GOST R 34.11-2012 256 bit) and stribog512 (GOST R 34.11-2012 512 bit) can be used.