Safeguard
Supply Chain Security•

eMMC and UFS Explained: RPMB, Inline Encryption and Secure Erase

eMMC and UFS are the soldered flash inside phones, cars and boards. How they differ, what RPMB holds, how inline encryption works and how to erase them.

Safeguard Security Team
42 min read

eMMC and UFS are the two JEDEC standards for flash storage that is soldered onto a circuit board instead of plugged in: a NAND flash die and a small controller in one package, speaking a fixed command set to the host processor. eMMC uses a parallel bus derived from MultiMediaCard; UFS uses a serial link built on MIPI M-PHY and MIPI UniPro with a SCSI based command layer. Both carry a replay protected memory block (RPMB) that a trusted execution environment uses for anti rollback counters and tamper evident storage, and both can sit behind an inline encryption engine in the host controller that Android and Linux use for file based encryption.

The practical consequences are what this post is about. Deleting a file on one of these parts does not erase it, overwriting it does not reliably erase it either, and the right way to retire a device depends on whether its data was encrypted from day one. Below you will find how the two interfaces differ on the wire, what lives in boot partitions, the user area and RPMB, how the kernel's blk-crypto layer drives inline encryption, how erase, discard, sanitize and secure erase differ, what NIST SP 800-88 Rev. 2 (September 2025) says about flash, and a Linux walkthrough that inspects a device before any destructive command runs.

Key takeaways

  • eMMC and UFS are managed NAND: a controller inside the package hides erase blocks, wear levelling and bad blocks behind logical blocks. That is also why overwriting a file proves nothing about old copies.
  • UFS is layered: a SCSI command subset, the UFS Transport Protocol carrying UFS Protocol Information Units (UPIUs), and MIPI UniPro plus M-PHY. Linux documents Gear 1 at 1,248 or 1,457.6 Mbps per lane, with each later gear doubling.
  • eMMC exposes two boot partitions, a user area and an RPMB partition. Linux keeps boot partitions read only by default.
  • RPMB writes need a MAC made with a key programmed once, plus a counter that only goes up, so old data cannot be replayed. Android's Trusty TEE uses it for storage the normal OS can block but not modify.
  • Inline encryption puts the AES engine in the host controller, driven by keyslots. Android requires file based encryption on devices launching with Android 10 or later and can wrap keys in hardware.
  • NIST SP 800-88 Rev. 2 says overwriting is infeasible on flash, points to IEEE 2883 for techniques, and accepts cryptographic erase only if no sensitive data was ever stored in plaintext.
  • Treat storage controller firmware as a versioned component, and treat wear as a schedule you can read from the device.

If you want the manufacturing side, how NAND dies, controllers and firmware come together, read how an SSD is made and how a USB flash drive is made. This post assumes the NAND and focuses on the interface, the security features and the erase story.

What are eMMC and UFS?

Managed NAND in one package

Raw NAND is written in pages, erased in much larger blocks, wears out after a limited number of program and erase cycles and grows bad blocks over time. eMMC (embedded MultiMediaCard) and UFS (Universal Flash Storage) move the flash translation layer, error correction and wear levelling into a controller that shares a package with the NAND, so the host simply reads and writes logical blocks. JEDEC defines both. The Linux kernel documentation describes UFS as aiming "to provide a universal storage interface for both embedded and removable flash memory-based storage in mobile devices such as smart phones and tablet computers".

The package is soldered to the main board, which is why a dead storage chip usually means a dead board.

How they differ from SSDs and SD cards

All four are flash behind a controller. The differences are interface, packaging and the features the standard gives the host.

  • SD cards are removable. Linux drives them through the same MMC subsystem as eMMC, which is why its attribute documentation lists an SD only scr register beside the shared cid and csd.
  • eMMC shares that lineage but is soldered down and adds boot partitions, RPMB, one time configurable partitions, reliable write and sanitize.
  • UFS replaces the parallel bus with a serial link and a SCSI style command layer, keeping boot areas, RPMB and purge.
  • NVMe SSDs sit on PCI Express with their own command set, namespaces instead of hardware partitions, a Sanitize command and optional RPMB targets.

Where you find them

You find them wherever a designer wants storage that cannot be pulled out and boots the system directly:

Device classTypical embedded storageWhy it matters
Phones and tabletsUFS on most current designs, eMMC on lower cost onesBootloader chain, verified boot state, TEE storage and encrypted user data
Vehicle head units and telematicseMMC or UFSLong service life makes wear and firmware updates a fleet issue
Routers, set top boxes, kioskseMMCConfiguration and credentials share the part with firmware
Single board computers and industrial controllerseMMC, SD cards on hobby boardsEasy to forget to wipe before resale or RMA

Specific models vary between product revisions, so read the descriptors as shown later rather than assume.

How do eMMC and UFS differ on the wire?

eMMC: a parallel bus with a command line and up to eight data lines

eMMC inherits the MMC electrical interface: a clock line, a bidirectional command line and a data bus that can run one, four or eight bits wide. You can see those widths in mmc-utils, whose bootbus set command takes a boot bus width of x1, x4 or x8. Data moves in one direction at a time over the shared lines, so a read and a write cannot overlap on the bus itself.

