Edit online

功能描述

15 Aug 2024
Read time: 2 minute(s)
SPI 数据加密使用 AES-128-CTR 算法,加解密总体计算过程如下:
  1. 以 16 字节为单位对数据进行分组,并且为每个数据分组产生对应的 Counter 值。

    关于详细的计算详细流程,可查看 计算分组密钥

  2. 使用一个 128-bit AES 密钥,对 Counter 值进行加密运算,产生数据分组的对应分组密钥。

    产生数据分组对应的 Counter 值,需要使用一个 Nonce,在 SPI ENC 使用过程中,Nonce 作为密钥数据的一部分提供。

  3. 使用分组密钥与数据进行异或运算,得到密文。

    关于如何输出分组密钥的流程,可查看 输出分组密钥

    关于异或运算的详细描述,可查看 数据加解密

密钥数据的来源有两个:
  • SPI 加密模块从 eFuse 中读取 AES KEY 和 Nonce。eFuse 中保存的密钥数据如下:
    名称 长度 说明
    SPI_ENC_KEY 128 bits 加密密钥,仅 SPI_ENC 模块可见。
    SPI_ENC_NONCE 64 bits 生成 Counter,仅 SPI_ENC 模块可见。
  • 用户通过相应的寄存器配置 AES KEY 和 Nonce,主要用于内部调试。

计算分组密钥


aes-128-ctr-alg

1. AES-128-CTR 算法原理
AES-128-CTR 算法原理中,使用 AES-128-CTR 进行加密或者解密的过程分为三个步骤:
  1. 生成数据分组的 Counter 值。

    Counter 值的产生方式如下:
    ID = (SPIE_ADDR & 0xFFFFFFF0) / 16
    Counter(ID) = (Nonce << 64) +(SPIE_TWEAK << 32) +  ID
  2. 生成分组密钥。

    1. 使用数据地址寄存器 SPIE_ADDR 中的地址值,计算分组 ID。
    2. 分组 ID 与 Nonce 和 Tweak 值组成 Counter 值。
    3. 使用 AES-128-ECB 加密算法,用 AES KEY 对 Counter 值进行加密,得到分组密钥。

      SPI ENC 一次可产生 16 字节的分组密钥,输出到内部 Key buffer。

      模块开始工作后,只要 Key buffer 有空间,计算分组密钥就会继续,并且总是按地址顺序自动计算下一组密钥,直到控制寄存器 SPIE_CTL[0] 被设置为 0。

    注:AES-128-CTR 算法原理所示,数据的加密和解密的分组密钥计算流程完全一致。
  3. 使用分组密钥对数据进行异或运算,产生加密数据。详细流程可查看 输出分组密钥

输出分组密钥

SPI ENC 模块仅计算 AES-128-CTR 的分组密钥,最后一步使用分组密钥对数据进行异或运算由 SPI 控制器完成。因此在启用 SPI ENC 的情况下,SPI 控制器需要为发送到总线或者从总线接收到的每一字节数据读取分组密钥。



2. SPI 数据传输模式

SPI 数据传输模式所示,在与 SPI NOR/ NAND 通信过程中,传输的数据可能出现明文和密文混合传输的情形。

SPI ENC 输出分组密钥的规则如下:
  • SPI 控制器每收发一个字节数据,都要读取一个字节的分组密钥
  • 明文数据位置对应的分组密钥,总是读取到 0;
  • 密文数据位置对应的分组密钥,总是计算得到的分组密钥;

分组密钥的计算总是以 16 字节为单位,但用户访问的地址可能并不是 16 字节对齐,如从 0x0000_0005 地址开始读取数据。 这种情况下,SPI ENC 计算的第一个分组密钥仍然为 16 字节,只是对应的数据地址为 0x0000_0000 ~ 0x0000_000F;SPI ENC 输出数据分组密钥时,应输出 0x05~0x0F 数据对应的分组密钥值。

注: SPI ENC 模块要准确的计算和输出分组密钥,依赖于用户开始传输前配置的数据地址、长度、加密数据的起始地址和长度等信息。

数据加解密

使用分组密钥与对应的数据分组进行异或运算,即可完成数据的加密或者解密。
注: 由于 SPI ENC 输出的密钥,只能应用于接收的数据,或者发送的数据,不可以同时应用于两组数据,因此使能 SPI ENC 时,不支持 SPI 全双工模式,
  • 对于发送数据,数据会先被写入 TXFIFO,SPI 控制器在将数据发送到 SPI 总线上之前执行:
    1. 读取一个字节的分组密钥数据。
    2. 将分组密钥数据与要发送的一个字节数据进行异或运算。
    3. 将结果发送到 SPI 总线。
  • 对于接收数据:
    1. 从 SPI 总线读取到一个字节数据的同时,读取一个字节的分组密钥。
    2. 将分组密钥数据与接收的数据进行异或运算。
    3. 将解密后的数据,写入 RXFIFO。