Crypto API and Storage Encryption

On this page

Changing the unlock passphrase usually does not require rewriting the entire disk, but changing the volume key may require re-encryption. Cryptographic primitives, key management, and the actual data path need to be understood in layers.

Protecting offline media and preventing malicious processes from reading files on an unlocked system are different goals; storage encryption still needs to be combined with access control.

GoalReference
Algorithm instances and asynchronous requestsSection 1
Block encryption, keyslots, and directory policiesSections 2–3
Network encryption, TPM, and digest experimentsSections 4–6

1. Crypto API: Algorithm Instances and Single Requests

Interface CategoryTaskExample
skcipherSymmetric encryption/decryptionXTS, CBC, etc.
AEADEncrypt and authenticate data and associated dataGCM, ChaCha20-Poly1305
shash / ahashSynchronous/asynchronous digest or keyed hashSHA-256, HMAC
akcipherAsymmetric encryption interfacesRSA operations
kppKey agreementDH, ECDH
rngSpecific random number generator interfaceRegistered RNG implementations

ECDH should be categorized under key agreement and should not be used as an example of an RSA-style encryption interface. Common kernel random byte requirements often use the random number subsystem interfaces such as get_random_bytes(), and not every caller allocates a crypto_rng themselves.

tfm is a transformation object that configures algorithm and key information; an operation usually also requires a request, source/destination scatterlist, length, and IV. The correct skcipher encryption entry point accepts skcipher_request *, not a fake crypto_skcipher_encrypt(tfm, src, dst, len).

  1. Allocate tfm, check for errors, and set the key.
  2. Establish request, callback, source/destination ranges, and IV.
  3. Submit and distinguish between synchronous completion or asynchronous processing based on the return status.
  4. Only after satisfying the completion contract, release the request, data, and context.

In sleepable contexts, you can use crypto_wait_req() to wait as per official examples; do not move it into atomic contexts. See skcipher API and complete example.

Algorithm Names Are Not Concrete Execution Units

Names like xts(aes) combine templates and underlying algorithms. Multiple implementations can provide the same generic algorithm name; the Crypto API selects based on matching conditions, implementation priority, etc.; specifying a driver name narrows the selection. /proc/crypto can observe currently registered implementations, but it is not a complete list of all possible algorithm combinations that can be loaded on the system.

AES-NI, ARM encryption extensions, and independent accelerators have different invocation costs. Small data blocks, queue latency, DMA, and copy costs can all affect results; you cannot guarantee that "the existence of a hardware implementation makes it fixedly ten times faster." The kernel also has direct cryptographic library interfaces, and not every cryptographic operation must go through dynamic tfm allocation. See Crypto API Architecture.

2. Where dm-crypt and LUKS Operate at Different Layers

Unlock keys and read/write data take different paths Passphrase / TPM unlock materials User-space handles unlock policies LUKS keyslot Protects volume key Volume Key Passed to running encryption mapping Filesystem Block I/O Plaintext accessible when unlocked dm-crypt Encrypts/decrypts per sector Underlying Storage Stores ciphertext data Changing the passphrase usually changes the keyslot; changing the volume key involves re-encrypting the data.

dm-crypt is a block encryption target for device-mapper, handling read/write data sent to the mapped device; the filesystem above usually sees decrypted blocks. LUKS is a disk format and key management convention, read by user-space tools like cryptsetup to parse the header, complete the unlock, and then configure the kernel mapping. The kernel dm-crypt does not parse each LUKS JSON keyslot.

ChangeLayer Typically Involved
Add or change passphrasePBKDF derives unlock material, handles keyslot
Restore volume key and open mappingUses key material protected in the keyslot
Actually change volume keyInvolves data re-encryption process

Therefore, changing the passphrase is usually not equivalent to re-encrypting the entire filesystem; the costs and recovery requirements for the two operations are different.

LUKS1 has a maximum of 8 keyslots; LUKS2 supports up to 32 slots, with the actual available number also limited by conditions such as keyslot area size. LUKS2 has redundant metadata and JSON descriptions, with clear layouts and configurable parameters for the header, keyslot area, and data offset; you cannot uniformly call them a "fixed first 16 MB header." See LUKS2 Format Specification and cryptsetup parameters.

The availability and parameters of PBKDF2, Argon2i, and Argon2id depend on the format and tool configuration. Memory cost can increase the cost of offline passphrase guessing, but it cannot make weak passphrases into unbreakable keys. Do not confuse the PBKDF overhead during the unlock phase with the encryption overhead for each sector read/write.

Confidentiality Does Not Equal Integrity

Common XTS mode provides sector data confidentiality but does not provide universal tamper authentication and anti-rollback guarantees. When authentication encryption or integrity protection is needed, you must choose the corresponding mode, metadata storage, and cooperating mechanisms such as dm-integrity, and understand their boundaries.

Allowing discard can expose usage space pattern information. When unlocked, processes with read privileges can still obtain plaintext; volume keys and cached plaintext also participate in the memory threat model of the running system. See dm-crypt documentation.

Below, we actually encrypt the same public example content in the browser, then flip one bit in the ciphertext. Compare unauthenticated CTR with authenticated GCM: being able to decrypt some bytes, and those bytes passing verification, are two different results.

Preparing the visual
If one bit is flipped in the ciphertext, does successful decryption mean the content is trustworthy?