Over successive versions of the JEDEC standard, eMMC added faster bus modes, a hardware command queue and background operations. The Linux kernel exposes whether the queue is on through a cmdq_en attribute (1 means enabled). The mmc-utils manual notes that automatic background operations (BKOPS) are only supported on eMMC 5.0 or newer. Android's file based encryption documentation refers to "the JEDEC eMMC v5.2 specification" when it describes eMMC inline encryption, which tells you inline crypto support arrived late in eMMC's history.

UFS: a layered serial interface

UFS is built in layers, and the kernel documentation describes each one:

  1. Application layer. The UFS command set layer handles a subset of SCSI commands from SPC-4 and SBC-3. A task manager handles task management functions "meant for command queue control". A device manager handles power management and configuration through query requests that read and write descriptors, attributes and flags.
  2. UFS Transport Protocol (UTP) layer. It carries everything as UFS protocol information units (UPIUs) through three service access points: one for device management, one for commands and one for task management.
  3. UFS Interconnect (UIC) layer. MIPI UniPro is the link layer and MIPI M-PHY is the physical layer.

Because the command layer is SCSI based, Linux runs UFS through its SCSI midlayer. The UFS host controller driver (UFSHCD) turns SCSI commands into UPIUs, so UFS logical units show up as ordinary SCSI disks. The kernel names the specifications it follows: JESD220 for UFS and JESD223 for the UFS host controller interface (UFSHCI).

The kernel documentation lists the original gear rates as the UFS 1.0 and 1.1 targets:

GearRate A (per lane)Rate B (per lane)Status in UFS 1.0 and 1.1
Gear 11,248 Mbps1,457.6 MbpsMandatory
Gear 22,496 Mbps2,915.2 MbpsOptional
Gear 34,992 Mbps5,830.4 MbpsListed as a future version

Two worked readings. Each gear doubles the last: 1,248 times 2 is 2,496, and times 2 again is 4,992 for rate A. Rate B is a fixed ratio above rate A: 1,457.6 divided by 1,248 is about 1.168, and 5,830.4 divided by 4,992 is the same 1.168. These are raw line rates per lane; usable throughput after coding and protocol overhead is lower, and devices can use more than one lane.

eMMC and UFS side by side

PropertyeMMCUFS
Physical layerParallel MMC bus, 1, 4 or 8 data bitsSerial MIPI M-PHY lanes
Link layerMMC bus protocolMIPI UniPro
Command setMMC commands (CMD numbers such as CMD13 status, CMD18 and CMD25 multi block read and write)SCSI subset (SPC-4, SBC-3) in UPIUs
QueueingCommand queue in later versions, shown by cmdq_en in LinuxTask manager and transfer request queues designed in from the start
Linux driver pathMMC block driver, /dev/mmcblkNSCSI midlayer through UFSHCD, /dev/sdX per logical unit, plus /dev/ufs-bsg for raw UPIUs
RPMB access from Linux/dev/mmcblkNrpmb through MMC ioctlsSCSI SECURITY PROTOCOL IN and OUT through SCSI generic

The CMD numbers come from Android's storage proxy source and from mmc-utils, which prints the STATUS_SEND (CMD13) response.

What lives where: boot partitions, user area and RPMB

The eMMC hardware partitions

An eMMC part is not one flat block device. The JEDEC standard defines several hardware partitions that the controller keeps separate, and Linux exposes them as separate block devices:

  • Boot partitions. Two of them, exposed as /dev/mmcblkXboot0 and /dev/mmcblkXboot1. The kernel documentation explains that they "often store a bootloader or bootloader configuration tables crucial to booting the platform", so write access is disabled by default. You can lift that with force_ro, lock a boot partition read only until the next power on with ro_lock_until_next_power_on (a card feature, not a kernel one), and the permanent lock is deliberately not exposed through sysfs "to avoid accidental or malicious bricking".
  • RPMB. A small authenticated partition, exposed as /dev/mmcblkXrpmb. Its size is reported through raw_rpmb_size_mult.
  • General purpose partitions. Optional extra hardware partitions an integrator can create once. The mmc-utils manual warns that gp create is "a one-time programmable (irreversible) change".
  • User data area. The large area that holds the partition table and every normal partition. Part of it can be configured as an enhanced area, again as a one time change.

Write reliability, the hardware reset signal and manual background operations are also one way switches, and mmc-utils flags each as irreversible. Treat them as factory operations, not experiments.

The UFS equivalent: logical units

UFS organises storage into logical units (LUs) addressed through SCSI. Normal LUs carry boot images and user data, and special functions such as RPMB are reached through their own SCSI commands, as the Android storage proxy shows below. Linux exposes the descriptors under sysfs, including geometry_descriptor/rpmb_rw_size. The detailed LU layout is defined in JESD220, so check your device's descriptors rather than assume one.

What a phone stores where

Putting the pieces together for a typical Android phone:

