Jimmy Chen

A Programmer

(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE

  emmmmmmm……上一篇,我们尝试使用了软件加密方式来进行全盘加密。但是呢,软件加密正如其名是通过软件的方式进行加密操作,这样一来,在执行加密的时候就需要CPU的参与。如果需要加密的内容较多,那吃的CPU资源就多,同时消耗的电量也多,最坑爹的就是效率还不高。典型的吃得多做得少啊,有鉴于此,加入硬件加密还是很有必要的。

  上一篇也讲到,因为不确定8909上是否支持使用ICE进行加密,所以这一篇我是试着去配置的。发现可以使用,但是因为涉及到一些时序的问题,不能保证是完全正确的。下面就开始进行配置吧。

上一次讲到在load mapping table的时候出现失败,失败的原因是因为没有使用到硬件加密。这里开始我们尝试配置好硬件加密的内容。

static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr,
        const unsigned char *master_key, const char *real_blk_name,
        const char *name, int fd, const char *extra_params) {

  ........................

#ifdef CONFIG_HW_DISK_ENCRYPTION
  if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) {
    strlcpy(tgt->target_type, "req-crypt",DM_MAX_TYPE_NAME);
    if (is_ice_enabled())
      convert_key_to_hex_ascii(master_key, sizeof(int), master_key_ascii);
    else
      convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
  }
  else {
    convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
    strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
  }
  snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s 0",
           crypt_ftr->crypto_type_name, master_key_ascii,
           real_blk_name, extra_params);

  SLOGI("target_type = %s", tgt->target_type);
  SLOGI("real_blk_name = %s, extra_params = %s", real_blk_name, extra_params);
#else
  convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
  strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
  snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s",
           crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name,
           extra_params);
#endif

  ..................
  

首先将Boardconfig.mk中的TARGET_HW_DISK_ENCRYPTION改回true

ifeq ($(TARGET_USES_AOSP), true)
TARGET_HW_DISK_ENCRYPTION := false
SDCLANG_AE_CONFIG := device/duubee/msm8909test/sdclang.json
SDCLANG := true
SDCLANG_PATH :=prebuilts/clang/host/linux-x86/sdclang-4.0/bin
SDCLANG_LTO_DEFS := device/qcom/common/sdllvm-lto-defs.mk
else
SDCLANG := true
SDCLANG_LTO_DEFS := device/qcom/common/sdllvm-lto-defs.mk
TARGET_HW_DISK_ENCRYPTION := true
endif

《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》

看Makefile可以知道需要将CONFIG_DM_REQ_CRYPT配置为y才会将dm-req-crypt编译到内核中。我们在项目kernel的defconfig文件中添加如下一句

CONFIG_DM_REQ_CRYPT=y

回到load_crypto_mapping_table中,继续往下分析,在设置启用了dm-req-crypt加密插件后,接下来有一个is_ice_enabled函数,我们看看这个函数做了什么东西

load_crypto_mapping_table —> is_ice_enable

int is_ice_enabled(void)
{
  char prop_storage[PATH_MAX];
  int storage_type = 0;
  int fd;

  if (property_get("ro.boot.bootdevice", prop_storage, "")) {
    if (strstr(prop_storage, "ufs")) {
      /* All UFS based devices has ICE in it. So we dont need
       * to check if corresponding device exists or not
       */
      storage_type = QCOM_ICE_STORAGE_UFS;
    } else if (strstr(prop_storage, "sdhc")) {
      if (access("/dev/icesdcc", F_OK) != -1)
        storage_type = QCOM_ICE_STORAGE_SDCC;
    }
  }
  return storage_type;
}

可以看到如果是EMMC需要访问到/dev/icesdcc这个节点,所以需要看看icesdcc这个阶段是在哪里配置的,通过查找可以在kernel/msm-3.18/driver/crypto/msm/ice.c中找到定义

#define QCOM_UFS_ICE_DEV   "iceufs"
#define QCOM_SDCC_ICE_DEV  "icesdcc"


// dtb适配的节点
/* Following struct is required to match device with driver from dts file */
static struct of_device_id qcom_ice_match[] = {
    { .compatible = "qcom,ice" },
    {},
};
MODULE_DEVICE_TABLE(of, qcom_ice_match);

所以内核在配置icesdcc的时候是会查找设备树是否存在qcom,ice这个节点的。明显开始阶段8909是不存在这个节点的,那怎么办?折中的方法就是查看其它的设备树进行模仿配置,博主这里模仿使用的设备树是msm8917.dtsi

