Verified Boot & encryption

Separate integrity, authenticity, rollback protection, and confidentiality.

12 min readChapter 35 of 50Advanced
In this chapter

Before you start#

Required: Android’s Security Model. Optional: Android boot images when available in this curriculum. The examples use AOSP Android 14 android-14.0.0_r1; physical boot implementations and vendor partitions differ. This is not a flashing guide.

Three words first: a hash is a one-way digest that lets you compare content with a known digest; it does not tell you who made the content. A digital signature lets a verifier check that signed data was approved by whoever controls the corresponding private signing key, assuming the verifier trusts the public key and its policy. A cipher and key protect confidentiality. A signature does not encrypt, and a hash by itself does not establish trust. A rollback index is a separate version/freshness constraint.

Learning goals#

Explain how AVB metadata, partition hashes/hash trees, boot state, and rollback policy contribute to boot integrity; distinguish those from file-based encryption (FBE), credential authentication, and key availability; describe exactly what an offline image check can and cannot establish.

Verified Boot and AVB

From trusted key to verified bytes
  1. Device trust anchor and policy

    The bootloader decides which verification keys and states are accepted.

  2. Signed VBMeta metadata

    Authenticate metadata, descriptors, and any chained verification keys.

  3. Partition digest / hash-tree root

    Descriptors bind the accepted metadata to protected content.

  4. Content integrity checks

    Image hashes and, where configured, dm-verity block checks. This is not file decryption.

Conceptual model. A simplified trust relationship, not exact verifier execution order. Acceptance also depends on rollback state, lock state, and device integration. No check proves code bug-free.

Verified Boot establishes a chain from an initial device trust decision through boot stages that verify subsequent code and metadata. On devices implementing Android Verified Boot (AVB), VBMeta structures carry descriptors for partitions. Descriptors can reference hashes for smaller images or hash trees for larger filesystems (avb_descriptor.h, tags AVB_DESCRIPTOR_TAG_HASH and AVB_DESCRIPTOR_TAG_HASHTREE). A hash tree (Merkle tree) organizes block digests so the system can verify a block using a path to an authenticated root digest. dm-verity can check filesystem blocks as they are read; it is integrity checking of block devices, not encryption. See the AOSP Verified Boot overview and the pinned AVB header and avb_slot_verify() implementation.

The AVB reference library defines the four-byte AVB0 metadata magic as AVB_MAGIC with AVB_MAGIC_LEN in avb_vbmeta_image.h. Finding those bytes only suggests a format marker. A useful verifier must parse valid metadata, verify signatures against an accepted key and expected policy, check descriptors, and account for boot state and rollback policy. The device bootloader’s trust anchors and integration decide acceptance. A successful calculation on a laptop is not evidence that a particular phone accepts the image.

Three checks, three questions

  1. Signature/key authentication: Was the metadata authorized by a key this verifier trusts?
  2. Integrity: Do the image bytes match the digest/hash tree authenticated by that metadata?
  3. Rollback: Is this signed version at least the minimum version remembered by the device’s rollback-protection state? (The VBMeta header carries a rollback_index field; see avb_vbmeta_image.h and Verified Boot.)

A correctly signed old image may fail rollback policy. A file’s hash can match a digest supplied by an attacker and still have no trustworthy origin. None of the three checks says that the code is bug-free.

Why a hash tree is useful: a four-block example

Let a fictional partition contain blocks B0 through B3. Compute leaves Hi = SHA256(Bi), parents P01 = SHA256(H0 || H1) and P23 = SHA256(H2 || H3), then root R = SHA256(P01 || P23). Here || means byte concatenation; this is a simplified teaching tree, not dm-verity's exact block/salt/layout format.

To validate B2, a verifier can recompute H2, combine it with the supplied sibling H3, and combine that result with P01 to reach the trusted root. It does not need to reread every data block for every access. If B2 changes, the recomputed root no longer matches, assuming the hash's security properties and the original authenticated root. If an attacker can replace both the block and the trusted root, recomputation alone gives no authenticity. That is why the root digest must be bound to accepted verification metadata rather than trusted because it is printed beside the image.

Boot-time verification authenticates metadata and selected images; dm-verity can check protected filesystem data during reads. Neither encrypts the block or prevents every denial-of-service/corruption event. A corrupted block can be detected rather than silently trusted, but the exact error/recovery policy is product-specific. See dm-verity.

Locked, unlocked, and verified state

