RPMB介绍与使用

信息安全

信息安全的三个基本目标是机密性完整性可用性

  • 机密性意味着只有授权实体才能阅读和理解保密的信息。没有访问权限的其他人无法阅读或理解机密信息;
  • 完整性意味着能够确保信息受到保护,以防止未经授权的更改,修改或删除。信息的完整性包括使用识别和认证等方法的起源,完整性和正确性;
  • 可用性意味着信息始终可供授权用户使用。

比如说,eMMC的Write protect(写保护)是为了保证数据的可用性。RPMB是为了保证数据的机密性完整性。eMMC关于安全特性的保护经历了:Password Lock -> Write Protect -> RPMB
1、Password Lock

Password lock was the first security feature integrated into the eMMC spec; previously it had been implemented in legacy SD cards. The password lock feature is designed to protect the contents of the user area from any type of access (read, write, or erase).

password lock&unlock机制使用CMD42命令来实现,如果设备lock住后,host只能做复位、初始化、选择和查询状态的动作,不能访问用户空间的任何数据。但是host可以访问boot分区、RPMB分区、GPA分区的信息。这个机制能保护数据不被破坏和访问,但是连同数据的所有者也不能访问。

2、Write Protect

Write protect was designed to protect against data corruption or erasure (whether malicious or unintentional). Once write protect is set, a host can’t erase or write to the specified protected area. However, unlike password lock, data can still be read from this area.

这个机制用来进行写保护


RPMB简介

RPMBReplay Protected Memory Block(重放保护内存块)的简称,是eMMC中的一个具有安全特性的分区。此功能使设备能够将数据存储在经过身份验证并防止重放攻击的小型特定区域(通常是4M Bytes)中。这里涉及一个概念Replay AttackReplay Protected
1、Replay Attack(重放攻击)
A向B请求服务(比如说登录某个网站),A将密码hash化传给B。但是在这中间,E抓取到该hash值。此后,E冒充A向B发送同样的hash值来获取服务。
图1

2、Replay Protected(重放保护)

  • 加随机数。该方法优点是认证双方不需要时间同步,双方记住使用过的随机数,如发现报文中有以前使用过的随机数,就认为是重放攻击。缺点是需要额外保存使用过的随机数,若记录的时间段较长,则保存和查询的开销较大。
  • 加时间戳。该方法优点是不用额外保存其他信息。缺点是认证双方需要准确的时间同步,同步越好,受攻击的可能性就越小。但当系统很庞大,跨越的区域较广时,要做到精确的时间同步并不是很容易。
  • 加流水号。就是双方在报文中添加一个逐步递增的整数,只要接收到一个不连续的流水号报文(太大或太小),就认定有重放威胁。该方法优点是不需要时间同步,保存的信息量比随机数方式小。缺点是一旦攻击者对报文解密成功,就可以获得流水号,从而每次将流水号递增欺骗认证端。
  • 一次性口令

RPMB认证

RPMB使用对称秘钥身份认证,也就是host和device使用相同的身份验证秘钥,此秘钥称之为认证秘钥(AuthKey)也可称为RPMB Key,工作方式如下:

  • AuthKey通过host写入到eMMC中(在安全的环境中写入)的OTP区域中;
  • host和device在读写RPMB区域的时候需要签名和验证;
  • 对消息进行签名涉及消息身份验证代码(Message Authentication Code)MAC,MAC是hash值,MAC是由通过AuthKey对Message + Write Counter使用HMAC SHA-256算法签名后得到。
  • 发送的消息为MAC + Message + Write Counter

HMAC是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
保护RPMB数据的关键就是保护AuthKey,因此在读写RPMB的时候,需要在TEE的环境中,因为在访问RPMB,需要显式的使用AuthKey(如果不在TEE环境中,可以对AuthKey进行加密,然后使用解密模块去操作)。
另外,AuthKey最好也是独一无二的,也就是与Soc UID相关的,形成自己独一无二的Key。


RPMB是怎么实现重放保护