WhatWhere it usually livesProtection
First stage bootloader and its configurationeMMC boot partitions or the UFS boot area, depending on the SoCRead only by default in Linux, signed by the SoC vendor's boot chain
Partition table, boot, vendor, system imagesUser area (eMMC) or normal LUs (UFS)Verified boot signatures, A/B slots
Verified boot rollback indexes, lock state, verification keysTamper evident storage, which integrators typically implement with RPMB or a secure elementAVB rejects images whose rollback index is lower than the stored value
TEE app state such as keys and countersTrusty's storage service: RPMB for the tamper proof class, other classes relayed through the normal world storage proxyAuthenticated encryption, RPMB write counters
User data (/data)userdata partition in the user area, for example /dev/block/by-name/userdataFile based encryption per file, metadata encryption for the rest
Adoptable storage (an SD card formatted as internal)The removable cardFile based encryption plus metadata encryption, which Android always enables on adoptable storage when FBE is on

The AVB README defines tamper evident as "it's possible to detect if the HLOS has tampered with the data" and requires it for rollback indexes, verification keys, the LOCKED or UNLOCKED state and named persistent values. AVB states the property rather than mandating RPMB, but RPMB is the storage feature built to provide it. For the iPhone side of the same question, see Apple data protection classes and the Secure Enclave, and for how the board itself is assembled, how a smartphone is made.

How RPMB works and how Trusty uses it

The replay protection idea

A TEE wants to keep a little state, such as an anti rollback counter, that even a compromised normal OS cannot change or swap for an older copy, yet the normal OS still carries the bytes to storage. RPMB makes that safe with three ingredients:

  1. A shared secret key programmed into the storage device once. The mmc-utils manual describes rpmb write-key as programming an "authentication key which is 32 bytes length" and marks it "a one-time programmable (irreversible) change". In an Android phone the TEE owns this key, and the normal operating system never needs it.
  2. A write counter that the device keeps and increments on every authenticated write. mmc-utils can read it with rpmb read-counter.
  3. A message authentication code computed with the shared key, carried on write requests and on read responses.

The normal OS can relay, delay or drop frames, but it cannot forge a valid write without the key, and it cannot replay an old write because the counter has moved on. Read responses are authenticated too: mmc-utils reads RPMB in 256 byte blocks and, if you give it the key, verifies the data that came back.

How Android carries RPMB frames

Android's storageproxyd is the normal world helper that ferries RPMB frames between Trusty and the storage device. Its source shows how different the two interfaces are:

  • On eMMC, it opens the RPMB block device and sends a multi command MMC ioctl, using CMD25 with the reliable write flag for writes and CMD18 for reads, in 512 byte blocks.
  • On UFS, it issues SCSI SECURITY PROTOCOL OUT (operation code B5h) and SECURITY PROTOCOL IN (A2h) with security protocol ECh, which the source labels "JEDEC Universal Flash Storage", through the Linux SCSI generic SG_IO interface. It retries reads up to three times and writes once.
  • It also supports virtual RPMB devices for emulated targets.

The proxy never needs to understand the content; it moves opaque, authenticated frames.

What Trusty builds on top

Android describes Trusty as "a secure operating system (OS) that provides a Trusted Execution Environment (TEE) for Android". It runs on the same processor as Android but is isolated by hardware and software; on Arm systems it uses TrustZone. Its kernel is derived from Little Kernel, and a Linux driver passes data between the two worlds. Among TEE uses, Android lists "device reset protection, replay-protected persistent storage, secure PIN and fingerprint processing".

Trusty's storage interface header (interface/storage/storage.h) shows the guarantees a Trusty app can ask for, each as a separate IPC port:

PortGuarantee in the header commentTypical use
NSPPersistence without rollback detection; tamper detection by authenticated encryptionData where rollback is acceptable
TDTamper and rollback detectionMost secure app state
TDPTamper and rollback detection, and "Data will be preserved during a normal device wipe"State that must survive a factory reset
TDEAStorage available "before the non-secure os has booted"Early boot state
TPTamper proof: "non-secure code can prevent read and write operations from succeeding, but it cannot modify on-disk data"The strongest class, the property RPMB is built to provide

The TDP line matters for erasure: a normal factory reset is designed not to clear some TEE state. "Factory reset" is a product behaviour, not a sanitisation method.

Anti rollback in practice

AVB gives each image a rollback index and keeps the highest seen value in tamper evident storage. The README states the rule: reject an image "unless rollback_index[n] >= stored_rollback_index[n] for all n", and increase the stored value over time. The build sets it with BOARD_AVB_ROLLBACK_INDEX, which "defaults to 0". If the stored value lived in an ordinary partition, anyone who could write that partition could reset it and boot an old, vulnerable image.

How does inline encryption work?

Engines in the host controller

The kernel's inline encryption documentation opens with the key distinction: inline encryption hardware "sits logically between memory and disk, and can en/decrypt data as it goes in/out of the disk". It is not a crypto accelerator that works on memory buffers, and it is not a self encrypting drive. Self encrypting drives "don't provide fine-grained control of encryption and provide no way to verify the correctness of the resulting ciphertext". Inline hardware lets software choose the key and the initialisation vector for each sector, and its output can be tested.

