Rockchip SoCs: foray into eFuse territory

Every System-on-Chip has a boot ROM taking care of finding the next component in the boot process, load and run it. Each different vendor tends to implement a different strategy for their boot ROM, often with similar capabilities.

We have written about the Rockchip SoCs boot ROM before on this blog, for instance to discuss their recovery boot capability and the related tooling.

This time, we’re going to look into a particular piece of memory on the SoC, that is very important to the security of the SoC: the secure eFuse.

Write-once memory & secure boot

Write-once memory banks are used in modern SoCs to allow storing data that can not be modified afterwards.

One very common use for this is to store the hash of the secure boot root key: the public key that will be used to verify the signature on the first part of the bootchain. For more details about this root key and its role in secure boot implementations, please see the materials for our security training.

Write-once memory technologies

Different hardware technologies exist to provide this write-once mechanism.  Both rely on applying a current with higher-than-normal intensity to change the conductivity of the gates of the transistors that make up the memory cells.

Because the change in conductivity is based on a permanent alteration of the hardware, by changing the electrochemical structure of the material, the changed bits cannot be changed again.

The difference between technologies lies in the direction in which that conductivity is changed, which results in two possibilities:

  • One-time programmable (OTP) memory: This term usually designates memory banks based on anti-fuses: we go from an open path (non-conductive) to a closed one (conductive). That is the opposite of what a traditional electrical fuse is intended to do: break open the circuit when encountering a surge of power, hence the name.
  • Electronic fuse (eFuse): This technology uses the normal principle of a fuse. Once blown, current no longer flows through. The principle used here is usually electromigration of the conductive material under the high-power current, leading to a breakdown of the material.

Both of those technologies can be used to change a transistor to be permanently either open or closed, and change the value of the associated memory cell.

Rockchip’s write-once memories

Rockchip SoCs usually embed at least one write-once memory bank. Which technology they use depends on the model of the SoC:

  • the RK35XX series and the RK3308 for example all include OTP memory, split into 2 regions, as shown in Table 1-1 of  Part 1 of the TRM: OTP_S (secure), 64 KiB mapped at 0xfe3a0000, and OTP_NS, 64 KiB mapped at 0xfecc0000
  • the RK3399 embeds two eFuse banks: the secure and non-secure one, which are the topic of this blog post.

The RK3399 eFuses

The RK3399’s 2 eFuse banks are described in the RK3399 Technical Reference Manual, part 1, section 1.1:

  • the non-secure eFuse (EFUSE0) is mapped at 0xff690000
  • the secure eFuse (EFUSE1) is mapped at 0xfffa0000

The RK3399 non-secure eFuse

The non-secure eFuse can be used to store non-sensitive information, such as the CPU ID, or info about the wafer. Rockchip implemented the driver for the non-secure eFuse, and upstreamed it in version 4.3 of the Linux kernel. It is accessible from a running Linux system, exposed as an nvmem device:

$ sudo insmod nvmem_rockchip_efuse.ko
$ ls /sys/bus/nvmem/devices/rockchip-efuse0/cells/
center-leakage@19,0 cpu-leakage@17,0
gpu-leakage@18,0 wafer-info@1c,0
cpu-id@7,0 cpu-leakage@1a,0 logic-leakage@1b,0
$ hexdump /sys/bus/nvmem/devices/rockchip-efuse0/nvmem
0000000 4b52 9933 fe91 5421 4141 3950 2e36 3030
0000010 0000 0000 9003 2201 2019 1713 0008 0000
0000020 0000 0010 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 0000 0000 0000 0000
*
0000080

This driver is detecting the non-secure eFuse from the RK3399 device tree, which includes its address, 0xff690000.

The RK3399 secure eFuse

Seeing that the driver for the non-secure eFuse works, one could be tempted to load a modified .dtbfile, with this description pointing instead to the secure eFuse’s address, 0xfffa0000. Unfortunately, this is the result:

