6.11. JTAG 解锁

在安全方案中,芯片使能安全启动之后,可通过 eFuse 关闭 JTAG, 防止攻击者通过 JTAG 控制芯片和窃取芯片中的敏感信息。然而在实际应用中可能会遇到一些需要使用 JTAG 调试的场景,即需要将关闭的 JTAG 重新打开。

JTAG 安全解锁的作用是提供一种安全的方法,在不影响芯片的安全等级的情况下, 让合法的用户可以重新打开芯片的 JTAG 接口。

6.11.1. JTAG 关闭和打开

在芯片内部,JTAG 调试模块与外部调试器的通信由几个主要信号连接实现。

../../_images/jtag_signal.png

图 6.12 JTAG 信号

这里的 JTAG 信号是:

  1. TMS

  2. TRST

  3. TDI

  4. TDO

将其中的 TDO 关闭,可以实现关闭外部调试器的 JTAG 调试功能。本芯片通过烧录 eFuse 的安全配置区域 JTAG_DIS 位进行关闭。

../../_images/jtag_tdo_signal.png

图 6.13 关闭 TDO 信号

要重新打开 JTAG,可通过另外一个来自寄存器的设置信号来重新使能 TDO 信号。具体如下图所示。

../../_images/jtag_tdo_enable.png

图 6.14 重新打开 TDO 信号

当JTAG_UNLOCK被设置为1时,不管 eFuse 中的 JTAG DIS 被设置为什么值,都会保证 TDO 有效。

6.11.2. 开关的安全性

eFuse JTAG DIS 被设置为1之后,JTAG 立刻关闭。由于 eFuse 比特无法被重新设置为0, 因此 JTAG_DIS 信号一直生效,每次重新上电,JTAG 总是默认关闭。

重新打开 JTAG 由 JTAG_UNLOCK 信号控制,该信号由 SID 模块的 JTAG_UNLOCK 寄存器比特位控制, 因此重新打开 JTAG 的安全性,取决于 JTAG_UNLOCK 比特位的安全性。

JTAG_UNLOCK 比特位具有一个特性:该比特位设置为1时,解锁 JTAG,但是仅有 SID 模块寄存器中的 BROM_PRIV_LOCK 为0时,JTAG_UNLOCK 才会有效。如果BROM_PRIV_LOCK为1,则 JTAG_UNLOCK位设置为1, 也无法解锁 JTAG。

BROM_PRIV_LOCK 有一个特点,一旦被设置为1,就无法清零,只有系统复位才可以清零。 在系统复位时,BROM 会被运行。BROM 跳出之前,会主动设置BROM_PRIV_LOCK=1。 即保证只有 BROM 程序可以设置 BROM_PRIV_LOCK和 JTAG_UNLOCK位。

通过上述的配置,将重新打开 JTAG 的权力放在 BROM 之中。BROM 在升级模式下,通过 USB 命令的方式, 对外部的解锁 JTAG 命令进行安全性校验,校验通过,则设置 JTAG_UNLOCK 对 JTAG 进行解锁。

在安全启动使能的情况下,BROM :

  1. 不能通过 USB READ/WRITE 命令对寄存器进行读写

  2. 所有BROM执行的程序,都需要经过安全校验(包括 PBP 程序,如果使能了安全启动,PBP 必须是加密的)

  3. BROM 在跳转任何其他程序之前,必须先设置 BROM_PRIV_LOCK 特权位

通过上述措施,保证在 BROM 阶段,JTAG 无法被其他程序打开。

6.11.3. 解锁的安全验证

在 BROM USB 升级模式下,可通过 USB 命令,让 BROM 执行 JTAG 解锁。具体流程如下:

  1. 通过 USB 命令,读取芯片中的 CHIP DATA(包含了 CHIP ID 等信息),保存为二进制文件

  2. 主机端需要使用RSA 私钥,对读取到的 CHIP DATA二进制文件进行签名,生成签名后的 JTAG 解锁文件(具体格式参考后面的描述)

  3. 通过 USB JTAG_UNLOCK 命令,发送 JTAG 解锁文件给 BROM

  4. BROM 验证通过后,执行 JTAG 解锁

输入的解锁文件格式:

../../_images/jtag_unlock_msg_format.png

图 6.15 解锁消息格式