引言
在前两篇文章中,我们深入分析了Android 15的Vold存储管理框架和FUSE文件系统。本篇作为存储子系统系列的收官之作,将重点聚焦于存储安全与性能优化两大核心主题:
- FBE(File-Based Encryption):Android 7.0引入、在Android 15进一步增强的文件级加密机制
- f2fs:针对Flash存储优化的文件系统,Android 15默认推荐文件系统
- 存储性能优化:从诊断到调优的完整实战方法论
这三者紧密关联:FBE加密保证了数据安全但会带来性能开销,f2fs通过专门优化减少这一开销,而性能优化则需要理解二者的配合机制。
本文内容概览
FBE加密机制深度解析
- FBE vs FDE对比
- CE/DE密钥体系
- 加密策略与密钥派生
- Keymaster HAL与硬件支持
f2fs文件系统核心特性
- Flash友好的设计哲学
- 多头日志与热/冷数据分离
- 在线碎片整理与GC机制
- Android 15中的f2fs增强
Metadata加密与完整性保护
- dm-default-key设备映射器
- Metadata加密实现
- fsverity完整性验证
存储性能分析与优化
- I/O性能基准测试
- systrace/perfetto存储追踪
- 常见性能问题诊断
- f2fs调优参数详解
实战:存储问题诊断案例
- 慢速读写问题定位
- 随机I/O性能调优
- 空间占用异常排查
让我们开始深入探索Android 15存储系统的安全与性能奥秘!
一、FBE加密机制深度解析
1.1 为什么需要FBE?
在Android 7.0之前,Android使用FDE(Full Disk Encryption,全盘加密):整个/data分区使用单一密钥加密,解锁手机后密钥加载到内存,所有数据可访问。
FDE的问题:
- 开机后无法接听电话、接收闹钟(因为
/data未解密) - 必须先输入密码才能启动系统核心功能
- OTA升级需要用户手动输入密码
FBE的优势:
┌─────────────────┬──────────────────┐ │ FDE (全盘加密) │ FBE (文件加密) │ ├─────────────────┼──────────────────┤ │ 单一加密密钥 │ 多密钥体系 │ │ 必须解锁才能开机 │ Direct Boot支持 │ │ 无法接听来电 │ 开机即可接电话 │ │ OTA需要密码 │ OTA可后台进行 │ │ 性能开销大 │ 按需加密,开销小 │ └─────────────────┴──────────────────┘1.2 FBE核心概念:CE与DE密钥
FBE引入了两级密钥体系:
DE (Device Encrypted) - 设备加密
// system/vold/FsCrypt.cpp - DE密钥路径staticstd::stringget_de_key_path(userid_t user_id){returnStringPrintf("%s/de/%d",user_key_dir.c_str(),user_id);}特点:
- 开机后即可用(系统启动时自动加载)
- 不依赖用户凭证(PIN/密码/指纹)
- 用于存储系统核心功能数据
典型用途:
# DE加密的目录示例/data/user_de/0/com.android.providers.telephony# 电话应用/data/user_de/0/com.android.deskclock# 闹钟应用/data/user_de/0/com.android.bluetooth# 蓝牙CE (Credential Encrypted) - 凭证加密
// system/vold/FsCrypt.cpp - CE密钥路径staticstd::stringget_ce_key_directory_path(userid_t user_id){returnStringPrintf("%s/ce/%d",user_key_dir.c_str(),user_id);}特点:
- 用户解锁后才可用(从Keymaster派生)
- 基于用户凭证(PIN/密码/指纹)
- 用户锁屏后,CE密钥从内存清除
典型用途:
# CE加密的目录示例/data/user/0/com.android.providers.contacts# 联系人/data/user/0/com.android.providers.media# 相册/data/user/0/com.whatsapp# 应用私有数据1.3 FBE密钥派生流程
让我们从源码角度看密钥是如何生成和管理的:
1.3.1 DE密钥创建
// system/vold/FsCrypt.cppstaticboolcreate_de_key(userid_t user_id,boolephemeral){KeyBuffer de_key;std::string de_key_path=get_de_key_path(user_id);// 1. 生成随机密钥(或从Keymaster派生)autoconst&options=BuildDataEncryptionOptions(s_data_options,ephemeral);KeyGeneration key_gen=makeGen(options);if(!generateStorageKey(key_gen,&de_key)){LOG(ERROR)<<"Failed to generate DE key for user "<<user_id;returnfalse;}// 2. 将密钥存储到文件系统if(!android::vold::storeKey(de_key_path,user_key_temp,de_key)){LOG(ERROR)<<"Failed to store DE key";returnfalse;}// 3. 在内核中安装加密策略EncryptionPolicy de_policy;if(!installKey(de_key,de_policy)){LOG(ERROR)<<"Failed to install DE policy";returnfalse;}s_de_policies[user_id].internal=de_policy;LOG(INFO)<<"Created DE key for user "<<user_id;returntrue;}关键步骤:
- 生成密钥:调用
generateStorageKey()生成AES-256密钥 - 持久化存储:密钥文件存放在
/data/misc/vold/user_keys/de/<userid>/ - 内核安装:通过
FS_IOC_ADD_ENCRYPTION_KEYioctl安装到内核
1.3.2 CE密钥创建与派生
// system/vold/FsCrypt.cppboolfscrypt_prepare_user_storage(conststd::string&volume_uuid,userid_t user_id,intserial,intflags){// CE密钥创建if(flags&android::os::IVold::STORAGE_FLAG_CE){// 1. 从用户凭证派生密钥android::vold::KeyAuthentication auth;if(!getUserKeyAuth(user_id,&auth)){returnfalse;}KeyBuffer ce_key;if(!retrieveOrGenerateKey(ce_key_path,auth,makeGen(s_data_options),&ce_key)){returnfalse;}// 2. 安装CE加密策略EncryptionPolicy ce_policy;if(!install_storage_key(BuildDataPath(volume_uuid),s_data_options,ce_key,&ce_policy)){returnfalse;}s_ce_policies[user_id].internal=ce_policy;}returntrue;}CE密钥派生链:
用户密码/PIN ↓ scrypt(密码, salt) ← 密钥派生函数 ↓ 派生密钥 (Derived Key) ↓ Keymaster派生 (Hardware-backed) ↓ CE加密密钥 (AES-256) ↓ 内核fscrypt子系统1.4 Fscrypt内核接口
Android通过libfscrypt库与内核fscrypt子系统交互:
// system/extras/libfscrypt/fscrypt.cpp// 添加加密密钥到内核boolfscrypt_add_key_to_keyring(constfscrypt_key&key,constchar*mountpoint){android::base::unique_fdfd(open(mountpoint,O_RDONLY|O_DIRECTORY|O_CLOEXEC));structfscrypt_add_key_argarg;memset(&arg,0,sizeof(arg));arg.key_spec.type=FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;memcpy(arg.key_spec.u.descriptor,key.fek,FSCRYPT_KEY_DESCRIPTOR_SIZE);arg.raw_size=key.fek_size;memcpy(arg.raw,key.fek,key.fek_size);// ioctl系统调用if(ioctl(fd,FS_IOC_ADD_ENCRYPTION_KEY,&arg)!=0){PLOG(ERROR)<<"FS_IOC_ADD_ENCRYPTION_KEY failed";returnfalse;}returntrue;}// 设置目录加密策略boolfscrypt_policy_set(constchar*directory,constfscrypt_policy_v2&policy){android::base::unique_fdfd(open(directory,O_RDONLY|O_DIRECTORY|O_CLOEXEC));// 使用v2策略(Android 11+)if(ioctl(fd,FS_IOC_SET_ENCRYPTION_POLICY,&policy)!=0){PLOG(ERROR)<<"FS_IOC_SET_ENCRYPTION_POLICY failed on "<<directory;returnfalse;}returntrue;}内核ioctl命令:
// Linux kernel include/uapi/linux/fscrypt.h#defineFS_IOC_SET_ENCRYPTION_POLICY_IOR('f',19,structfscrypt_policy_v2)#