Unauthenticated CTR can decrypt modified plaintext after a ciphertext bit flip; GCM verifies the authentication tag and rejects the modification here. Confidentiality, integrity, and anti-rollback need to be explained separately.

3. fscrypt: Choosing Protection Scope Within the Filesystem

fscrypt provides file content and filename encryption for supported filesystems. Directory policies allow different directory trees to use different master keys, facilitating the management of multiple unlock domains within the same filesystem.

It usually does not hide non-filename metadata such as file size, permissions, timestamps, and directory structure, nor can it guarantee that offline observers cannot correlate files. The default per-file derivation and nonce mechanisms have policy differences such as DIRECT_KEY and IV_INO_LBLK; you cannot generalize it as "every file has an independent data key under any configuration."

Standard fscrypt design mainly protects static data confidentiality and does not automatically provide complete filesystem authentication against active tampering and rollback. Removing the master key also needs to consider derived keys still in use in open files and caches; you cannot interpret the ioctl return as all plaintext disappearing instantly.

New directory policies are usually set when conditions such as an empty directory are met, and subsequently created files inherit the corresponding policy; it does not magically convert an existing plaintext directory. FS_IOC_GET_ENCRYPTION_PWSALT is a historical passphrase derivation auxiliary interface, not a general interface for reading unique salt values for any directory. Policies and limitations are documented in fscrypt documentation.

Comparison Pointdm-cryptfscrypt
Management BoundaryBlock mappingPolicies and key domains within the filesystem
Filesystem MetadataBecomes encrypted blocks together when inside the encryption mappingMany non-filename metadata remain visible
Unlock GranularityUsually the entire mappingCan manage keys for different directory trees
Access Control After UnlockStill relies on permissions/LSM, etc.Still relies on permissions/LSM, etc.

The two can also be stacked; they are not mutually exclusive product replacements.

4. WireGuard and kTLS: Encryption at Different Network Layers

WireGuard provides Layer 3 encrypted tunnels, using fixed protocol components such as Noise handshake, Curve25519, and ChaCha20-Poly1305. Static public keys identify peers, and the handshake generates session keys; packet counters, authentication, and replay protection jointly participate in protection. Key updates are triggered by conditions such as time, message count, and session state, not strictly executed as a timed action every two minutes unconditionally.

Curve25519 is not a post-quantum algorithm. WireGuard can mix in pre-shared symmetric keys as additional protection, but this cannot be generalized as "post-quantum issues are unimportant" or the entire system has obtained all post-quantum security attributes. The configuration interface mainly uses generic netlink, and network device creation also involves standard network interface management. See WireGuard Protocol.

kTLS passes supported TLS record layer send/receive processing to the kernel or hardware; handshake, certificate verification, and protocol state management are still mainly handled by user-space TLS libraries. After connection negotiation, TCP TLS ULP needs to be set, and cipher states required for TX/RX configured separately; you cannot just copy a setsockopt and consider it a complete TLS client.

Paths such as sendfile can reduce user-space copying, but software encryption, NIC offload, and zero-copy sending are different capabilities; whether they are available depends on kernel, protocol, algorithm, and driver support. See kTLS documentation.

5. TPM: Use Secrets According to Policy, and Manage the Policy Itself

TPM can protect key objects and constrain unsealing or usage based on conditions such as PCR. Typical LUKS integration generates unlock material, associates it with TPM objects/policies and LUKS tokens; this does not mean keeping the entire disk encryption key permanently only inside the TPM for every sector encryption.

PCR is the accumulated result of measuring events, not the TPM understanding "this kernel is definitely benign." Which PCRs are selected, whether the measurement chain is trusted, and who signs the authorization policy determine the unlock constraints. Allowing legitimate upgrades also requires policy updates, signed PCR policies, or recovery credentials design.

What Do Boot Authorization, Measurement, and Unsealing Prove Respectively?

Secure Boot verifies the authorization relationship of boot code, measured boot records measurements, and TPM sealing restricts secret usage based on policies; the three can cooperate but cannot replace each other. Runtime vulnerabilities after normal unlock are not automatically prevented by PCR binding. Implementations can refer to systemd-cryptenroll source code and documentation.

6. Observing a Digest Request Using AF_ALG

Below, we use the Linux AF_ALG call to the kernel SHA-256 to perform a known result check on a public string, without reading keys or modifying storage. Requires Python/Linux support for AF_ALG, and the kernel has enabled the corresponding algorithm user interface. It demonstrates kernel interfaces and does not imply that general applications should replace their own cryptographic libraries.

import socket

expected = 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
with socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0) as alg:
    alg.bind(('hash', 'sha256'))
    op, _ = alg.accept()
    with op:
        sent = op.send(b'abc')
        if sent != 3:
            raise RuntimeError('unexpected short input')
        digest = op.recv(32)
assert len(digest) == 32 and digest.hex() == expected
print(digest.hex())

When AF_ALG is not enabled in this environment, creating a socket will return EAFNOSUPPORT; this indicates that the interface capability is unavailable, and you cannot judge that the SHA-256 algorithm itself is erroneous based on this.

If socket creation returns EAFNOSUPPORT, first check support for CONFIG_CRYPTO_USER_API_HASH, etc.; you cannot judge that the SHA-256 algorithm implementation is erroneous because of this.

Digest matching proves that this call path yields the expected result, but does not prove that the entire encrypted storage configuration, key management, or hardware offload is correct. See Kernel Userspace Crypto Interface for AF_ALG interface limitations and support status.