Most inline engines have a fixed number of keyslots. Software programs a key, algorithm and data unit size into a slot, and each I/O request then carries just a slot index and a data unit number from which the IV is derived. The engine lives in the UFS or eMMC host controller on the SoC, which is why Android's kernel configuration has separate switches for each: CONFIG_SCSI_UFS_CRYPTO for UFS and CONFIG_MMC_CRYPTO for eMMC.

blk-crypto: how the kernel drives it

The block layer manages it with struct blk_crypto_key (key type, raw or hardware wrapped, plus algorithm and data unit size), struct bio_crypt_ctx (the key and data unit number attached to each I/O, where "WRITE means encrypt, and READ means decrypt") and struct blk_crypto_profile (how a driver advertises capabilities and programs or evicts keys). The block layer tracks which key sits in which slot and reprograms the least recently used idle slot when needed.

Two details carry security weight. A controller reset wipes the keyslots, so the driver must restore them with blk_crypto_reprogram_all_keys(), and resets are routine error recovery. And at end of life a key must be evicted from every slot with blk_crypto_evict_key(), after which callers zero their own copy, a step that "has no dedicated function".

If the hardware cannot handle a request, blk-crypto-fallback encrypts with the kernel crypto API instead, and the on disk ciphertext is the same either way. If a device supports block integrity, the kernel ignores its inline encryption, because no hardware was known to implement both correctly together.

The kernel's stable ABI lists what each device advertises under /sys/block/DISK/queue/crypto/; the walkthrough reads it.

Android file based encryption on top

Android has supported file based encryption (FBE) since Android 7.0, and "All devices launching with Android 10 and higher are required to use file-based encryption." FBE gives every user two storage classes:

  • Credential Encrypted (CE) storage, the default, available only after the user unlocks the device.
  • Device Encrypted (DE) storage, available during Direct Boot (before first unlock) and after.

Android's guidance is blunt: "Whenever possible, files should reside in CE storage."

FBE is set in the device's fstab with a fileencryption= option, and inline hardware is turned on with a separate inlinecrypt mount option. Android's documentation gives this example line:

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

The flags carry hardware facts. inlinecrypt_optimized selects a key and IV layout suited to engines with few keyslots. emmc_optimized does the same but limits IVs to 32 bits, for hardware compliant with the JEDEC eMMC v5.2 specification, and Android says it "should never be used on UFS-based storage; the UFS specification allows the use of 64-bit IVs." Since Android 15, dusize_4k forces a 4,096 byte encryption data unit for engines that cannot handle larger units on large page f2fs devices. Without inline hardware, Android recommends fileencryption=aes-256-xts; on devices with no AES acceleration at all, Adiantum is the alternative.

FBE encrypts file contents and names. Everything else, which Android lists as "directory layouts, file sizes, permissions, and creation/modification times", is covered by metadata encryption, introduced in Android 9 and required on internal storage for devices launching with Android 11 or later. A single key present at boot encrypts what FBE does not; it is protected by KeyMint (previously Keymaster), which "in turn is protected by Verified Boot". It requires the dm-default-key device mapper module.

Hardware wrapped keys

Storage encryption traditionally lets the raw key sit in kernel memory, since the main threat is offline. The kernel documentation lists what that misses: cold boot memory dumps, attacks that can read kernel memory without full compromise, and compromises where exfiltration is limited so the attacker wants the key.

Hardware wrapped keys, which Android introduced in Android 11, address this. The raw key is known only to hardware. Software holds it only in wrapped form: long term wrapped for storage on disk, and ephemerally wrapped (with a per boot key) while in use. When the controller resets, the kernel can hand the ephemerally wrapped blob back to the hardware to reprogram the slot without ever seeing the raw key. In fstab this is the wrappedkey flag (or the legacy wrappedkey_v0). Because the kernel never sees the raw key, the software fallback cannot be used with wrapped keys; they work only with real inline hardware.

The documentation admits it is "impossible to fully protect users' data from these attacks", since decrypted pages remain in memory; the goal is protecting the keys.

Erase, discard, sanitize and secure erase: what is the difference?

Why flash makes this hard

On a magnetic disk, writing zeros over a sector replaces the old magnetisation in place. On flash, a write to a logical block goes to a fresh physical page, and the old page is merely marked invalid until garbage collection erases its block, which may be much later. The controller also keeps spare blocks the host cannot address, moves data around for wear levelling and retires worn blocks with data still on them. NIST puts it plainly: for "flash memory-based storage devices that contain spare cells and perform wear levelling", it is "infeasible for a user to sanitize all previous data" by overwriting through the normal read and write interface.

The command vocabulary

eMMC and the Linux tools around it give you several operations with similar names and very different meanings. mmc-utils's erase command lists the types legacy, discard, secure-erase, secure-trim1, secure-trim2 and trim.

