RPMB 简介

信息安全

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

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

RPMB简介

RPMB是Replay Protected Memory Block(重放保护内存块)的简称,是eMMC中的一个具有安全特性的分区。此功能使设备能够将数据存储在经过身份验证并防止重放攻击的小型特定区域(通常是4M Bytes)中。这里涉及一个概念Replay Attack和Replay Protected。

Replay Attack(重放攻击)

A向B请求服务(比如说登录某个网站),A将密码hash化传给B。但是在这中间,E抓取到该hash值。此后,E冒充A向B发送同样的hash值来获取服务。

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产生。

一个访问RPMB命令通过HMAC SHA-256计算进行验证,以下几项做为该计算的输入:

  • 身份验证的秘钥AuthKey;
  • 消息,包括命令或返回的值;
  • 写计数器,也就是总的写RPMB的次数,存放计数器的值为32bit,当写入次数达到0xFFFFFFFF的时候,RPMB就变为只读;
  • 一个随机数,它是为每个read命令随机生成的数字(Read的时候才用到)。 具体的RPMB命令格式如下:

从RPMB读数据

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

写数据到RPMB

在 Host Soc端:

  • Host端使用AuthKey对Message(Data + Metadata) + Write Counter 使用HMAC SHA-256算法签名后得到MAC
  • Host端将MAC + Message + Write Counter传给Device

在Devices端(eMMC/UFS):

  • Device接受到Host传送过来的MAC + Message + Write Counter
  • Device端比较接收到的Write Counter是否与自己的一致
  • Devices将接受到的Message + Write Counter + devcies端的AuthKey 经过SHA-256生成MAC1
  • 将Devices端生成的MAC1与接收到的MAC进行比较,如果两者一致,就将Data写入到RPMB中

通过上述的写入流程,可以保证 RPMB 不会被非法篡改。

使用mmc命令访问RPMB

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

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 - -

  • 创建AuthKey和WrongAuthKey

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

  • 将AuthKey写入到eMMC的OTP中

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

  • 创建一个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

    <256 byte data file>

  • 用正确的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。

  • 用错误的AuthKey往RPMB写入数据

    1
    mmc rpmb write-block /dev/block/mmcblk0rpmb 0 Data WrongAuthKey
    这时候会提示RPMB operation failed, retcode 0x0002的错误,表示验证失败。

  • 不用AuthKey读取RPMB数据

    1
    mmc rpmb read-block /dev/block/mmcblk0rpmb 0 1 out.txt
    这个结果能读取到数据,但是并不能保证这个数据没有被修改过。

  • 用正确的AuthKey读取RPMB数据

    1
    mmc rpmb read-block /dev/block/mmcblk0rpmb 0 1 out1.txt AuthKey
    这个结果能读取到数据,并且能保证这个数据没有被修改过,而不是攻击者伪造的数据。

  • 用错误的AuthKey读取RPMB数据

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

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

参考文献

https://wowothink.com/8ca78fd8/
https://blog.csdn.net/qq_35675731/article/details/101017841