NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Re: The official disk encryption guide seems a bit lacking (detailed list of concrete improvement suggestions!)



> From: Greg Troxel <gdt%lexort.com@localhost>
> Date: Wed, 28 Oct 2026 10:04:12 -0400
> 
> The problem with this discussion is that saying disk encryption uses
> "CBC" is very underspecified.  True CBC has an IV, and then further
> blocks use previous state as IVs (leaving out details as not important
> to this discussion).  You can't use that for disk encryption because of
> the need to read/write blocsk with random access.  cgd's "AES-CBC" says
> 
>   The CBC initialization vector for each disk sector is chosen to be the
>   encryption under AES of the little- endian encoding of the disk sector
>   number.
>   
> and reading the web briefly, it seems that choosing to use the encrypted
> block number avoids some of the attacks, and thus this specific form of
> CBC seems stronger than XTS.

This does not meaningfully distinguish CBC from XTS in cgd encryption.

The meaningful difference between them is very modest.  Recall that
the threat model of disk encryption is that the adversary has the
power to read the disk, and possibly some older snapshots of (part of)
the disk, e.g. if they can read old reassigned sector content.  (The
power to write to the disk is outside the threat model.)

Under this threat model, what can the adversary observe?

First, the adversary can always tell which disk sectors changed and
which disk sectors did not change.  This is always the case for disk
encryption, where disk sectors can be written independently.

Second, with CBC, the adversary can tell _how long a prefix_, in units
of cipher blocks, did not change, because once one cipher block
changes, all subsequent cipher blocks are randomized, whether or not
they changed.

For illustration, suppose you have a (512-byte) disk sector which
breaks into (16-byte) cipher blocks like so:

             i:  0   1   2   3   4
 Plaintext P_i: foo bar baz qux zot
Ciphertext C_i: cVj 1PG 5RH vx8 3RC

What happens if you change `baz' to `bax' in block 2?  The updated
disk sector becomes:

             i:  0   1   2   3   4
 Plaintext P_i: foo bar bax qux zot
Ciphertext C_i: cVj 1PG w-D Qqs lqv
                        ^^^ ^^^ ^^^

(Blocks whose ciphertext changed are underlined.)

This is because C_i = AES_k(C_{i-1} + P_i) -- each ciphertext block
depends on all the previous plaintext blocks.  (Here + is xor and
C_{-1} = AES_k(blkno) is the initialization vector.)  The adversary
can tell that blocks 0 and 1 did not change, and that block 2 did
change, but can't tell whether blocks 3 or 4 changed or not.

In contrast, XTS encrypts each block within each sector independently.
So if you change `baz' to `bax' in block 2, the updated disk sector
becomes:

             i:  0   1   2   3   4
 Plaintext P_i: foo bar bax qux zot
Ciphertext C_i: cVj 1PG w-D vx8 3RC
                        ^^^

This is because C_i = AES_k(tweak*alpha^i + P_i) -- each ciphertext
block is independent of the other ciphertext blocks.  (Here alpha^i
and + are arithmetic in GF(2^128), and tweak = AES_{k'}(blkno), and
alpha is the unit monic polynomial of degree 1 in GF(2^128).  Using an
independent key k' to derive the tweak is not significant for security
but was baked into the design of XTS for reasons unclear to me.)  The
adversary can tell that only block 2 changed.

This difference in security is extremely minor.  It is not worth any
serious publication in cryptography literature.  It is not worth the
amount of argument it has provoked on the internet.  It is not worth
any extended discussion in user-facing documentation.  They're both
suboptimal but fine.  CBC was there first and is marginally less
suboptimal than XTS.  The only reason it may have been worthwhile for
us to have added XTS at all is that some users may see XTS named in
NIST standards and think the US federal government branding might give
an advantage to ticking that box.

Both constructions fail to meet the criterion of a `wide-block
tweakable block cipher' in the cryptography literature, i.e., a disk
encryption scheme that encrypts the entire disk sector as a unit.
Formally, this is a family of functions

E_k(i, x)

mapping a plaintext disk sector content x at sector number i to a
ciphertext disk sector content E_k(i, x) having the property that,
under random k, for each sector number i, the function

x |---> E_k(i, x)

is indistinguishable from an independent uniform random permutation of
disk sector content.  CBC and XTS fail to meet this criterion
precisely because of the distinguishers I described above.

Unlike CBC and XTS, Adiantum _is_ designed to be a wide-block
tweakable block cipher.  That is, if you change any bit in a disk
sector, the _entire ciphertext_ for that sector is randomized by
Adiantum:

             i:  0   1   2   3   4
 Plaintext P_i: foo bar bax qux zot
Ciphertext C_i: NDs cfS w-D Qqs lqv
                ^^^ ^^^ ^^^ ^^^ ^^^

And there is a theorem[1] (published in the serious open access
peer-reviewed cryptography literature, albeit by the designers of
Adiantum), built out of straightforward components that are
well-understood by cryptographers, that any way to distinguish
Adiantum from uniform random choice of tweakable 512-byte permutation
necessarily leads to a way (of not much more computational cost) to
distinguish AES from a uniform random choice of 128-bit permutation or
a way to distinguish ChaCha from a uniform random choice of
128-bit-to-512-bit function.

This -- together with Adiantum's good performance, and tendency not to
leak through cache-timing side channels, in software implementations
on CPUs without hardware AES acceleration -- is why Google's
cryptography team decided it was a good choice to deploy Adiantum on
what are probably millions if not billions of arm32 devices in
Android.  (It's also why I made the choice to add Adiantum to cgd(4):
https://mail-index.netbsd.org/tech-crypto/2020/06/18/msg000782.html)


[1] Paul Crowley and Eric Biggers, `Adiantum: length-preserving
    encryption for entry-level processors', IACR Transactions on
    Symmetric Cryptology 2018(4), pp. 39--61.
    https://doi.org/10.13154/tosc.v2018.i4.39-61


Home | Main Index | Thread Index | Old Index