重放保护最基本的就是要保证每个消息是独一无二的,RPMB分别加入2个因子进去:

  • 在写操作的时候,使用Write Counter(32Bytes)来实现重放保护。Write Counter是由Device管理的,该计数器在每次有效的验证写入消息后递增,其新值将包含在要发送的下一个身份验证代码MAC的计算中;
  • 在读操作的时候,使用随机数Nonce(16Bytes)来实现重放保护。Nonce是由Host产生。
    图2
    一个访问RPMB命令通过HMAC SHA-256计算进行验证,以下几项做为该计算的输入:
  • 身份验证的秘钥AuthKey
  • 消息,包括命令或返回的值;
  • 写计数器,也就是总的写RPMB的次数,存放计数器的值为32bit,当写入次数达到0xFFFFFFFF的时候,RPMB就变为只读;
  • 一个随机数,它是为每个read命令随机生成的数字(Read的时候才用到)。
    具体的RPMB命令格式如下:
    图3

从RPMB读数据

图4

1、在Host端,发送读请求以及一个16Bytes随机数Nonce给Device端;
2、在Device端(eMMC),将请求的数据从RPMB取出来,通过AuthKey对Data + 随机数使用HMAC SHA-256算法签名后得到MAC,与Data + 随机数一起发送给Host端;
3、在Host端收到Devcie发送过来的数据, 首先比较随机数是否与自己一致,如果一致,在Host端使用自己的AuthKey对接收到的Data + 随机数使用HMAC SHA-256算法签名后得到MAC1,比较自己生成的MAC1与接收到的MAC是否一致。
如果一致,Host端就可以确定该Data是从RPMB读取到的,没有被修改过,而不是攻击者伪造的数据。


写数据到RPMB

图5

在 Host Soc端:
1、Host端使用AuthKey对Message(Data + Metadata) + Write Counter 使用HMAC SHA-256算法签名后得到MAC;
2、Host端将MAC + Message + Write Counter传给Device。
这里有个疑问,既然Write Counter是由Device管理的,那么Host怎么拿到这个值呢?

图6

从上图可以明显的看出,Host端发送读Write Counter随机数给device端获取Write Counter,使用上面的读数据流程。

在Devices端(eMMC/UFS):
1、Device接受到Host传送过来的MAC + Message + Write Counter;
2、Device端比较接收到的Write Counter是否与自己的一致;
2、Devices将接受到的Message + Write Counter + devcies端的AuthKey 经过SHA-256生成MAC1;
3、将Devices端生成的MAC1与接收到的MAC进行比较,如果两者一致,就将Data写入到RPMB中;

在这个过程中,如果想要破解,Host端需要知道AuthKey和Write Counter。当然,Write Counter可以读取出来,所以最最重要的就是保护AuthKey。


使用mmc命令访问RPMB

使用mmc命令可以访问RPMB,查看访问RPMB相关的用法如下:

mmc的使用方法
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
mmc rpmb write-key <rpmb device> <key file>
Program authentication key which is 32 bytes length and stored
in the specified file. Also you can specify '-' instead of
key file path to read the key from stdin.
NOTE! This is a one-time programmable (unreversible) change.
Example:
$ echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH | \
mmc rpmb write-key /dev/mmcblk0rpmb -
mmc rpmb read-counter <rpmb device>
Counter value for the <rpmb device> will be read to stdout.
mmc rpmb read-block <rpmb device> <address> <blocks count> <output file> [key file]
Blocks of 256 bytes will be read from <rpmb device> to output
file or stdout if '-' is specified. If key is specified - read
data will be verified. Instead of regular path you can specify
'-' to read key from stdin.
Example:
$ echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH | \
mmc rpmb read-block /dev/mmcblk0rpmb 0x02 2 /tmp/block -
or read two blocks without verification
$ mmc rpmb read-block /dev/mmcblk0rpmb 0x02 2 /tmp/block
mmc rpmb write-block <rpmb device> <address> <256 byte data file> <key file>
Block of 256 bytes will be written from data file to
<rpmb device>. Also you can specify '-' instead of key
file path or data file to read the data from stdin.
Example:
$ (awk 'BEGIN {while (c++<256) printf "a"}' | \
echo -n AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH) | \
mmc rpmb write-block /dev/mmcblk0rpmb 0x02 - -

