Hello,
I would like to ask for some clarifications regarding randomness and speed of encrypted data, and consequences of reversing the direction of the encryption. Sorry for a long email, but I think the issues are related so it is better than separate emails. My questions are related to the answers I found in https://www.saout.de/pipermail/dm-crypt/2020-June/006531.html
I was under the assumption that the result of block device encryption should be indistinguishable from random data. If the encryption (data transformation) is supposed to work in both directions, it should produce random like output, correct?
echo "0 100000000 zero" | dmsetup create zero1
echo "0 $(blockdev --getsize /dev/mapper/zero1) crypt \
aes-xts-plain64:sha512 $(sha512sum /proc/sys/kernel/random/uuid | cut -b 1-128) \
0 /dev/mapper/zero1 0" | dmsetup create crypto1
rngtest -b 10000 < /dev/mapper/crypto1
dieharder -a -g 200 < /dev/mapper/crypto1
(failures/weak results seem comparable to /dev/urandom,
or can you see a measurable difference?)
echo "0 100000000 zero" | dmsetup create zero2
echo "0 $(blockdev --getsize /dev/mapper/zero2) crypt \
aes-cbc-essiv:sha256 $(sha256sum /proc/sys/kernel/random/uuid | cut -b 1-64) \
0 /dev/mapper/zero2 0" | dmsetup create crypto2
rngtest -b 10000 < /dev/mapper/crypto2
(just failures, the data is visible pattern)
Is the reversed encryption strong? Why is the reversed aes-xts-plain64:sha512 generating random like output, but the reversed aes-cbc-essiv:sha256 is a pattern? Is there an explanation?
I would like to ask for some clarifications regarding randomness and speed of encrypted data, and consequences of reversing the direction of the encryption. Sorry for a long email, but I think the issues are related so it is better than separate emails. My questions are related to the answers I found in https://www.saout.de/pipermail/dm-crypt/2020-June/006531.html
I was under the assumption that the result of block device encryption should be indistinguishable from random data. If the encryption (data transformation) is supposed to work in both directions, it should produce random like output, correct?
echo "0 100000000 zero" | dmsetup create zero1
echo "0 $(blockdev --getsize /dev/mapper/zero1) crypt \
aes-xts-plain64:sha512 $(sha512sum /proc/sys/kernel/random/uuid | cut -b 1-128) \
0 /dev/mapper/zero1 0" | dmsetup create crypto1
rngtest -b 10000 < /dev/mapper/crypto1
dieharder -a -g 200 < /dev/mapper/crypto1
(failures/weak results seem comparable to /dev/urandom,
or can you see a measurable difference?)
echo "0 100000000 zero" | dmsetup create zero2
echo "0 $(blockdev --getsize /dev/mapper/zero2) crypt \
aes-cbc-essiv:sha256 $(sha256sum /proc/sys/kernel/random/uuid | cut -b 1-64) \
0 /dev/mapper/zero2 0" | dmsetup create crypto2
rngtest -b 10000 < /dev/mapper/crypto2
(just failures, the data is visible pattern)
Is the reversed encryption strong? Why is the reversed aes-xts-plain64:sha512 generating random like output, but the reversed aes-cbc-essiv:sha256 is a pattern? Is there an explanation?
The reverse aes-xts-plain64:sha512 is quite fast (I tested on Dell Optiplex 3020, quad Core i5-4590 3.30GHz, AESNI, kernel 4.14.150)
pv /dev/mapper/crypto1 > /dev/null
(1.8 GB/sec, for previous aes-xts-plain64:sha512 dm-crypt table)
When I compare to other ways of generating random data, I get:
openssl enc -chacha20 -nosalt -pass file:/proc/sys/kernel/random/uuid \
< /dev/zero | pv > /dev/null
(1.6 GB/sec)
/dev/urandom gives me 245 MB/sec on the same hardware
TrueRNG v3 produces 50KB/sec
(https://www.amazon.com/TrueRNG-V3-Hardware-Random-Generator/dp/B01KR2JHTA)
I do not know about any faster way of generating good pseudo-random data than aes-xts-plain64:sha512 dm-crypt table. But on the list it was said that /dev/urandom has gotten a lot faster. Am I missing something why /dev/urandom is slow for me? Could I be missing any important kernel options?
If I wanted to generate RSA key pairs I would go with a hardware generator, but if I want to fill a large space with pseudo-random noise quickly then aes-xts-plain64:sha512 table seems to be the fastest way. Or am I wrong?
pv /dev/mapper/crypto1 > /dev/null
(1.8 GB/sec, for previous aes-xts-plain64:sha512 dm-crypt table)
When I compare to other ways of generating random data, I get:
openssl enc -chacha20 -nosalt -pass file:/proc/sys/kernel/random/uuid \
< /dev/zero | pv > /dev/null
(1.6 GB/sec)
/dev/urandom gives me 245 MB/sec on the same hardware
TrueRNG v3 produces 50KB/sec
(https://www.amazon.com/TrueRNG-V3-Hardware-Random-Generator/dp/B01KR2JHTA)
I do not know about any faster way of generating good pseudo-random data than aes-xts-plain64:sha512 dm-crypt table. But on the list it was said that /dev/urandom has gotten a lot faster. Am I missing something why /dev/urandom is slow for me? Could I be missing any important kernel options?
If I wanted to generate RSA key pairs I would go with a hardware generator, but if I want to fill a large space with pseudo-random noise quickly then aes-xts-plain64:sha512 table seems to be the fastest way. Or am I wrong?
I also do not understand why the AESNI encryption speed changed when I upgrade the kernel from 4.14 to 5.4
The speed of /dev/urandom is about the same and 4.14 to 5.4.
pv /dev/urandom > /dev/null
- single run 1x 245 MB/sec
- dual run 2x 95 MB/sec
- triple run 3x 60 MB/sec
- quad run 4x 45 MB/sec
But for AES it is different
for X in 1 2 3 4; do
echo "0 4294967296 zero" | dmsetup create zero${X}
echo "0 $(blockdev --getsize /dev/mapper/zero${X}) crypt \
aes-xts-plain64:sha512 $(sha512sum /proc/sys/kernel/random/uuid | cut -b 1-128) \
0 /dev/mapper/zero${X} 0" | dmsetup create crypto${X}
done
pv /dev/mapper/cryptoX > /dev/null
Rough numbers I get for 4.14.150
- single run 1x 1800 MB/sec
- dual run 2x 1040 MB/sec
- triple run 3x 810 MB/sec
- quad run 4x 680 MB/sec
but for 5.4.58
- single run 1x 500 MB/sec
- dual run 2x 500 MB/sec
- triple run 3x 500 MB/sec
- quad run 4x 500 MB/sec
Is there a reason for this?
The speed of /dev/urandom is about the same and 4.14 to 5.4.
pv /dev/urandom > /dev/null
- single run 1x 245 MB/sec
- dual run 2x 95 MB/sec
- triple run 3x 60 MB/sec
- quad run 4x 45 MB/sec
But for AES it is different
for X in 1 2 3 4; do
echo "0 4294967296 zero" | dmsetup create zero${X}
echo "0 $(blockdev --getsize /dev/mapper/zero${X}) crypt \
aes-xts-plain64:sha512 $(sha512sum /proc/sys/kernel/random/uuid | cut -b 1-128) \
0 /dev/mapper/zero${X} 0" | dmsetup create crypto${X}
done
pv /dev/mapper/cryptoX > /dev/null
Rough numbers I get for 4.14.150
- single run 1x 1800 MB/sec
- dual run 2x 1040 MB/sec
- triple run 3x 810 MB/sec
- quad run 4x 680 MB/sec
but for 5.4.58
- single run 1x 500 MB/sec
- dual run 2x 500 MB/sec
- triple run 3x 500 MB/sec
- quad run 4x 500 MB/sec
Is there a reason for this?
The last thing I wanted to point out is that I noticed no real interest in inverted dm-crypt map. Do you think it is completely useless?
Somewhere in the past I found a discussion (sorry I do not have the link) about possible use of inverted dm-crypt map for encrypted backups of plain data (block based, possibly incremental, possibly onto a tape). Also someone asked on dm-crypt about "inverted" usage for NBD encryption/decryption
https://www.saout.de/pipermail/dm-crypt/2013-August/003474.html
https://www.saout.de/pipermail/dm-crypt/2013-August/003479.html
I thought it might be useful to have an option to encrypt the data by reading from a dm-crypt device (read data and write somewhere) and then being able to decrypt the data by another dm-crypt table (read again and get the original data).
If I try a quick and dirty way of adding another cipher and reversing encrypt/decrypt in recent 5.4 kernel
--- linux-5.4.56/arch/x86/crypto/aesni-intel_glue.c-orig
+++ linux-5.4.56/arch/x86/crypto/aesni-intel_glue.c
@@ -987,6 +987,22 @@ static struct skcipher_alg aesni_skciphers
.setkey = xts_aesni_setkey,
.encrypt = xts_encrypt,
.decrypt = xts_decrypt,
Somewhere in the past I found a discussion (sorry I do not have the link) about possible use of inverted dm-crypt map for encrypted backups of plain data (block based, possibly incremental, possibly onto a tape). Also someone asked on dm-crypt about "inverted" usage for NBD encryption/decryption
https://www.saout.de/pipermail/dm-crypt/2013-August/003474.html
https://www.saout.de/pipermail/dm-crypt/2013-August/003479.html
I thought it might be useful to have an option to encrypt the data by reading from a dm-crypt device (read data and write somewhere) and then being able to decrypt the data by another dm-crypt table (read again and get the original data).
If I try a quick and dirty way of adding another cipher and reversing encrypt/decrypt in recent 5.4 kernel
--- linux-5.4.56/arch/x86/crypto/aesni-intel_glue.c-orig
+++ linux-5.4.56/arch/x86/crypto/aesni-intel_glue.c
@@ -987,6 +987,22 @@ static struct skcipher_alg aesni_skciphers
.setkey = xts_aesni_setkey,
.encrypt = xts_encrypt,
.decrypt = xts_decrypt,
+ }, {
+ .base = {
+ .cra_name = "__xts(aesr)",
+ .cra_driver_name = "__xts-aesr-aesni",
+ .cra_priority = 401,
+ .cra_flags = CRYPTO_ALG_INTERNAL,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = XTS_AES_CTX_SIZE,
+ .cra_module = THIS_MODULE,
+ },
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = xts_aesni_setkey,
+ .encrypt = xts_decrypt,
+ .decrypt = xts_encrypt,
#endif
}
};
echo "0 100000000 zero" | dmsetup create zero
echo "0 $(blockdev --getsize /dev/mapper/zero) crypt \
aesr-xts-plain64:sha512 $(sha512sum /bin/bash | cut -b 1-128) \
0 /dev/mapper/zero 0" | dmsetup create crypto
echo "0 $(blockdev --getsize /dev/mapper/crypto) crypt \
aes-xts-plain64:sha512 $(sha512sum /bin/bash | cut -b 1-128) \
0 /dev/mapper/crypto 0" | dmsetup create crypto2
od /dev/mapper/crypto2
(zeroes)
+ .base = {
+ .cra_name = "__xts(aesr)",
+ .cra_driver_name = "__xts-aesr-aesni",
+ .cra_priority = 401,
+ .cra_flags = CRYPTO_ALG_INTERNAL,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = XTS_AES_CTX_SIZE,
+ .cra_module = THIS_MODULE,
+ },
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = xts_aesni_setkey,
+ .encrypt = xts_decrypt,
+ .decrypt = xts_encrypt,
#endif
}
};
echo "0 100000000 zero" | dmsetup create zero
echo "0 $(blockdev --getsize /dev/mapper/zero) crypt \
aesr-xts-plain64:sha512 $(sha512sum /bin/bash | cut -b 1-128) \
0 /dev/mapper/zero 0" | dmsetup create crypto
echo "0 $(blockdev --getsize /dev/mapper/crypto) crypt \
aes-xts-plain64:sha512 $(sha512sum /bin/bash | cut -b 1-128) \
0 /dev/mapper/crypto 0" | dmsetup create crypto2
od /dev/mapper/crypto2
(zeroes)
It seems to work both ways aesr-xts-plain64 / aes-xts-plain64, or aes-xts-plain64 / aesr-xts-plain64.
In case of transferring such encrypted data via NBD or iSCSI you mentioned replay attack - if the attacker has access to the network the data can be modified. Not sure if this would be the best usage example, But with checksumming (e.g. BTRFS with checksums) this would be difficult, or not?
Or if the attacker has access to multiple versions (e.g. incremental backups) of the encrypted data, then he can analyze changes. Does this make XTS encryption problematic/unusable and the whole idea of inverted dm-crypt useless?
Thank you very much,
John
In case of transferring such encrypted data via NBD or iSCSI you mentioned replay attack - if the attacker has access to the network the data can be modified. Not sure if this would be the best usage example, But with checksumming (e.g. BTRFS with checksums) this would be difficult, or not?
Or if the attacker has access to multiple versions (e.g. incremental backups) of the encrypted data, then he can analyze changes. Does this make XTS encryption problematic/unusable and the whole idea of inverted dm-crypt useless?
Thank you very much,
John
_______________________________________________ dm-crypt mailing list dm-crypt@xxxxxxxx https://www.saout.de/mailman/listinfo/dm-crypt