“Locked” means that the bootloader enforces its configured verification policy; it does not mean every component is protected equally or the OS has no vulnerabilities. An owner-authorized unlock commonly permits alternate software, reduces the original trust assurance, can display a warning, and wipes user data: AOSP’s device state page says an UNLOCKED bootloader “proceeds to boot even if the loaded OS isn’t signed by the root of trust” and that all state transitions wipe the data partitions. Exact flow and state indicators are manufacturer-specific. Unlocking changes what boot code is accepted; rooting changes runtime privileges or boot components. An unlocked device need not be rooted, and root does not manufacture the vendor signing key.

Do not infer security from a single color, property, or manager status. Record the actual observed state and the source that defines it. Hardware and vendor implementation may expose different signals.

File-based encryption and credential language

DE and CE key availability
Direct Boot: DE storage
Device-encrypted data can support selected services before first user unlock; process access checks still apply.
After authorized user unlock: CE storage
Authentication permits the relevant key-management path; vold/fscrypt coordinate storage-key availability. The PIN is not simply the raw file key.
Conceptual model. Intended CE/DE availability, not unrestricted file access. Credential authentication, CE-key availability, bootloader unlocking, and UID 0 are different things.

FBE encrypts file contents with keys organized by user and storage policy. Device-encrypted (DE) data is designed to be available for some Direct Boot services before the user’s first unlock. Credential-encrypted (CE) data is made available after user authentication permits the relevant key path. This describes intended availability, not that every DE file is readable to every process before unlock. AOSP documents the CE/DE availability distinction in its FBE overview.

Do not picture the PIN as the raw filesystem key. The credential is an authentication input; Android’s storage and key-management components decide whether and how CE key material can be made available. Depending on design and hardware, authentication, Gatekeeper/Weaver, KeyMint/secure hardware, vold and kernel fscrypt are involved. Their exact responsibilities and derivation path vary by device/release; this chapter does not claim one universal formula. Bootloader unlock, screen/user authentication, and CE-key installation are three different meanings of “unlock.” UID 0 does not derive a missing CE key.

FBE protects file contents and filenames under its supported policies. Metadata encryption adds protection for remaining filesystem metadata, such as file sizes, permissions, timestamps, and directory-layout information, depending on the filesystem/configuration. It is not simply another name for filename encryption. See AOSP’s FBE and metadata encryption documents.

Follow availability rather than imagining a PIN-shaped disk key

The key path has several jobs, which should not be collapsed into “the TEE decrypts the phone”:

Component/mechanismJob in the broader designWhat it is not
Lock-settings and synthetic-password machineryCoordinates credential-protected authentication/key material under the release's designA rule that the typed PIN is the raw filesystem key
Gatekeeper / Weaver where implementedHardware-assisted credential verification, throttling, or secret-access gating under the supported designA general filesystem reader
Keystore / KeyMint and secure hardwareEnforce properties of supported cryptographic keys and operationsA promise that every key or all file plaintext lives only in secure hardware
vold and fscryptManage filesystem encryption policies and key installation/eviction pathsAndroid runtime permissions for every app file
DAC / SELinux / framework checksConstrain which process may access available data/operationsA substitute for unavailable cryptographic key material

This is a responsibility map, not a universal function-by-function call chain; devices and releases differ. See FBE key protection, Gatekeeper, Weaver, and Keystore.

Worked lifecycle: after a reboot but before the user's first unlock, supported Direct Boot components can use their DE storage while CE data remains unavailable through the normal key path. Authorized authentication makes the relevant CE key path available; vold/fscrypt coordinate installation and policy use. App access still needs the appropriate identity/labels. Later turning the screen off or showing the lock screen does not universally evict every installed CE key: ordinary screen locking and a user/key-eviction or reboot lifecycle are different events. Therefore “screen is locked” is insufficient evidence that CE material is unavailable.

Conversely, after keys are available, encryption at rest does not prevent all plaintext access by a sufficiently compromised running OS. Powerful root code may read accessible data or interfere with future authentication through the components it controls. “UID 0 does not derive an unavailable CE key” is a narrow boundary claim, not a guarantee that rooting leaves a user's future data safe. The threat model must state before/after first unlock, installed key state, attacker persistence, and which trusted components remain uncompromised.

Source walkthrough: AVB and vold are separate paths

