Cryptography / Storage Security

Full-Disk & File-Level Encryption

Data at rest security protects stored information against physical storage theft, unauthorized disk cloning, and exfiltration of storage media, backups, or snapshots taken outside the authorized decryption/key boundary — it does not, by itself, protect against a compromised running workload or a breached cloud control plane that already holds legitimate decrypt access. Architecture decisions span full-disk encryption (FDE) operating at the block-device layer (e.g. Linux LUKS2, encrypting an entire partition under one volume key), file-system encryption (FBE, e.g. Android's fscrypt) enforcing per-file access boundaries, and database field-level encryption using Key Encryption Key (KEK) envelope hierarchies.

Threat Scope: Data at Rest Protection Boundaries

Full-disk encryption protects data only while its key is evicted from memory — in practice, chiefly when the device is fully powered off:

Full-disk encryption threat scope diagram showing physical theft protection when powered off vs transparent access when unlocked.

FDE Threat Scope: protects against physical disk theft when powered off; OS transparently decrypts blocks while running

  1. Powered-Off State (Protected): Storage blocks are encrypted under volume keys that may be bound to hardware elements such as a TPM 2.0 or Secure Enclave, or protected by user passphrases/keyfiles. Physical removal of the SSD yields unreadable ciphertext.
  2. Active Booted Session (Transparent): Once the OS boots and unlocks the volume key, decryption occurs transparently at the block and file-system layer, though operating system access controls (user permissions, ACLs, process boundaries) still apply. Application-layer vulnerabilities (SQLi, path traversal) bypass FDE completely, since the OS transparently decrypts on the application’s behalf. Adding file- or field-level encryption is not automatically a fix: it only helps if the compromised application component itself lacks the decryption key or the authorization to use it — if the same vulnerable process legitimately holds both (the common case for an application that reads its own encrypted data), that layer is bypassed too. What actually mitigates this class of vulnerability is application-level authorization and input validation, least-privilege service accounts, and a genuinely separate encryption/key boundary (e.g., a distinct service or KMS call the compromised component can’t reach) — not merely stacking another encryption layer the same process can unlock.
  3. Screen-Locked, Still Mounted (Transparent, Not Protected): A locked screen is a separate security boundary from FDE — it does not, by itself, evict the volume key or unmount the disk. On iOS, only the narrower Complete Protection data class discards its keys at lock; the After First Unlock class (used by most app data) keeps its keys resident until reboot, and desktop FDE (FileVault, LUKS2) behaves the same way once mounted. An adversary with physical or software access to a locked-running machine cannot read decrypted data without bypassing operating system access controls, exploiting an authorized session, obtaining privileged execution, or extracting keys from RAM; only evicting the key (power-off, or an explicit re-lock of the volume) restores physical data-at-rest protection.

Block Cipher Mode for Disks: AES-XTS (IEEE 1619)

Standard 512-byte disk sectors cannot change size when encrypted (a 512-byte plaintext sector must produce a 512-byte ciphertext sector) with no spare room for an appended tag, which is why mainstream FDE (LUKS2, BitLocker, FileVault) uses an unauthenticated tweakable mode like AES-XTS rather than AEAD there. This is a constraint of that specific on-disk layout, not an absolute law of block storage: drives or filesystems that reserve extra per-sector metadata (e.g., 520-byte “DIF/DIX” sectors) or that authenticate at a coarser granularity than the raw sector (storing tags in a separate metadata region) can and do support authenticated storage — they just aren’t what conventional AES-XTS full-disk encryption uses. ZFS’s own native encryption feature (per-dataset AES-GCM, distinct from its unkeyed block checksums discussed below) is one real-world example of this coarser-granularity authenticated approach.

Standardized in IEEE 1619 and NIST SP 800-38E, AES-XTS uses two independent, equal-length AES keys (K1, K2) and a sector tweak value. Per NIST’s naming convention the two halves are concatenated into one key, so AES-256-XTS — the common full-disk-encryption default — supplies 512 bits of total key material (two 256-bit keys), while AES-128-XTS supplies 256 bits total (two 128-bit keys):

C = AES-XTS(K1, K2, Sector Number, Plaintext)

AES-XTS prevents pattern leakage across different sector addresses — the per-sector tweak means two identical plaintext blocks at different sector locations produce different ciphertext, unlike ECB. It is not randomized within repeated encryptions of the same sector, though: encrypting the same plaintext to the same sector under the same key is deterministic, so an observer comparing multiple snapshots of the same volume can tell whether a given sector’s ciphertext changed between snapshots (revealing that something was written there, even without knowing what), and, if a sector’s plaintext space is small or guessable, potentially confirm an equality guess. Per NIST SP 800-38E, modifying a single ciphertext byte completely randomizes the 16-byte AES block containing that byte upon decryption, while leaving the remaining 16-byte blocks in the sector unchanged (XTS provides confidentiality, not authenticity or integrity).

Linux LUKS2 & Argon2id Header Security

On Linux systems, LUKS2 (Linux Unified Key Setup v2) is a header and key-management format layered on dm-crypt — it is not itself a cipher, but a key hierarchy that wraps the underlying disk cipher (typically the AES-XTS above). A LUKS2 header holds up to 32 independent key slots, each a passphrase- or keyfile-derived wrapping of the volume key, so a passphrase and a separate recovery key can unlock the same block device independently. Each slot independently selects its own key-derivation function — LUKS2 supports PBKDF2, Argon2i, and Argon2id per cryptsetup’s luksFormat documentation — so not every slot in a given header is necessarily Argon2id-derived, particularly on headers migrated from LUKS1 or created with an explicit --pbkdf override. Modern cryptsetup compiles with Argon2id as its default KDF for newly created slots (a change from LUKS1, which defaulted to PBKDF2), but that default is configurable at slot-creation time, not a hard guarantee for every slot.

File-Level Encryption: A Distinct Construction & Threat Boundary

Everything above operates at the block-device layer: AES-XTS encrypts fixed-size sectors transparently, underneath the filesystem, without any concept of individual “files.” File-level (or file-based) encryption — Android’s fscrypt, encrypted archive formats, application-level “encrypt this document” features — is a different construction with its own design requirements, not simply AES-XTS applied to smaller units:

Envelope Key Hierarchy: DEK & KEK

To encrypt millions of database fields or S3 objects efficiently, systems implement Envelope Encryption:

Envelope encryption architecture showing KMS KEK wrapping data encryption key DEK.

Envelope encryption: Key Encryption Key (KEK) in KMS wraps per-object Data Encryption Keys (DEKs)

  1. Data Encryption Key (DEK): Commonly a single-use 256-bit AES key generated by a CSPRNG that encrypts the actual file or database payload — the specific size and generation method are deployment choices, not a fixed requirement of envelope encryption itself.
  2. Key Encryption Key (KEK): A long-lived master key managed inside an HSM or Cloud KMS wraps (encrypts) the DEK. AES Key Wrap (RFC 3394) is one common wrapping construction for a symmetric KEK, but it’s not the only one in use — some KMS providers wrap with AES-GCM instead, and asymmetric KEKs (e.g., RSA-OAEP) wrap the DEK under a public key rather than a shared secret.
Key Hierarchy & Rotation Mechanics
CMEK, DEK, KEK & Key Rotation Under the Hood

To secure massive data stores efficiently, envelope encryption divides responsibilities between local fast data keys and centralized master key custody:

  • Data Encryption Key (DEK): A 256-bit AES symmetric key generated in memory. It encrypts the raw file or database payload. In a correctly implemented envelope-encryption scheme, the plaintext DEK is designed never to be written to disk — that's the architecture's security objective, not a property guaranteed automatically by calling something "envelope encryption"; a buggy or misconfigured implementation can still leak it (e.g., via a swap file, crash dump, or logging path). It encrypts the file, gets wrapped by the KEK into an Encrypted DEK (EDEK), and the EDEK is stored alongside the payload file.
  • Key Encryption Key (KEK) / CMEK: A master key stored inside a Hardware Security Module (HSM) or Cloud KMS (e.g. AWS KMS, GCP KMS). A Customer-Managed Encryption Key (CMEK) is a KEK where the customer controls access policies, rotation schedules, and revocation. In non-exportable HSM-backed architectures, the KEK remains within the HSM security boundary, used primarily to wrap and unwrap key material such as local DEKs.
What Key Is Actually Being Rotated?

When key rotation is triggered (e.g. annually), one common efficient strategy is rotating only the Master KEK/CMEK inside KMS — avoiding multi-terabyte bulk data re-encryption — though DEKs and bulk data can also be rotated or re-encrypted after a compromise or according to policy:

  • Version Creation: KMS generates KEK_v2 and marks it active for new encryptions. KEK_v1 is retained inside KMS as decrypt-only.
  • Older Data Decryption: When reading older data, the application sends EDEK_v1 to KMS. KMS inspects the key version header, uses KEK_v1 to unwrap the DEK, and returns the plaintext DEK to RAM. No bulk data re-encryption is required!
  • Re-wrapping EDEKs (Optional): If security compliance mandates eliminating dependencies on KEK_v1, KMS performs a ReEncrypt operation: unwrapping EDEK_v1 and wrapping the same 32-byte plaintext DEK under KEK_v2. The wrapped EDEK itself is larger than the 32-byte plaintext DEK it contains — wrapping constructions like AES Key Wrap add a fixed overhead (8 bytes for RFC 3394), and some KMS providers additionally prepend metadata (key version, algorithm identifier) to the stored EDEK — so don't assume EDEK and DEK are the same size on disk. The multi-terabyte data payload remains completely untouched on disk.

Cloud Disk Encryption: Customer-Managed Encryption Keys (CMEK)

Cloud Provider Managed Service Customer Key Control (CMEK) HSM Backing Standard
Amazon Web Services (AWS) AWS KMS / EBS Encryption AWS KMS Customer Managed Keys (CMK) FIPS 140-3 Level 3 validated HSM hardware in most AWS Regions — China Regions are the documented exception: AWS KMS there uses HSMs certified by China’s OSCCA and compliant with Chinese regulations, but not validated under the FIPS 140-3 program (AWS KMS data protection docs).
Google Cloud (GCP) Cloud KMS / Persistent Disk Customer-Managed Encryption Keys (CMEK) Not HSM-backed by default: Cloud KMS keys are software-protected unless you explicitly choose the HSM, external, or external VPC protection level at key-ring creation; only the HSM protection level runs inside a FIPS 140-2/3 validated HSM boundary. Supports configurable regional, dual-region, or multi-region key locations (Google Cloud KMS Locations).
Microsoft Azure Azure Key Vault / Disk Encryption Customer-Managed Keys (CMK) Three distinct tiers, not one HSM guarantee: Key Vault Standard stores keys in software (no HSM); Key Vault Premium can create HSM-backed keys inside a shared, multi-tenant HSM; Azure Key Vault Managed HSM is a separate, single-tenant FIPS 140-3 Level 3 validated HSM service. Confirm which tier and key type a deployment actually uses before assuming HSM backing (Microsoft’s comparison).

Storage Encryption Gaps Beyond “Is It Encrypted?”

Confirming that a disk or object store is encrypted answers a narrower question than it sounds like — several adjacent concerns determine whether that encryption actually protects what you think it does:

What I need to remember

AES-XTS (IEEE 1619) provides confidentiality for block storage without built-in integrity, so a targeted ciphertext modification goes undetected unless a separate authenticated layer is added. Encryption on a live volume doesn't automatically cover its backups, snapshots, or hibernation files — each copy needs its own verified encryption and key-management posture.

Primary references