OperationWhat it promisesWhere old copies can survive
Delete a fileThe file system forgets the blocksEverywhere: the data is untouched until reused
Discard or trimTells the device these logical blocks no longer hold useful data; the device may erase them laterPhysical pages until garbage collection, plus older copies already moved
Erase (legacy)Erases the addressed erase groupsCopies the controller moved elsewhere earlier
Secure erase and secure trimeMMC operations aimed at removing the data in an address range, including copies the controller madeDepends on the controller's implementation; check what the part advertises
Secure discard (blkdiscard -s)A discard where "all copies of the discarded blocks that were possibly created by garbage collection must also be erased"; "requires support from the device"Anything the device does not actually implement
Sanitize (eMMC)mmc-utils: "delete the unmapped memory region of the device"Mapped (live) data is untouched; you must discard or erase it first
Purge (UFS)The UFS counterpart of sanitize; Linux exposes its progress through a read only purge_status attributeAs above, implementation dependent
Sanitize (NVMe)Block erase, overwrite or crypto erase across the whole device, chosen with the sanitize actionImplementation dependent; check the vendor's statement
Cryptographic eraseDestroy the key, leaving only ciphertextAny data ever written in plaintext

eMMC sanitize cleans only the unmapped region, the stale copies, not live mapped blocks. A full logical wipe is two steps: discard or erase the whole user area, then sanitize.

The kernel's MMC documentation adds that one erase command stalls all other I/O on the card, that large erase timeouts "can end up being several minutes", and that trim's minimum is "always one 512 byte sector" regardless of erase_size.

What NIST SP 800-88 Rev. 2 says

NIST published SP 800-88 Rev. 2, Guidelines for Media Sanitization, in September 2025, superseding Rev. 1 of 17 December 2014. Three points matter for embedded flash.

Technique specific guidance has moved out. Rev. 2 keeps the three sanitisation methods: clear, purge and destroy. But it states that "Except for cryptographic erase (see Sec. 3.2), technology-specific sanitization techniques are out of scope for this document", and tells readers to consult the latest version of standards such as IEEE 2883 (the IEEE Standard for Sanitizing Storage). So NIST no longer tells you which eMMC or UFS command counts as purge; that comes from IEEE 2883 and the device vendor's statement.

Overwriting flash is called out. In the clear section, Rev. 2 explains the wear levelling problem quoted above and warns that people who carried overwrite habits from magnetic media to flash "can be exposing their data to increased risk of unintentional disclosure". It adds that the device "may support dedicated sanitize commands that address all storage areas more effectively", with a trade off: they "require trust and assurance from the ISM vendor that the commands have been implemented as expected".

Purge and cryptographic erase are spelled out. Logical purge techniques "can include overwrite, block erase, and cryptographic erase using dedicated, standardized device sanitize commands". Cryptographic erase (CE) is "noteworthy in its ability to rapidly sanitize target data", but only with strong cryptography and a hard precondition, taken from ISO/IEC 27040: "no sensitive data has previously been stored on the ISM in plaintext form". Rev. 2's Table 1 lists the CE considerations: key generation (SP 800-90A, 90B, 90C, 800-133), the encryption itself (FIPS 140-3, FIPS 197, SP 800-38A and 800-38E, with ECB not allowed), key level and wrapping (where the key destroyed might be a wrapping key rather than the data key) and key derivation. Federal agencies "must use encryption modules validated to the current FIPS-140 standard" to rely on CE for a self encrypting drive.

Appendix B tells buyers to ask vendors which sanitize commands a device supports, which areas each misses, how long each takes and what validation was done. Appendix C gives a sample Certificate of Sanitization. NIST also warns that same named commands on two interfaces can "perform very different sanitization operations".

How this maps to a phone

A phone that launched with Android 11 or later has FBE and metadata encryption, both tied to KeyMint and TEE secrets. A reset that destroys those keys leaves ciphertext, which resembles cryptographic erase, but meets NIST's precondition only if no sensitive data was ever written unencrypted. Upgraded devices, unencrypted cards and embedded Linux systems without encryption do not meet it; plan on discard plus sanitize or purge, checked against the vendor's statement, or destruction.

Comparison: eMMC, UFS, NVMe SSD and SD card

eMMCUFSNVMe SSDSD card
FormSoldered BGA packageSoldered BGA package (the standard also covers removable media)Module or soldered, on PCI ExpressRemovable card
InterfaceParallel MMC bus, 1, 4 or 8 bitsSerial MIPI M-PHY with UniPro, SCSI subset in UPIUsPCIe with the NVMe command setSD bus
Linux device/dev/mmcblkN, bootN, rpmb/dev/sdX per LU, /dev/ufs-bsg/dev/nvmeN, /dev/nvmeNnM/dev/mmcblkN
RPMBYes, dedicated partitionYes, reached with SCSI security protocol commandsOptional RPMB targets, reachable with nvme rpmbNot assumed; check the card
Inline cryptoIn the host controller on supporting SoCs, eMMC v5.2 era, 32 bit IVsIn the host controller (UFSHCI), 64 bit IVs allowedNot in the host path; drives may encrypt internallyNot typical
Sanitise optionsDiscard, erase, secure erase and trim types, sanitizeUnmap, purgeSanitize with block erase, overwrite or crypto erase; Format (nvme format)Erase; capabilities vary
Health reportingLife time estimation and pre end of life fields in extended CSDhealth_descriptor attributes and critical_healthSMART and health log (nvme smart-log)Little or none
Typical devicesLower cost phones, routers, cars, SBCsMost current phones and tablets, newer carsPCs, servers, high end embeddedCameras, hobby boards, removable expansion

