emmmmmmm……上一篇,我们尝试使用了软件加密方式来进行全盘加密。但是呢,软件加密正如其名是通过软件的方式进行加密操作,这样一来,在执行加密的时候就需要CPU的参与。如果需要加密的内容较多,那吃的CPU资源就多,同时消耗的电量也多,最坑爹的就是效率还不高。典型的吃得多做得少啊,有鉴于此,加入硬件加密还是很有必要的。
上一篇也讲到,因为不确定8909上是否支持使用ICE进行加密,所以这一篇我是试着去配置的。发现可以使用,但是因为涉及到一些时序的问题,不能保证是完全正确的。下面就开始进行配置吧。
上一次讲到在load mapping table的时候出现失败,失败的原因是因为没有使用到硬件加密。这里开始我们尝试配置好硬件加密的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
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
1 2 3 4 5 6 7 8 9 10 11 |
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 <font color='red'>TARGET_HW_DISK_ENCRYPTION := true</font> endif |
看Makefile可以知道需要将CONFIG_DM_REQ_CRYPT配置为y才会将dm-req-crypt编译到内核中。我们在项目kernel的defconfig文件中添加如下一句
1 |
CONFIG_DM_REQ_CRYPT=y |
回到load_crypto_mapping_table中,继续往下分析,在设置启用了dm-req-crypt加密插件后,接下来有一个is_ice_enabled函数,我们看看这个函数做了什么东西
load_crypto_mapping_table —> is_ice_enable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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中找到定义
1 2 3 4 5 6 7 8 9 10 11 |
#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设备树如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
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中添加如下内容
1 2 |
#define clk_sdcc1_ice_core_clk_src 0xfd6a4301 #define clk_gcc_sdcc1_ice_core_clk 0x0fd5680a |
设备树改完,但是还差最后一步,我们看看kernel/msm-3.18/driver/crypto/msm下的Makefile文件
1 2 3 4 5 6 7 8 9 10 11 12 |
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 <font color='red'>obj-$(CONFIG_CRYPTO_DEV_QCOM_ICE) += ice.o</font> |
可以看到,还需要在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特性就是如此,请读者们自行斟酌啦,这里就当提供修改参考。
下面贴一下测试速度图:
不执行任何加密的测试结果
测试的时候,测试APK和mmcqd占用的CPU比较多。
启用软件加密的测试结果
软件加密的速度降得就有点夸张了,而且在测试的时候会启用4个kworker进行写入,CPU占用极高。
启用硬件加密的测试结果
硬件加密速度和不加密基本类似,CPU占用也差不多。
最后,以上内容仅供参考,下次有时间再在Pixel上试一试。