At AOSP android-14.0.0_r1, avb_slot_verify() in external/avb/libavb/avb_slot_verify.c loads and verifies VBMeta through the caller-provided operations interface. Its API takes an AvbSlotVerifyFlags flags argument, from which the implementation derives the local boolean allow_verification_error using AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR. That distinction matters when tracing who chose the verification policy: the caller supplies flags, not a separate boolean parameter with that local variable's name. Error handling also depends on the result category; this is not a promise that the flag makes every malformed image acceptable. The reference library does not itself provide the hardware trust anchor; bootloader integration and configuration supply that context. The verified slot result feeds the boot configuration; how dm-verity is set up for relevant partitions is build- and device-specific and was not traced in this review.

Compare fscrypt_unlock_user_key() in AOSP system/vold/FsCrypt.cpp. In the FBE branch, the function checks whether a CE policy is already present, converts an argument named secret_hex using authentication_from_hex(secret_hex), and passes the resulting authentication material down the CE-key read/install path. The call boundary tells us that this parameter is parsed as authentication material and that failure returns false. It does not by itself tell us that secret_hex is the PIN, a raw fscrypt key, or the universal cryptographic derivation input. Do not invent that meaning: trace the caller and implementation for the same revision and device path before making a stronger statement. The helper eventually coordinates storage-key installation; that is distinct from AVB’s boot-metadata verification. The cited Android 14 source lines establish this call path, while the current FBE documentation explains key handling at a broader level.

These excerpts are abbreviated source-reading aids, not runtime proof. AVB public-key verification authenticates boot metadata; fscrypt keys protect file data; authentication gates an authorized key path. None is a generic “root key.”

Practice#

Draw two separate flows on paper. Boot: initial trust anchor → bootloader/AVB policy → authenticated metadata and descriptors → partition/block integrity checks. Data: user authentication → key-management authorization → vold/fscrypt key availability → process access checks. Label each arrow with what evidence could establish it and what remains device-specific.

Add a four-state worksheet: reboot-before-first-unlock, successful user authentication, later screen lock, and explicit supported key eviction/reboot. For each, separate display lock, CE key availability, and process authorization. Model answer: the first normally lacks the user's CE key; the second establishes availability through the authorized path; screen lock alone does not establish eviction; a supported eviction/reboot transition needs its own lifecycle evidence. No key extraction, credential guessing, or device modification is part of this exercise.

Optional offline inspection: with a copied, known AOSP image and avbtool already available, inspect VBMeta metadata on the host. Do not alter or flash it. A parseable VBMeta block or successful verification using a supplied key establishes only facts about that artifact/tool/key combination. It does not prove that key is rooted in a phone’s hardware, the phone’s rollback index accepts the image, the device’s bootloader will boot it, or dm-verity works at runtime. No image/tools? The diagram exercise is the intended lab, not a failed setup.

Knowledge check#

  1. What does a hash alone fail to establish?
  2. How is a signature check different from rollback protection?
  3. Does an AVB0 marker or successful offline parse prove device acceptance?
  4. Is the screen PIN necessarily the CE filesystem key?
  5. Does root automatically reveal CE data before authentication?
  6. In the four-block tree, why must the root digest be authenticated separately?
  7. Does showing the lock screen after first unlock prove the CE key was evicted?

Answers#

  1. It does not establish who created/approved the content; that needs a trusted comparison or signature trust chain.
  2. A signature verifies authorization by a trusted key; rollback checks whether the authenticated version is allowed by stored minimum-version policy.
  3. No. The device trust anchor, state, rollback policy, integration, and exact image matter.
  4. No. It is an authentication input to a device-specific key-management path, not necessarily the raw data key.
  5. No. UID 0 does not derive unavailable key material or substitute for the authorized CE-key path.
  6. An attacker who replaces both data and the comparison root can recompute a self-consistent tree; trust must bind the accepted root to authorized metadata/policy.
  7. No. Screen-lock state and key lifecycle differ. Ordinary screen locking does not universally evict installed CE keys; establish the actual user/key state separately.

Checkpoint#

Submit the two flows with a table of claims marked observed, source-derived, or unknown. Ready if hash, signature, encryption, rollback, bootloader unlock, and user authentication are distinct; revise if an offline parse is treated as phone acceptance; not yet evidenced if you assert a universal PIN-to-key derivation. Remediation: revisit the source walkthrough and AOSP FBE/AVB references.

Sources#


Next: Read SELinux policy and denials

A little further beneath the surface.

Check your understanding with the checkpoint. Marking a chapter as read saves a bookmark, not a proficiency assessment.