Note the inline crypto row: the engine is in the SoC's host controller, so the eMMC or UFS part stores ciphertext and never sees the key, the opposite of a self encrypting drive.

Dated timeline: the features this post relies on

WhenWhatSource
UFS 1.0 and 1.1Gear 1 mandatory, Gear 2 optional, SCSI based command layerLinux UFS documentation
17 December 2014NIST SP 800-88 Rev. 1NIST CSRC
eMMC v5.2Inline encryption with 32 bit IVs, the reason for Android's emmc_optimizedAndroid FBE documentation
Android 7.0File based encryption and Direct Boot (CE and DE storage)Android FBE documentation
Android 9Metadata encryption introduced; FBE compatible with adoptable storageAndroid metadata encryption and FBE documentation
Android 10FBE required for devices launching with Android 10 and laterAndroid FBE documentation
Android 11Metadata encryption required on internal storage for new launches; hardware wrapped keys introducedAndroid metadata encryption and wrapped keys documentation
Android 15dusize_4k FBE flagAndroid FBE documentation
February 2025Linux critical_health UFS attribute documentedLinux sysfs-driver-ufs ABI
September 2025NIST SP 800-88 Rev. 2, technique specific guidance moved to IEEE 2883NIST CSRC

Step by step on Linux: identify, inspect, then sanitise

These steps assume a Linux system with root access: a single board computer, an embedded target with a shell, or a phone running a development build. Read only steps are marked. Steps 6 and 7 destroy data. Do them only on a device you own, that you intend to wipe, with any data you need backed up elsewhere.

Step 1: identify the storage (read only)

# List whole disks with transport and model
lsblk -d -o NAME,SIZE,TYPE,TRAN,MODEL,ROTA

# eMMC and SD show up as mmcblk; UFS LUs show up as sd devices on a ufs host
ls -l /dev/mmcblk* 2>/dev/null
ls /sys/bus/platform/devices/ | grep -i ufs

# Which device holds the running root file system?
findmnt -n -o SOURCE /
cat /proc/cmdline

mmcblk0 with boot0, boot1 and rpmb siblings is eMMC; a bare mmcblk1 is usually an SD card; SCSI disks under a *.ufs platform device are UFS logical units.

Step 2: read eMMC identity and health (read only)

D=/sys/block/mmcblk0/device
for f in name manfid oemid date serial prv raw_rpmb_size_mult rel_sectors erase_size preferred_erase_size cmdq_en; do
  printf '%-22s %s\n' "$f" "$(cat $D/$f 2>/dev/null)"
done

These are the kernel's documented MMC attributes. fwrev applies only to SD and MMC v1 cards, so on eMMC read firmware fields from the extended CSD.

Step 3: read the eMMC extended CSD with mmc-utils (read only)

mmc-utils is the kernel community's eMMC tool, maintained by Ulf Hansson and packaged by most distributions.

mmc extcsd read /dev/mmcblk0 > extcsd.txt
grep -i -E 'life|eol|sanitize|secure|rpmb|firmware|revision|boot' extcsd.txt
mmc writeprotect boot get /dev/mmcblk0
mmc writeprotect user get /dev/mmcblk0
mmc status get /dev/mmcblk0

Look for life time estimation and pre end of life fields, the advertised secure erase and sanitize features, RPMB size, firmware fields and boot configuration. Labels differ between versions, so grep broadly.

Do not run mmc rpmb write-key, gp create, enh_area set, write_reliability set, hwreset enable or hwreset disable, or bkops_en manual while exploring. The manual marks each as one time programmable or irreversible.

Step 4: read UFS descriptors through sysfs (read only)