$ sudo insmod nvmem_rockchip_efuse.ko
$ hexdump /sys/bus/nvmem/devices/rockchip-efuse0/nvmem 
[   60.897618] SError Interrupt on CPU0, code 0x00000000bf000000 -- SError
[   60.897644] CPU: 0 PID: 2230 Comm: hexdump Tainted: G            E      6.9.0-okpine #15
[   60.897655] Hardware name: Pine64 PinePhone Pro (DT)
[   60.897659] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[   60.897668] pc : __const_udelay+0x10/0x38
[   60.897684] lr : rockchip_rk3399_efuse_read+0x94/0x218 [nvmem_rockchip_efuse]
[...]
[   60.897822] Kernel panic - not syncing: Asynchronous SError Interrupt
[   60.897827] CPU: 0 PID: 2230 Comm: hexdump Tainted: G            E      6.9.0-okpine #15
[   60.897835] Hardware name: Pine64 PinePhone Pro (DT)
[   60.897840] Call trace:
[   60.897844]  dump_backtrace+0xa8/0x110
[   60.897855]  show_stack+0x1c/0x30
[   60.897863]  dump_stack_lvl+0x34/0x88
[   60.897874]  dump_stack+0x14/0x20
[   60.897883]  panic+0x380/0x398
[   60.897895]  nmi_panic+0x60/0x80
[   60.897904]  arm64_serror_panic+0x74/0x90
[   60.897913]  do_serror+0x40/0x80
[   60.897920]  el1h_64_error_handler+0x30/0x48
[   60.897934]  el1h_64_error+0x68/0x70
[   60.897942]  __const_udelay+0x10/0x38
[   60.897950]  rockchip_rk3399_efuse_read+0x94/0x218 [nvmem_rockchip_efuse]
[   60.897965]  nvmem_reg_read+0x28/0x50

Instead of reading the secure eFuse we got a kernel oops! As the oops message states, the kernel gets killed by an SError. One reason for it, given by the ARM documentation, is:

Memory access which has passed all the MMU checks but then encounters an error on the memory bus

The question therefore becomes: what is this error on the memory bus?

The secure eFuse is described in section 2 of the Secure Boot Application Note:

  • the first 32-bit word holds the security enable flag bits in its first 8 bits
  • the next 15 words are reserved
  • the following 8 words hold the 256-bit SHA256 hash of the RSA public key
  • the next 7 words are, again, reserved
  • the last 32-bit word holds the eFuse write lock bits

Chapter 21 of the TRM adds some information, and mentions that the secure eFuse (EFUSE1) can only be accessed in “secure mode”, which most likely refers to ARM Trustzone’s Secure World. Let’s try and confirm this.

Secure memory isolation on Rockchip SoCs

The question we’re going to try and answer in this section is: “Can we confirm that the RK3399 is configured to only allow accesses to the secure eFuse from Secure World, and can we change that?”.

To answer this question, we need to look at Chapter 16 of version 1.3 of the TRM: “System security”.
Section 16.3.4 shows that APB slaves can be in one of 4 secure types:

  • secure: accessible only from secure world
  • non-secure: accessible from both secure and non-secure worlds
  • boot-secure: accessible only from secure world at boot, and can be configured in software for late accesses
  • per configure: the device can be configured to be in either the secure or non-secure secure type above, based on the Secure General Register File (sGRF)

Table 16-4 in section 16.3.6 RK3399 secure slave setting shows that, while EFUSE0 is of secure type “per configure”, and most likely configured to be in “non-secure” by default, efuse1 is of secure type “secure”, so there is no way to configure it for access from non-secure world.

While the root key is part of the secure boot implementation, the information stored in the secure eFuse is the SHA256 hash of the public key, so its integrity should be protected, not its confidentiality.
It is therefore unclear why Rockchip chose to make this eFuse bank only accessible from secure World, but we can confirm that this is a deliberate choice they made.

Conclusion

As we have seen, some Rockchip SoCs embed eFuses to store non-volatile information that can not be modified once it’s been written.

A typical use of this memory area is to store the hash of the secure boot public key. That hash is expected to be written to a secure eFuse, which is an APB slave marked for secure access only (meaning only from TrustZone’s secure world) and cannot be reconfigured to allow access from outside of it.

In a further blog post, we’ll explore how to access this secure eFuse, e.g. to retrieve the hash of the secure boot public key.

Leave a Reply