Commit Message

From: Eric Biggers <ebiggers@google.com>
Add support for HPolyC, which is a tweakable, length-preserving
encryption mode that encrypts each message using XChaCha sandwiched
between two passes of Poly1305, and one invocation of a block cipher
such as AES. HPolyC was designed by Paul Crowley and is fully specified
by our paper https://eprint.iacr.org/2018/720.pdf
("HPolyC: length-preserving encryption for entry-level processors").
HPolyC is similar to some existing modes such as XCB, HCTR, HCH, and
HMC, but by necessity it has some novelties. See the paper for details;
this patch only provides a brief overview and an explanation of why
HPolyC is needed in the crypto API.
HPolyC is suitable for disk/file encryption with dm-crypt and fscrypt,
where currently the only other suitable options in the kernel are block
cipher modes such as XTS. Moreover, on low-end devices whose processors
lack AES instructions (e.g. ARM Cortex-A7), AES-XTS is much too slow to
provide an acceptable user experience, resulting in "lightweight" block
ciphers such as Speck being the only viable option on these devices.
However, Speck is considered controversial in some circles; and other
published lightweight block ciphers are too slow in software, haven't
received sufficient cryptanalysis, or have other issues.
Stream ciphers such as ChaCha perform much better but are insecure if
naively used directly in dm-crypt or fscrypt, due to the IV reuse when
data is overwritten. Even restricting the threat model to offline
attacks only isn't enough, since modern flash storage devices make no
guarantee that "overwrites" are really overwrites, due to wear-leveling.
Of course, the ideal solution is to store unique nonces on-disk, ideally
alongside authentication tags. Unfortunately, this is usually
impractical. Hardware support for per-sector metadata is extremely
rare, especially in consumer-grade devices. Software workarounds for
this limitation struggle with the crash consistency problem (often
ignored by academic cryptographers): the crypto metadata MUST be written
atomically with regards to the data. This can be solved with data
journaling, e.g. as dm-integrity does, but that has a severe performance
penalty. Or, for file-level encryption only, per-block metadata is
possible on copy-on-write and log-structured filesystems. However, the
most common Linux filesystems, ext4 and xfs, are neither; and even f2fs
is not fully log-structured as it sometimes overwrites data in-place. A
solution that works for more than just btrfs and zfs is needed.
So, we're mostly stuck with length-preserving encryption for now.
HPolyC therefore provides a way to securely use ChaCha in this context.
Essentially, it uses a hash-XOR-hash construction where a Poly1305 hash
of the tweak and message is used as the nonce for XChaCha, resulting in
a different nonce whenever either the message or tweak is changed. A
block cipher invocation is also needed, but only once per message. Note
that Poly1305 is much faster than ChaCha20, making HPolyC faster than
might be first assumed; still, due to the overhead of the two Poly1305
passes, some users will need ChaCha12 to get acceptable performance.
See the Performance section of the paper. (Currently, ChaCha12 is still
secure, though it has a lower security margin.)
HPolyC has a proof (section 5 of the paper) that shows it is secure if
the underlying primitives are secure, subject to a security bound.
Unless there is a mistake in this proof, one therefore does not need to
"trust" HPolyC; they need only trust XChaCha (which itself has a
security reduction to ChaCha) and AES. Unlike XTS, HPolyC is also a
true wide-block mode, or tweakable super-pseudorandom permutation:
changing one plaintext bit affects all ciphertext bits, and vice versa.
HPolyC supports any message length >= 16 bytes without any need for
"ciphertext stealing". Thus, it will also be useful for fscrypt
filenames encryption, where CBC-CTS is currently used.
We implement HPolyC as a template that wraps existing Poly1305, XChaCha,
and block cipher implementations. So, it can be used with either
XChaCha20 or XChaCha12, and with any block cipher with a 256-bit key and
128-bit block size -- though we recommend and plan to use AES-256, even
on processors without AES instructions, as the block cipher performance
is not critical when it's invoked only once per message. We include
test vectors for HPolyC-XChaCha20-AES and HPolyC-XChaCha12-AES.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
crypto/Kconfig | 28 +++
crypto/Makefile | 1 +
crypto/hpolyc.c | 577 +++++++++++++++++++++++++++++++++++++++++++++++
crypto/testmgr.c | 12 +
crypto/testmgr.h | 158 +++++++++++++
5 files changed, 776 insertions(+)
create mode 100644 crypto/hpolyc.c