12.3. Security and DRM userspace¶
The device’s trust model has two parts. The secure world — TrustZone (QSEE), the hypervisor, the trustlets and the fused keys — is below userspace and is documented in Secure world and coprocessors (TZ, HYP, trustlets), Crypto engine (QCE) and hardware RNG and AVB enforcement code path (LoadImageAndAuth / libavb). This page is the userspace half: the HAL services and daemons that reach into TZ, the key/credential stores, the storage-encryption plumbing, and the DRM stack. None of it is the root of trust — it is the set of clients that depend on the root of trust — but it is what a replacement bootloader has to keep working, because keystore attestation, file-based encryption and Widevine all break if the TZ/keymaster/RPMB chain underneath them is disturbed.
Everything here is read statically from system_a.img / vendor_a.img and
artifacts/boot_a/fstab.default. No code was executed.
12.3.1. The bridge to TrustZone (QSEE)¶
Every hardware-backed security service in userspace reaches its trustlet through the QSEECOM channel:
qseecomd— the daemon that loads and talks to QSEE trustlets;libQSEEComAPI.so+vendor.qti.hardware.qseecom@1.0-service/…-impl.so— the API and HAL wrapper;vendor.qti.hardware.qteeconnector@1.0-service— the newer QTEE connector;vendor.qti.hardware.tui_comm@1.0-service-qti— the Trusted UI channel (secure display/touch, e.g. for PIN entry).
The trustlets these load (keymaster, widevine, gatekeeper, the fingerprint TA, soter …) live in the secure world and are catalogued in Secure world and coprocessors (TZ, HYP, trustlets). The mechanism below this — PAS authentication of the trustlet images — is the same one the DSP/GPU images use (Firmware-blob inventory (the payloads)).
12.3.2. Keys, credentials and attestation¶
Keymaster —
android.hardware.keymaster@4.0-service-qtiand@4.1-service-qti(backed bylibqtikeymaster4.so); the private keys live in the TZ Keymaster trustlet, not in Linux.keystore2+android.system.keystore2andlib_android_keymaster_keymint_utils.soare the framework front-end. Provisioning helpers:libkeymasterprovision.so,libkeymasterdeviceutils.so.Attestation keybox —
init.keybox.sh/init.erase_keybox.shprovision (and wipe) the device attestation keybox that Keymaster uses to sign key attestations; the keys are sealed to the device.RPMB —
init.rpmb.shsets up the Replay-Protected Memory Block on the storage device (Secure world and coprocessors (TZ, HYP, trustlets)), which Keymaster/Gatekeeper use for rollback-protected counters and secure state.Gatekeeper —
android.hardware.gatekeeper@1.0-service-qti+gatekeeperd; PIN/pattern/password enrolment and verification with TZ-enforced throttling (the HMAC key never leaves TZ).
12.3.3. QSEE secure storage: keystore.bin and persist/data¶
Checked directly against _READONLY/lun0/keystore.bin and
_READONLY/lun0/persist.bin (raw dumps, not the extracted images used
elsewhere on this page); full transcript and command-by-command evidence in
artifacts/re_static/item_qsee_storage_recheck.txt.
keystore.bin (the dedicated 512 KiB GPT partition labelled keystore in
rawprogram0.xml) is entirely zero bytes — all 524288 bytes, confirmed by
full-file scan. It is not encrypted or opaque; it is empty/unprovisioned on this
unit (or wiped before the dump — the two are indistinguishable statically).
Whatever holds live key material, it isn’t this partition.
persist.bin is a normal ext4 filesystem (confirmed with 7z l, matching
the pre-existing artifacts/re_eink/persist_all extraction). Under
data/ it holds two directories with opaque, hash-like base64url names —
this is Qualcomm’s QSEE SFS (Secure File System): keymaster asks to open a
plaintext path like /persist/data/rsa_attest_key and QSEE’s qsee_sfs_*
API (confirmed present by name in keymaster_a.bin — qsee_sfs_open,
qsee_sfs_read, qsee_sfs_write, sfs_rpmb_set/get, alongside the
literal strings /persist/data/rsa_attest_key and
/persist/data/ecc_attest_key) transparently maps it to an opaque on-disk
name before it ever touches flash. That name-obfuscation mapping could not be
reversed (the key/digest that produces it isn’t a static constant in the TA).
What was recovered, byte-for-byte, is the container format wrapping every leaf file in those directories:
offset size field
0x00 32 opaque tag (MAC/digest-shaped; differs every rewrite)
0x20 4 LE u32 — per-file RPMB-backed generation/anti-rollback counter
(proven, not guessed: every "live" file's counter is exactly
one more than its own ".bak" twin's)
0x24 var NUL-terminated on-disk (obfuscated) filename
... var NUL-terminated CLEARTEXT logical name/path
... 0 zero-padded out to a fixed offset 0x79
0x79 var payload — genuinely high-entropy ciphertext (fails
``openssl asn1parse``, no readable ``strings``, re-randomized
on every rewrite down to the trailing 4 KiB page)
Because the logical name field is cleartext, the one attestation-id SFS
context on this device (data/[REDACTED — unique per physical unit]/)
directly reveals its own inventory without needing the payload: six files
logically named brand / device / product / serial /
manufacturer / model (the device-ID attestation tags from
artifacts/re_static/item2_keymaster_interface.txt section [F]), one
attest_key (12692 bytes — the RSA/ECC attest key blob), and one
gk_sfs_file (gatekeeper’s SFS-backed state). A second SFS context
(data/[REDACTED — unique per physical unit]/) holds a widevine file whose logical name is stored
as a full path, /persist/data/widevine/master_gen_num.dat — confirming the
same container format and the same qsee_sfs API is shared by the DRM
trustlet, not exclusive to keymaster.
The payload ciphertext (post-0x79) and the name-obfuscation key are genuinely unreachable from static analysis. The container header, however, is cleartext and fully mapped, and positively identifies what is stored (all six attestation-id fields, the attest key, gatekeeper state, and a widevine counter): it is provisioned, present, and inventoried; only the payload bytes resist reading.
12.3.4. persist and metadata: the rest of the inventory¶
persist.bin and metadata.bin carry more than the QSEE SFS blobs
above; the rest of their content, for completeness:
``persist``’s other populated directories:
sensors/— IMU factory calibration (accel/gyrofac_calbias + correction matrix,mag_cal, placement) plus asensors/registry/;data/pfm/licenses/;time/(atstime anchors);hvdcp_opti/(battery state-of-health);rfs/(remote-filesystem server stubs). Empty on this unit:display/(no EPD calibration stored here — the panel VCOM lives inonyxconfigand the FPGA flash instead, E-ink driver internals (register-level, from the kernel)),secnvm,iar_db,vpp,lost+found. Not here: the WLAN MAC override is/vendor/firmware/wlan/qca_cld/wlan_mac.bin(32 B), not inpersist.``metadata`` (16 MiB ext4, ``Last Mounted = /metadata``) — the pre-decryption partition FBE needs before
/dataunlocks. Populated:vold/metadata_encryption/key/holds a real, Keymaster-wrapped metadata key (encrypted_key228 B,keymaster_key_blob228 B — the key material never leaves the TA, per the FBE story below),secdiscardable(16 KiB, the auxiliary secretvoldXORs in for “secure discard”), andversion("1"). This confirms metadata encryption is provisioned, not merely declared in fstab. Also present:gsi/dsu/avb/{q,r,s}-gsi.avbpubkey— three 1032-byte AVB public keys used bylibfs_mgr/init to verify a Dynamic-System-Update generic system image before mounting it over/system(the on-partition counterpart to the OEM-unlock/DSU installer presence confirmed app-side, APK sweep: bulk decompile of the remaining 123 system/product apps; not diffed against upstream AOSP’s published copies — DSU keys are meant to be identical on every certified device);bootstat/persist.sys.boot.reasonreadingreboot,edl— the backup this dump came from was pulled via a cold boot into 9008/Sahara EDL mode (EDL / 9008 entry and the deep-flash cable); and empty-but-provisionedaconfig/,apex/sessions/,gsi/{ota,remount},ota/snapshots,staged-install,userspacereboot,password_slotsdirectories (machinery present, never fired on this unit).
12.3.5. Factory Reset Protection — frp¶
frp.bin (LUN0, 512 KB) is 99.98% zero but not blank: a real, live
Android PersistentDataBlockService partition, decoded field-for-field
against the AOSP source
(services/core/java/com/android/server/pdb/PersistentDataBlockService.java)
and verified byte-exact:
Header — a 32-byte digest at
+0x0, the 4-byte markerPARTITION_TYPE_MARKER = 0x19901873at+0x20, then a 4-bytetotalDataSizefield at+0x24reading 0 — the plain FRP data block (OEM-unlock /persist.sys.localeetc.) is present-but-empty.``FRP_SECRET_MAGIC`` (
da c2 fc cd b9 1b 09 88) found byte-exact at its AOSP-computed offset,0x7d4df— independently confirming both the constants and the partition’s real-world layout. This is the newer “FRP secret” deactivation mechanism (Android 14+), confirmed present/enabled.FRP credential region (
0x7fc17) — not empty: a 4-byte big-endian size header reading0x67(103) followed by real payload bytes — a credential handle is stored here (written whenever Setup Wizard is completed with an account). By AOSP design this block survives a normalSettings → Factory reset(that’s the whole point of FRP — a thief can’t clear it that way), so its presence is consistent with standard factory/QC provisioning-and-reset during manufacturing, not necessarily any use after purchase. The credential’s actual content (account identity) is opaque and was not decoded here — only the region’s occupied/empty state was read.OEM-unlock byte — the literal last byte of the partition (
0x7ffff) reads 0 — OEM unlock is not marked allowed through this mechanism. This is a different, higher-level gate than the QFPROMSEC_BOOTfuse or the ABLdevice_info.is_unlockedbit (AVB enforcement code path (LoadImageAndAuth / libavb)) — all three must be considered for a real unlock/flash story.Test-Harness-Mode region (
0x7d507–0x7fc16) — all-zero: not in use.
12.3.6. Storage encryption (vold / FBE)¶
/data (f2fs) is File-Based Encryption v2, per fstab.default:
fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0
metadata_encryption=aes-256-xts:wrappedkey_v0
keydirectory=/metadata/vold/metadata_encryption
The important flags are wrappedkey_v0 and inlinecrypt: file contents are
AES-256-XTS and filenames AES-256-CTS, but the keys are hardware-wrapped
(HWKM) and used through inline crypto — i.e. the ICE engine inside the UFS
controller, not a software cipher (Storage controllers — UFS, ICE, and SDCC, Crypto engine (QCE) and hardware RNG).
vold obtains the class keys via Keymaster, hands the wrapped key to the
block-crypto/ICE path, and the raw key never appears in the kernel. Metadata for
the /metadata partition is separately encrypted with a wrapped key. Removable
storage (the microSD /storage/sdcard1) uses the legacy encryptable=footer
scheme instead.
This is the userspace end of the crypto chain whose hardware end
(SCSI_UFS_CRYPTO_QTI / HWKM) is in Storage controllers — UFS, ICE, and SDCC.
12.3.7. DRM (Widevine, ClearKey, CAS)¶
Widevine —
android.hardware.drm@1.3-service.widevinewithlib64/libwvhidl.soand, crucially, a vendorliboemcrypto.so: the OEMCrypto implementation runs against the TZ Widevine trustlet (thewidevinefirmware blob is on the NON-HLOS partition, Firmware-blob inventory (the payloads)). A hardware OEMCrypto + TZ trustlet is the configuration required for Widevine L1 (keys and decrypt confined to the secure world / ICE); the level a given build is actually provisioned at is a runtime/keybox property, not visible statically.ClearKey —
mediadrm/libdrmclearkeyplugin.so, the software test plugin.CAS —
android.hardware.cas@1.2-service(Conditional Access System, for broadcast/streaming; pairs with thempq-*demux modules in Vendor drivers and HALs, largely vestigial here).Framework:
libmediadrm.so/libdrmframework.soand the metrics libraries in/system/lib64.
12.3.8. Biometrics (fingerprint)¶
Two HAL services ship — android.hardware.biometrics.fingerprint@2.1-service
and Onyx’s vendor.fptool.fingerprint@2.0-service — over three vendor
implementations (chipsailing.fingerprint, fsfingerprint,
libmicroarray), matching the three fingerprint firmware sets in
Firmware-blob inventory (the payloads). Template storage and matching run in a TZ trustlet; the
sensor’s IRQ/reset/SPI-CS pins are in Pin control — TLMM and the PMIC GPIOs.
12.3.9. Other secure services¶
vendor.qti.hardware.soter@1.0-service— Tencent Soter payment attestation (a TZ-backed key-attestation scheme used by Chinese payment apps).vendor.qti.esepowermanager@1.1-service— embedded Secure Element power management; since NFC is declared unavailable (Wireless drivers and HAL), the eSE is present in the reference stack but not exercised here.
12.3.10. Relevance below userspace¶
Keymaster/Gatekeeper keys are sealed by TZ using fused key material, FBE
class keys are unwrapped by HWKM/ICE, Widevine decryption happens inside TZ,
and RPMB provides rollback protection — the entire chain above is anchored in
TZ and RPMB. A custom bootloader that replaces ABL/XBL must preserve the TZ, keymaster and RPMB
provisioning (and the devcfg that configures them, Secure world and coprocessors (TZ, HYP, trustlets))
or key attestation, FBE unlock and DRM all fail. The current chain is test-key
signed with secure boot un-fused (AVB enforcement code path (LoadImageAndAuth / libavb),
Secure boot and image signing), which is what makes replacing the bootloader feasible
without bricking these services — but the trustlets themselves remain
signature-checked by TZ.
12.3.11. Provenance¶
- Source:
artifacts/super/vendor_a.img(bin/hw+lib64/hwsecurity/DRM HAL services and impls,liboemcrypto.so,libwvhidl.so,libqtikeymaster4.so,libQSEEComAPI.so,qseecomd,init.{keybox, rpmb,erase_keybox}.sh),system_a.img(keystore2,gatekeeperd,libmediadrm/libdrmframework, keystore2/keymaster/gatekeeper NDK libs),artifacts/boot_a/fstab.default(FBE / metadata-encryption flags),_READONLY/lun0/keystore.binand_READONLY/lun0/persist.bin(raw partition dumps, cross-checked against the existingartifacts/re_eink/persist_allextraction),_READONLY/lun4/keymaster_a.bin(qsee_sfs_*/sfs_rpmb_*strings) — seeartifacts/re_static/item_qsee_storage_recheck.txtandartifacts/re_static/item2_keymaster_interface.txtfor the full transcripts.- Method:
ext4 images listed/extracted read-only with
7z; encryption flags read from the fstab.keystore.bin/persist.bininspected withfile,7z l,xxd,stringsand a byte-level structure/entropy scan (python3);openssl asn1parsetried against candidate key blobs. No code executed; no keys or secure state accessed; no encryption defeated.- Cross-refs:
Secure world and coprocessors (TZ, HYP, trustlets) (TZ, QSEE trustlets, HYP), Crypto engine (QCE) and hardware RNG (QCE/ICE/HWKM hardware), Storage controllers — UFS, ICE, and SDCC (ICE inline crypto), AVB enforcement code path (LoadImageAndAuth / libavb) (fuses, secure-boot state), Secure boot and image signing (verified boot), Firmware-blob inventory (the payloads) (widevine/fingerprint firmware, trustlet load path), Vendor drivers and HALs (eSE, HAL-layer overview), Sensor drivers and HAL (fingerprint impls), Wireless drivers and HAL (NFC).