U=$(ls -d /sys/bus/platform/devices/*.ufs 2>/dev/null | head -n 1)
echo "UFS host: $U"
for f in device_descriptor/specification_version device_descriptor/manufacturer_id \
         string_descriptors/manufacturer_name string_descriptors/product_name string_descriptors/product_revision \
         health_descriptor/life_time_estimation_a health_descriptor/life_time_estimation_b health_descriptor/eol_info \
         geometry_descriptor/rpmb_rw_size attributes/purge_status critical_health; do
  printf '%-45s %s\n' "$f" "$(cat $U/$f 2>/dev/null)"
done

All appear in the kernel's sysfs-driver-ufs ABI. product_revision is the nearest thing to a firmware version, the health descriptor fields show wear, and critical_health counts critical health events. On PCI attached hosts, search /sys for health_descriptor.

Step 5: check inline encryption capability (read only)

for q in /sys/block/*/queue/crypto; do
  [ -d "$q" ] || continue
  dev=$(echo "$q" | cut -d/ -f4)
  echo "== $dev"
  echo "keyslots:       $(cat $q/num_keyslots 2>/dev/null)"
  echo "max dun bits:   $(cat $q/max_dun_bits 2>/dev/null)"
  echo "raw keys:       $(cat $q/raw_keys 2>/dev/null)"
  echo "wrapped keys:   $(cat $q/hw_wrapped_keys 2>/dev/null)"
  ls "$q/modes" 2>/dev/null
done

No queue/crypto directory means no inline encryption is registered for that queue. On Android, check the fstab for inlinecrypt and the fileencryption= flags.

Step 6: device path check before any destructive command

Warning: the next steps permanently destroy data on the target device. Run this check immediately before each destructive block, every time, and stop if any line surprises you.

TARGET=/dev/mmcblk1          # set this deliberately; never copy it from a tutorial
lsblk -o NAME,SIZE,TYPE,MODEL,SERIAL,MOUNTPOINTS "$TARGET"
cat /sys/block/$(basename "$TARGET")/device/name 2>/dev/null
cat /sys/block/$(basename "$TARGET")/device/serial 2>/dev/null
findmnt -n -o SOURCE / | grep -q "$(basename "$TARGET")" && echo "STOP: this is the root device"
grep "$(basename "$TARGET")" /proc/mounts && echo "STOP: something is mounted from this device"

Confirm the size, the CID name and serial match the part you intend to wipe, and that nothing on it is mounted. If the system is running from the target, boot from other media first.

Step 7: discard, then sanitize an eMMC user area

Warning: this destroys all data in the user area of the device in TARGET. Repeat the Step 6 check right before running it.

# Re-run the Step 6 checks here, then:
blkdiscard -v "$TARGET"                 # unmap every block in the user area
mmc sanitize "$TARGET"                   # remove stale copies in unmapped blocks
mmc extcsd read "$TARGET" | grep -i -E 'sanitize|secure'

blkdiscard discards the whole device by default and, since util-linux 2.36, opens it exclusively to avoid colliding with a mounted file system. Where supported, blkdiscard -s also erases copies made by garbage collection. None of this touches the boot partitions or RPMB; leave both alone unless the platform vendor documents a reset procedure.

Step 8: comparison commands for UFS and NVMe

Warning: the NVMe sanitize command below destroys all data on the whole controller. Repeat a device path check adapted for /dev/nvmeN before running it.

UFS purge is a device management operation, issued as a query request in a UPIU, which Linux lets userspace send through /dev/ufs-bsg. The kernel docs point to a userspace UPIU tool for that; follow the platform vendor's procedure, then confirm progress with cat $U/attributes/purge_status. Ask the vendor which areas purge reaches, as NIST's Appendix B suggests.

For an NVMe drive in the same fleet, nvme-cli exposes the standard sanitize actions:

# Re-run your device path check for the NVMe controller, then:
nvme sanitize /dev/nvme0 -a start-crypto-erase    # or start-block-erase
nvme sanitize-log /dev/nvme0

Record what you ran, the device identifiers and the result. NIST's Appendix C sample certificate lists the fields worth keeping.

Embedded supply chain angle: firmware is a component, wear is a schedule

The controller firmware is software you ship

Every eMMC and UFS controller runs firmware that decides how wear levelling, power loss handling, sanitize or purge and RPMB authentication behave. It has a readable revision (the UFS product_revision string, the eMMC CID product revision and extended CSD firmware fields), and vendors ship updates through the device maker. When an OTA update includes storage firmware, that firmware is a component of the release like the kernel.

  • Record the part and firmware per build during manufacturing test and keep them with the device's SBOM, so a vendor fix for corruption or a sanitize defect maps to affected units.
  • Track second sources. Boards often qualify several storage vendors, each with its own firmware line and sanitize implementation.
  • Keep the host side current. Host controller drivers, blk-crypto, the TEE and the storage proxy are open source components in your BSP.

Plan for wear out in fleets

Both standards report wear. A fleet that logs UFS life_time_estimation_a, _b and eol_info, or the eMMC equivalents, every week sees which units will fail first and why: heavy logging, swap on flash, a database writing far more than needed. Keep chatty writes in RAM or batch them, leave free space for wear levelling, and make sure discard reaches the device.

Common mistakes

  1. Factory reset on a device that never had encryption. Without encryption from first boot, a reset may only reformat. NIST's cryptographic erase precondition covers the device's whole history.
  2. Assuming delete equals erase. Deleting or discarding only marks data unwanted. Use sanitize or purge after discard when it must be gone.
  3. Overwriting flash and calling it sanitised. Writing zeros tells you nothing about copies the controller moved away.
  4. Ignoring wear levelling remnants. Blocks retired as worn can still hold data that only the controller's sanitize, purge or crypto erase path, or destruction, reaches.
  5. Writing to RPMB without understanding the key. The key is programmed once. Run mmc rpmb write-key on a production part and the TEE can no longer use RPMB. Treat RPMB as owned by the TEE, and treat every other one time eMMC setting as a factory step.
  6. Unlocking boot partitions casually. echo 0 > force_ro is a legitimate step when reflashing a bootloader, and a common way to brick a board when aimed at the wrong device. Turn it back on with echo 1 afterwards.
  7. Using emmc_optimized on UFS or skipping inlinecrypt. Android's documentation says the eMMC flag "should never be used on UFS-based storage". Forgetting the inlinecrypt mount option means the CPU does the encryption and the inline engine sits idle.
  8. Treating every "secure erase" as the same thing. The same command name on two interfaces can do different things, as NIST notes. Read what each device's vendor says the command reaches.
  9. Forgetting removable and adoptable storage. An SD card used as adoptable storage is encrypted; an SD card used as portable storage is not. Sanitise or destroy cards separately.

FAQ

What is the difference between eMMC and UFS?

Both are JEDEC standards for soldered, managed flash. eMMC uses a parallel bus of up to eight data lines and MMC commands; UFS uses serial MIPI M-PHY lanes with UniPro and carries SCSI commands inside UPIUs, with queueing designed in from the start.

Is UFS faster than eMMC?

Usually, because a serial, queued link scales better than a shared parallel bus, and UFS can use more than one lane. Real speed also depends on the NAND, firmware and host, so compare measured results for specific parts.

What is RPMB on a phone?

A small authenticated area on the eMMC or UFS part. Writes need a MAC made with a once programmed key the TEE owns, and a counter blocks replays. Trusty uses it for tamper proof storage.

Can you erase RPMB?

Not usefully from the normal OS. Only the key holder, the TEE, can write valid data, and the key cannot be changed once programmed.

Does a factory reset securely erase an Android phone?

If the device used file based and metadata encryption from first boot, a reset that destroys the keys leaves only ciphertext, much like cryptographic erase. NIST counts that as purge only if no sensitive data was ever stored in plaintext.

What is inline encryption?

An AES engine in the storage host controller that encrypts data on the way to flash and decrypts it on the way back, using keyslots. Linux drives it through blk-crypto; Android enables it with the inlinecrypt mount option.

What does NIST SP 800-88 Rev. 2 say about flash storage?

It keeps clear, purge and destroy, calls overwriting infeasible on flash, says dedicated sanitize commands need trust in the vendor's implementation, and points to IEEE 2883 for techniques.

What is the difference between sanitize and secure erase on eMMC?

Sanitize cleans the unmapped region, the stale copies left after discards, so discard first and sanitize second. Secure erase and secure trim target an address range. Check the extended CSD for what your part supports.

Where Safeguard fits

Safeguard's fit here is indirect. It does not read eMMC or UFS descriptors, manage devices, scan firmware images, generate hardware bills of materials, run sanitize commands or certify wipes. Those jobs belong to device management, manufacturing test and asset disposal.

Where Safeguard helps is the software around these devices. The board support package, the bootloader build, the kernel configuration, the TEE apps, the storage proxy and the fleet tooling that collects health data are software you build, and they pull open source components like anything else. Safeguard scans those repositories, container images and SBOM files for vulnerable components (safeguard scan --dir ., --image <name>, --sbom <file>), shows which projects contain a given component and version, and evaluates policies and gates against the results. Gate actions are Block, Warn and Notify, and teams approve exceptions through the platform rather than by switching a gate off. If you import an SBOM that already lists your storage firmware revisions, Safeguard can show which products carry each version, but the coverage you get depends on the inventory you feed it.

Rebuilding a fleet image pulls every dependency again, and BSP, driver and TEE code ship open source components that need the same patch discipline as any service. The next section covers closing the gap when a fix is slow, with the limit that storage controller firmware still has to come from the storage vendor.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.

3. Gold Registry: start from components that are already fixed

Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The demos show Safeguard on ordinary software projects, not storage hardware; they fit the BSP, kernel, TEE and fleet tooling repositories around these devices.

The first demo is a real Safeguard CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repository, and it reads the finding and advisory, asks before any command that changes something, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. It ends with /permissions, /model and /scan. The same review loop suits the fleet dashboard or OTA tooling that collects storage health, where every change should be seen by a person before it ships.

Click through it at your own pace, or open it full screen.

The second demo sets up the Safeguard local runner on your own machine, approves it with its device code and then runs a scan from the terminal. That suits a firmware build host that holds BSP and image repositories you want scanned where they are built.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and shows how you choose which tools Claude can use. An embedded team can then ask about findings in the repositories that build their device images, with Claude limited to the tools you allowed.

Click through it at your own pace, or open it full screen.

Safeguard's desktop and CLI downloads are at safeguard.sh/download, and the CLI documentation is at docs.safeguard.sh/docs/cli.

Quick check

You discard every block on an eMMC user area. Why run sanitize afterwards?

Discard only unmaps the logical blocks. The physical pages, and older copies the controller moved during wear levelling, can still hold data until they are erased. eMMC sanitize removes data from the unmapped region, so discard then sanitize covers both live and stale copies, as far as the controller's implementation goes.

Why can a compromised Android kernel not roll back a Trusty TP storage file?

Writes to RPMB need a MAC made with a key only the TEE holds, and the device's write counter rejects replays of older frames. The normal world can block reads and writes, but as Trusty's header puts it, it "cannot modify on-disk data".

Sources

Last reviewed: 25 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.