avatarProf Bill Buchanan OBE FRSE

Summary

The web content discusses the intricacies of full disk encryption (FDE), particularly the XEX-based tweaked-codebook mode with ciphertext stealing (XTS), and its implementation in cybersecurity.

Abstract

The article delves into the technical aspects of full disk encryption, emphasizing the importance of understanding the underlying encryption methods used in cybersecurity. It explains how AES encryption blocks are fitted into disk sectors and the necessity of ciphertext stealing to fill empty blocks. The author contrasts Electronic Code Book (EBC) and Cipher Block Chaining (CBC) modes of block encryption with XTS, which is tailored for disk encryption due to its ability to handle random sector access without the need for sequential block processing. The XTS method uses a tweak derived from the encryption key and sector number to encrypt data, providing a unique ciphertext for each sector, thus enhancing security. The article also provides a brief Go code example illustrating the use of XTS in practice and concludes by urging cybersecurity professionals to have a thorough understanding of encryption methods like XTS, especially when recommending tools like encrypted USB sticks or Microsoft BitLocker.

Opinions

  • The author expresses concern over the depth of knowledge within certain areas of cybersecurity, particularly regarding the specifics of encryption methods used in full disk encryption.
  • There is an implied criticism of industry professionals who lack detailed knowledge about the encryption methods they recommend, likening it to an architect's ignorance of building material strengths.
  • The author advocates for the use of XTS in full disk encryption, acknowledging it as the de-facto standard and a practical solution for encrypting disk sectors.
  • The article suggests that while XTS is widely used and effective, it is not without limitations, and professionals should be aware of these when implementing full disk encryption solutions.
  • A strong emphasis is placed on the importance of encrypting files at their source in addition to using full disk encryption for comprehensive data security.

Who Needs a Tweak? Meet Full Disk Encryption

XEX-based tweaked-codebook mode with ciphertext stealing

I was discussing with an industry professional about the storing of files on an encrypted USB device, and I said, “But how are the files encrypted on the device?”, “I don’t know”, “Is it AES, and what’s the key size?”, “I don’t know”. I thus sometimes worry about the depth of knowledge applied within some areas of cybersecurity. To me, this is similar to an architect not actually knowing the strength of the bricks that they are designing with. So let’s have a look at what actually happens with full-disk encryption.

Before we start, it is important to know that AES encryption deals with 128-bit (16 bytes) encryption blocks, whereas disks typically deal with 512-byte segments. We must thus fit 32 AES blocks into our disk segments (Figure 1). Sometimes we will have empty blocks, so we must fill these with “ciphertext stealing” blocks.

With non-full disk encryption, we typically create an AES key and encrypt the file. The encryption key is typically generated from a passphrase, and uses a key derivation function (KDF). We can also create a key pair (a public key and a private key), and then encrypt the key with our public key, and then decrypt it with our private key. With this we are thus encrypting at a file level, and which will be fairly inefficient, as we need to read the whole file in at a time. With full disk encryption, we typically read from sectors on the disk, and in a random manner.

The smallest addressable element of a disk is a block — and which is typically around 512 bytes — and these are arranged into sectors:

Disk /dev/sda: 640.1 GB, 640135028736 bytes
255 heads, 63 sectors/track, 77825 cylinders, total 1250263728 sectors
Units = sectors of 1  512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064a1a

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1              63     2040254     1020096   83  Linux
/dev/sda2         2040255    22523129    10241437+  82  Linux swap / Solaris
/dev/sda4        22523191  1250258624   613867717    5  Extended

Two of the most common modes of block encryption are Electronic Code Book (EBC) and Cipher Block Chaining (CBC). With ECB we basically take blocks of 128 bits, and then cipher these:

Unfortunately the same input in the blocks will lead to the same cipher output, and leaves us open to a range of cipher attacks. With CBC the blocks are chained together, and where the output of one block feeds into another one. The IV makes sure that for the same input plaintext, we will have a different ciphertext. We initially take an IV and then EX-OR it with the first plaintext block, and then encrypt this. This block is then EX-OR’ed with the next plain text block, and so it continues:

