For most disk I/O driver models, there is a "down path" and an "up path". When writing, the sector address and plaintext are passed down the chain from one driver to another. The encryption driver transforms the plaintext to ciphertext and passes it to the next driver downstream until it eventually reaches the disk; a status code is then propagated upstream. When reading, the sector address is propagated downstream until it eventually reaches the disk. The disk returns the requested sector, which is then propagated upstream. The encryption driver transforms the ciphertext to plaintext and passes it upstream until it eventually reaches the application.
SectorCrypt works by employing a tweakable wide block cipher (Xoofff-WBC) to encipher each sector.
Sector-level disk encryption is challenging because it does not allow for any expansion; i.e., there is no room for a nonce or authentication tag. The solution is to use a wide block cipher to reversibly map (e.g. 4K) blocks to other (4K) blocks in a way that is computationally indistinguishable from true randomness to an adversary who does not know the secret key. As input, we have the secret key and the sector plaintext. The idea is to split the sector plaintext into two halves, and use the halves to encrypt each other. Clearly, some sacrifices must be made: without a nonce, it is not possible to achieve perfect semantic security nor prevent replay attacks (e.g. copying in a sector from a previous state); without an authentication tag, it is not possible to achieve surefire authentication. However, flipping even a single bit in an enciphered sector will cause it to decipher to a completely different plaintext (i.e., random garbage). In other words, this mode has the advantage of being non-malleable. Thanks to the fact that the first and last rounds need only expand a short one-block tag, the construction performs two read passes over the input and only one write pass.
Consider an adversary who copies an enciphered sector from one location to another. It could be problematic if an enciphered sector deciphers to identical plaintext regardless of its location on the disk. To mitigate this concern, we employ a tweak W. The tweak is a public value that is plugged into the wide block cipher to change its mapping on the fly. For the application of disk encryption, it is natural to use the sector address as the tweak. This way, copying a sector to another location offers no gain: instead, the copied sector is deciphered under a different tweak and thus yields random garbage. In addition, the tweak helps provide a level of semantic security: even if multiple sectors hold identical plaintext, the enciphered output is uncorrelated due to the differing tweak.
To demonstrate the wide block cipher, I created a small disk of size approximately 256 MB. I inserted my disk encryption driver into the chain of drivers for this disk, and then initialized and formatted the disk.
Next, I created a very large bitmap to fill a majority of the disk. I did this to simplify the demonstration.
From outside the VM, I opened the disk in a disk editor. I then seeked to a sector somewhere near the middle. Note how even though an empty bitmap fills the disk, the sectors appear to be full of random bits. This is because the wide block cipher reversibly transforms blocks to other blocks in a uniformly random way, tweaked by the sector address. This effectively prevents any patterns from appearing, regardless of disk contents.
I then modified a single byte in a single sector using the disk editor.
Back in the VM, I opened the bitmap. Since one 512-byte sector underpins 171 24-bit pixels, we would expect to see a string of 171 random-looking pixels somewhere within the bitmap. Sure enough, this is exactly what we see. This demonstrates that tampering with a sector causes it to decipher to a completely different plaintext. This non-malleable property provides some protection against an adversary modifying sectors from the outside.