Android 加密

Device Encryption

Posted by LXG on August 16, 2024

加密-AOSP

深入理解Android之设备加密Device Encryption

概念

加密是使用对称加密密钥对 Android 设备上的所有用户数据进行编码的过程。设备经过加密后,所有由用户创建的数据在存入磁盘之前都会自动加密,并且所有读取操作都会在将数据返回给调用进程之前自动解密数据。加密可确保未经授权方在尝试访问相应数据时无法进行读取。

Android 有两种设备加密方法,即文件级加密和全盘加密。

文件级加密

Android 7.0 及更高版本支持文件级加密。采用文件级加密时,可以使用不同的密钥对不同的文件进行加密,也可以对加密文件单独解密

全盘加密

搭载 Android 10 及更高版本的新设备上不允许使用全盘加密。请在新设备上使用文件级加密

Android 5.0 到 Android 9 支持全盘加密。全盘加密是使用单个密钥(由用户的设备密码加以保护)来保护设备的整个用户数据分区。在启动时,用户必须先提供其凭据,然后才能访问磁盘的任何部分。

加密配置

./rockchip/rk3399/rk3399_all.mk


./rockchip/rk3399/rk3399_all.mk:BUILD_WITH_FORCEENCRYPT := true

device/rockchip/rk3399/device.mk


ifeq ($(BUILD_WITH_FORCEENCRYPT),true)
PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/fstab.rk30board.bootmode.forceencrypt.unknown:root/fstab.rk30board.bootmode.unknown \
    $(LOCAL_PATH)/fstab.rk30board.bootmode.forceencrypt.emmc:root/fstab.rk30board.bootmode.emmc \
    $(LOCAL_PATH)/fstab.rk30board.bootmode.forceencrypt.nvme:root/fstab.rk30board.bootmode.nvme
else
PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/fstab.rk30board.bootmode.unknown:root/fstab.rk30board.bootmode.unknown \
    $(LOCAL_PATH)/fstab.rk30board.bootmode.emmc:root/fstab.rk30board.bootmode.emmc \
    $(LOCAL_PATH)/fstab.rk30board.bootmode.nvme:root/fstab.rk30board.bootmode.nvme
endif

fstab.rk30board.bootmode.forceencrypt.emmc VS fstab.rk30board.bootmode.emmc

  • 差异点1: 是否支持system分区完整性校验 verify=/dev/block/platform/fe330000.sdhci/by-name/verity_mode
  • 差异点2: 是否强制全盘加密 forceencrypt=/metadata/key_file(强制) encryptable=/metadata/key_file(非强制)

***system 分区***

/dev/block/platform/fe330000.sdhci/by-name/system         /system             ext4      ro,noatime,nodiratime,noauto_da_alloc                                  wait,resize,verify=/dev/block/platform/fe330000.sdhci/by-name/verity_mode
# use this line below instead to enable verity
#/dev/block/platform/fe330000.sdhci/by-name/system         /system             ext4      ro,noatime,nodiratime,noauto_da_alloc                                  wait,check,verify


/dev/block/platform/fe330000.sdhci/by-name/cache          /cache              ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard                wait,check
/dev/block/platform/fe330000.sdhci/by-name/metadata       /metadata           ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard                wait,check

***userdata 分区加密forceencrypt=/metadata/key_file**

#data for ext4 
/dev/block/platform/fe330000.sdhci/by-name/userdata       /data               ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard,errors=panic,dirsync   wait,check,forceencrypt=/metadata/key_file


/dev/block/platform/fe330000.sdhci/by-name/misc          /misc                emmc        defaults      defaults
# sdcard
/devices/platform/fe320000.dwmmc/mmc_host*                auto  auto    defaults        voldmanaged=sdcard1:auto,encryptable=userdata

# for usb2.0
/devices/platform/*.usb*            auto vfat defaults      voldmanaged=usb:auto
# for usb3.0
/devices/platform/usb@*/*.dwc3*     auto vfat defaults      voldmanaged=usb:auto

# pcie
/devices/platform/*.pcie*           auto vfat defaults     voldmanaged=pcie:auto

/dev/block/zram0                                none                swap      defaults                                              zramsize=533413200

WIF VS Firefly

主要差异在于 forceencrypt 和 encryptable 这两个选项。forceencrypt 强制加密整个分区,而 encryptable 允许在加密文件系统中进行加密处理,但可能不强制全盘加密


**WIF**

/dev/block/platform/fe330000.sdhci/by-name/userdata       /data               ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard,errors=panic,dirsync   wait,check,forceencrypt=/metadata/key_file

**Firefly**

/dev/block/platform/fe330000.sdhci/by-name/userdata       /data               ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard,errors=panic,dirsync   wait,check,encryptable=/metadata/key_file

加密失败

src/com/android/settings/CryptKeeper.java


public class CryptKeeper extends Activity implements TextView.OnEditorActionListener,
        OnKeyListener, OnTouchListener, TextWatcher {


    private void updateProgress() {

        final String state = SystemProperties.get("vold.encrypt_progress");

        if ("error_partially_encrypted".equals(state)) {
            showFactoryReset(false);
            return;
        }
    
    }

    private void showFactoryReset(final boolean corrupt) {

        // Show the reset button, failure text, and a divider
        final Button button = (Button) findViewById(R.id.factory_reset);
        button.setVisibility(View.VISIBLE);    
    
    }

}