最后配置好的msm8909.dtsi设备树如下

    sdcc1_ice: sdcc1ice@7803000 {
        compatible = "qcom,ice";
        reg = <0x7803000 0x8000>;
        interrupt-names = "sdcc_ice_nonsec_level_irq",
                  "sdcc_ice_sec_level_irq";
        interrupts = <0 312 0>, <0 313 0>;
        qcom,enable-ice-clk;
        clock-names = "ice_core_clk_src", "ice_core_clk",
                "bus_clk", "iface_clk";
        clocks = <&clock_gcc clk_sdcc1_ice_core_clk_src>,
             <&clock_gcc clk_gcc_sdcc1_ice_core_clk>,
             <&clock_gcc clk_gcc_sdcc1_apps_clk>,
             <&clock_gcc clk_gcc_sdcc1_ahb_clk>;
        qcom,op-freq-hz = <200000000>, <0>, <0>, <0>;
        qcom,msm-bus,name = "sdcc_ice_noc";
        qcom,msm-bus,num-cases = <2>;
        qcom,msm-bus,num-paths = <1>;
        qcom,msm-bus,vectors-KBps =
            <78 512 0 0>,    /* No vote */
            <78 512 1000 0>; /* Max. bandwidth */
        qcom,bus-vector-names = "MIN", "MAX";
        qcom,instance-type = "sdcc";
    };

    sdhc_1: sdhci@7824000 {
        compatible = "qcom,sdhci-msm";
        reg = <0x07824900 0x11c>, <0x07824000 0x800>;
        reg-names = "hc_mem", "core_mem";

        interrupts = <0 123 0>, <0 138 0>;
        interrupt-names = "hc_irq", "pwr_irq";

        sdhc-msm-crypto = <&sdcc1_ice>;
        qcom,bus-width = <8>;

        qcom,pm-qos-irq-type = "affine_irq";
        qcom,pm-qos-irq-latency = <2 250>;

        qcom,msm-bus,name = "sdhc1";
        qcom,msm-bus,num-cases = <8>;
        qcom,msm-bus,num-paths = <1>;
        qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
                <78 512 1046 3200>,    /* 400 KB/s*/
                <78 512 52286 160000>, /* 20 MB/s */
                <78 512 65360 200000>, /* 25 MB/s */
                <78 512 130718 400000>, /* 50 MB/s */
                <78 512 261438 800000>, /* 100 MB/s */
                <78 512 261438 800000>, /* 200 MB/s */
                <78 512 1338562 4096000>; /* Max. bandwidth */
        qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
                        100000000 200000000 4294967295>;


        clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
             <&clock_gcc clk_gcc_sdcc1_apps_clk>,
             <&clock_gcc clk_gcc_sdcc1_ice_core_clk>;
        clock-names = "iface_clk", "core_clk", "ice_core_clk";
        qcom,ice-clk-rates = <200000000 100000000>;
        qcom,clk-rates = <400000 25000000 50000000 100000000 177770000>;
        qcom,devfreq,freq-table = <50000000 177770000>;

        status = "disabled";
    };

emmmm…..,这样还没完,还要在头文件中添加clk的定义,kernel/msm-3.18/include/dt-binding/clock/msm-clocks-8909.h中添加如下内容

#define clk_sdcc1_ice_core_clk_src     0xfd6a4301
#define clk_gcc_sdcc1_ice_core_clk     0x0fd5680a

设备树改完,但是还差最后一步,我们看看kernel/msm-3.18/driver/crypto/msm下的Makefile文件

obj-$(CONFIG_CRYPTO_DEV_QCEDEV) += qcedev.o
ifeq ($(CONFIG_CRYPTO_DEV_QCE50), y)
        obj-$(CONFIG_CRYPTO_DEV_QCOM_MSM_QCE) += qce50.o
else
        obj-$(CONFIG_CRYPTO_DEV_QCOM_MSM_QCE) += qce.o
endif
ifdef CONFIG_COMPAT
obj-$(CONFIG_CRYPTO_DEV_QCOM_MSM_QCE) += compat_qcedev.o
endif
obj-$(CONFIG_CRYPTO_DEV_QCRYPTO) += qcrypto.o
obj-$(CONFIG_CRYPTO_DEV_OTA_CRYPTO) += ota_crypto.o
obj-$(CONFIG_CRYPTO_DEV_QCOM_ICE) += ice.o

可以看到,还需要在kernel的defconfig文件中加上CONFIG_CRYPTO_DEV_QCOM_ICE=y的配置即可。

到这里就配置完成了,大家编译试一试吧。不过需要说明的是,在setting下执行加密后,手机会显示phone encrypted,但是我使用androbench2测试EMMC读写速度时发现启用ICE后测试出来的速度和没有启用FDE加密时相当。这就让我感觉ICE并没有启用成功,但是无论通过setting查看,还是adb shell getprop来查看都显示是encrypted了,这么说应该是启用成功了,不然我岂不是在无意中发现了一个BUG,emmmmmm…….,还有就是记得ICE的介绍有说,ICE不启用时就ICE是直接读写,启用的时候就进过ICE加解密再传送,也就是说都会经过ICE,那速度差不多好像也合理。具体是BUG还是ICE特性就是如此,请读者们自行斟酌啦,这里就当提供修改参考。

下面贴一下测试速度图:

不执行任何加密的测试结果

《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》
《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》

测试的时候,测试APK和mmcqd占用的CPU比较多。

启用软件加密的测试结果

《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》
《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》

软件加密的速度降得就有点夸张了,而且在测试的时候会启用4个kworker进行写入,CPU占用极高。

启用硬件加密的测试结果

《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》
《(原创)高通MSM8909+Android 8.1.0 FDE全盘加密失败分析记录(二)启用ICE》

硬件加密速度和不加密基本类似,CPU占用也差不多。

最后,以上内容仅供参考,下次有时间再在Pixel上试一试。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d 博主赞过: