1. 什么是RPMB
首先RPMB是repaly protected memory block,从字面意思理解就是一个回放保护的存储区域。
这个区域是EMMC或者UFS上的一个区域,这个区域可以读,可以写,但是读和写是受到访问控制和回放保护的。UFS上的RPMB空间大小一般是16M;
EMMC上的RPMB空间大小一般是4M,也有64K的;
所以RPMB的空间大小一般看选择的存储芯片的数据手册(遇到过EMMC上没有RPMB区域的)。
一般情况下数据需要具备几个要素:
- 机密性
- 完整性
- 新鲜性
- 可用性
回放保护,可以保证数据的新鲜性。
2. 什么是回放保护
理解回放保护,我们先理解一下回放攻击。
int write_file()
{
char *data = “123456”;
int fd;
fd = open(“a.txt”, O_RDWR);
if (fd < 0) {
printf(“open a.txt failed, errno= %d\n”, errno);
return -1;
}
int wlen = write(fd, data, strlen(data)); if (wlen != strlen(data)) { printf("write failed"); close(fd); return -2; } printf("write file success\n"); close(fd); return 0;
}
上边方法,我们往a.txt中写入了一些数据,这个时候,如果我们将写完的文件备份出来,备份成b.txt,我们使用程序读a.txt,是可以正常读出来的,然后再将a.txt删除,最后再将b.txt拷贝成a.txt,
如果有回放保护,那么程序再读a.txt,应该会失败。如果成功,那么证明就没有回放保护机制。
3. RPMB的工作原理
RPMB功能
- get counter: 获取RPMB中counter计数器;
- program key:写入RPMB key,每个RPMB在生命周期内,都需要program仅仅一次密钥,这个动作可以在工厂完成,也可以每次开机在bootloader中自动完成;
- read:读RPMB中的数据;
- write:往RPMB中写数据;
- get max wr size: 获取一次可以往RPMB中写入的最大数据量;
RPMB操作关键数据结构
struct rpmb_frame { u_int8_t stuff[196]; //无用 u_int8_t key_mac[32]; //rpmb key,program rpmb key指令的时候会使用到 u_int8_t data[256];//对RPMB进行读写的数据 u_int8_t nonce[16];//一个随机数,可以不使用,如果使用,需要发起者生成随机数,RPMB硬件对随机数与其它数据一起做mac,发起者调用返回之后,需要验证mac与nonce,保证调用是新鲜的。相当于很多场景中challenge的意思。 u_int32_t write_counter; //写操作的时候,counter标记,用户防止回放攻击 u_int16_t addr; //读写RPMB的地址,块设备操作,每次操作256字节,因此这个地方可以是256的整数倍 u_int16_t block_count;//每次读写几块RPMB数据,一块是256字节 u_int16_t result; //操作之后的返回结果,对frameout的数据有效 u_int16_t req_resp; //本次操作的CMD, 代表本次要做什么 };
RPMB program key
此动作可以在开机的时候自动完成,由bootloader来操作,也可以通过用户产线手动绑定。
注意:
RPMB KEY大部分情况下与CPU进行绑定,也就是说,如果CPU损坏,那么在维修的时候,也需要更换EMMC或者UFS
由于RPMB KEY与CPU进行绑定,所以大部分客户在使用RPMB的时候,都是使用工厂program key的方案。原因:降低成本。
工厂需要进行CPU的老化测试,如果CPU与EMMC进行提前绑定,那么CPU坏的情况,会导致EMMC的浪费,因此大量生产的情况下,客户都会选择延迟绑定的方案来节省成本。
RPMB READ and WRITE原理
RPMB读写: 调用原理
4. RPMB实现参考
EMMC RPMB: 应用调用实现参考
UFS RPMB: 应用调用实现参考/dev/0:0:0:49476
trusty REE RPMB: REE端RPMB调用
trusty TEE RPMB: TEE端RPMB调用