接下来我们要做如下几件事:
1、创建AuthKey和WrongAuthKey:

1
2
echo "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH" > AuthKey
echo "11112222333344445555666677778888" > WrongAuthKey

2、将AuthKey写入到eMMC的OTP中:

1
mmc rpmb write-key /dev/block/mmcblk0rpmb AuthKey

3、创建一个256Bytes的数据:

1
echo "123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef.123456789abcdef." > Data

之所以要创建256Bytes的数据,是因为mmc规定要写256Bytes:mmc rpmb write-block <rpmb device> <address> <256 byte data file> <key file>
4、用正确的AuthKey往RPMB写入数据:

1
mmc rpmb write-block /dev/block/mmcblk0rpmb 0 Data AuthKey

在这个步骤中,没有看到有读取Write Counter的动作,这是因为mmc命令已经在write-block中首先实现了读取Write Counter,详见mmc源码do_rpmb_write_block()函数,该函数会调用rpmb_read_counter()获取Write Counter
5、用错误的AuthKey往RPMB写入数据:

1
mmc rpmb write-block /dev/block/mmcblk0rpmb 0 Data WrongAuthKey

这时候会提示RPMB operation failed, retcode 0x0002的错误,表示验证失败。
6、不用AuthKey读取RPMB数据:

1
mmc rpmb read-block /dev/block/mmcblk0rpmb 0 1 out.txt

这个结果能读取到数据,但是并不能保证这个数据没有被修改过。
7、用正确的AuthKey读取RPMB数据:

1
mmc rpmb read-block /dev/block/mmcblk0rpmb 0 1 out1.txt AuthKey

这个结果能读取到数据,并且能保证这个数据没有被修改过,而不是攻击者伪造的数据。
8、用错误的AuthKey读取RPMB数据:

1
mmc rpmb read-block /dev/block/mmcblk0rpmb 0 1 out2.txt WrongAuthKey

提示RPMB MAC missmatch的错误,无法读取到数据。

上面所做的所有操作,必须在可信任的环境下执行,也就是TEE环境,保护AuthKey不被泄露。


RPMB的使用用例

1、软件版本认证,防止回滚攻击
比如说厂商发布更新软件版本的顺序为 Ver001 -> Ver002 -> Ver003 -> Ver004 -> Ver005 -> Ver006 -> ……
有一天厂商发现Ver006有个重大的漏洞,因此他们发布和升级了Ver007版本。
如果不做版本认证,黑客就有可能在Ver007的版本基础上回滚到Ver006,并使用Ver006的漏洞进行攻击。
那么如果将每次升级的软件版本号写入到RPMB中,只能往更高的版本升级。因为RPMB写操作需要key,所以黑客不容易修改RPMB中的版本号来实现回滚。

2、手机开锁认证
通常,PIN码、图像、指纹可以给设备解锁,Android称之为GateKeeper,它够安全地限制对用户凭据进行暴力破解的尝试次数。其实现失败计数器,然后再验证用户密码。如果密码验证成功,则应清除失败计数器。
失败计数器写入到RPMB中,可以防止黑客无限制次数的攻击。


RPMB总结

1、由于RPMB的读操作没有AuthKey也能返回的,因此,存入RPMB的数据最好是经过加密的;
2、RPMB的操作最好在TEE环境下,这样可以保证AuthKey不被泄露;


参考资料

white-paper-emmc-security
Replay_attack
eMMC总线协议
mmc用法
How to access Replay Protected Memory Block (RPMB) in eMMC?
JESD84-B50.1
mmc-util
GateKeeper

Title:RPMB介绍与使用

Author:Victor Huang

Time:2019-06-09 / 18:06

Link:http://wowothink.com/8ca78fd8/

License: Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)