Within a disk system, this is a problem, as we need to be able to randomly access sectors, without having to read all the other sectors. XTS (XEX-based tweaked-codebook mode with ciphertext stealing) is a fairly common method which overcomes these problems. For this it uses a “tweak”, and where we take an encryption key, and encrypt the sector number, and use this to X-OR the data within the sector.

We first define two keys (K1 and K2). If we use 128-bit AES, then we generate two keys which are 128 bits long. Next we define an input block (P) and a sector number (i) and a block number (j), and create a tweak (X ):

Note, ⊗ is a multiplication (within a finite field of 127). The ciphertext (C) for each block is then:

With ⊕, we have an EX-OR operation. To decrypt, we do the opposite:

The plaintext (P) for each block is then:

In this way, we just need the encryption key, and the sector number, in order to encrypt and decrypt. The tweak acts as an IV. This process is illustrated by Figure 2.

Figure 2: Reference: [here]

Overall a sector of a size of 512 bytes will store 32, 16-byte AES-blocks (a block in AES is 128 bits long). In this way, for a single sector, we call the encrypt/decrypt method 32 times using the same i value, but different j values (0 to 31).

Most fully encrypted disks now use the AES-XTS block cipher mode, and which is defined in IEEE Standard 1619. It is now implemented in many USB encrypted devices, and with Microsoft Bitlocker for Windows 10, TrueCrypt, VeraCrypt, OpenSSL, and Mac OSX FileVault.

The following is some sample Go code [here]:

package main
import (
"golang.org/x/crypto/xts"
    "crypto/aes"
    "encoding/hex"
    "crypto/sha256"
    "bytes"
"fmt"
"os"
"strconv"
)
func PKCS5Padding(ciphertext []byte, bSize int) []byte {
    padding := bSize - len(ciphertext)%bSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}
func PKCS5Trimming(encrypt []byte) []byte {
    padding := encrypt[len(encrypt)-1]
    return encrypt[:len(encrypt)-int(padding)]
}
func getSHA1(s string) []byte {
        hasher := sha256.New()
        hasher.Write([]byte(s))
    key:=hasher.Sum(nil)
    return key
}
func main() {
var sector uint64
    password:="test"
    message:="hello"
    sector=100
    argCount := len(os.Args[1:])
    if (argCount>0) {message = string(os.Args[1])}
        if (argCount>1) {password = string(os.Args[2])}
        if (argCount>2) {sector,_ = strconv.ParseUint(os.Args[3],10,64)}
    key:=getSHA1(password)
    c, _ := xts.NewCipher(aes.NewCipher,key )
        fmt.Printf("Message:\t%s\nPassword:\t%s\nSector:\t\t%d\n\n\nKey (hex):\t%s\n",message,password,sector,hex.EncodeToString(key))
    plaintext := PKCS5Padding([]byte(message),16)
    ciphertext := make([]byte, len(plaintext))
    c.Encrypt(ciphertext, plaintext, sector)
        fmt.Printf("Cipher:\t\t%s\n",hex.EncodeToString(ciphertext))
    decrypted := make([]byte, len(ciphertext))
    c.Decrypt(decrypted, ciphertext, sector)
    fmt.Printf("Decrypted:\t%s",string(PKCS5Trimming(decrypted)))
}

A sample run is [here]:

Message:    Hello
Password:   qwerty
Sector:     202
Key (hex):  65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5
Cipher:     99beddc752083a8b190f3fdfb8b09872
Decrypted:  Hello

Conclusions

If you are a Cybersecurity professional, and you give advice on using encrypted USB sticks, or advise on using Microsoft BitLocker for full disk encryption, make sure you actually know how it works. Within BitLocker, the Tweak keys are protected by the Volume Master Key (VMK):

XTS is not perfect, but it is the de-facto full disk encryption mode. You should always try and encrypt your files at their source, and not rely on full disk encryption.

Security
Cybersecurity
Cryptography
Recommended from ReadMedium