Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: OP-TEE/optee_os
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4d2ba219355d46ffe20f21c22b6fb8328a4fbf51
Choose a base ref
..
head repository: OP-TEE/optee_os
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5baa554be1d3a40f8f09eeefc78c0b1c3c366419
Choose a head ref
Showing with 62 additions and 50 deletions.
  1. +62 −50 core/arch/arm/plat-rockchip/platform_rk3588.c
112 changes: 62 additions & 50 deletions core/arch/arm/plat-rockchip/platform_rk3588.c
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@
#include <platform_config.h>
#include <rng_support.h>
#include <string.h>
#include <string_ext.h>
#include <utee_defines.h>

#define FIREWALL_DDR_RGN(i) ((i) * 0x4)
#define FIREWALL_DDR_CON 0xf0
@@ -72,8 +74,7 @@
#define OTP_POLL_PERIOD_US 0
#define OTP_POLL_TIMEOUT_US 1000

#define HW_UNIQUE_KEY_INDEX 0x100
#define HW_UNIQUE_KEY_SIZE 16
#define HW_UNIQUE_KEY_INDEX 0x104

register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE);
register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DSU_BASE, FIREWALL_DSU_SIZE);
@@ -192,27 +193,30 @@ TEE_Result hw_get_random_bytes(void *buf, size_t blen)
return TEE_SUCCESS;
}

static TEE_Result tee_otp_read_secure(uint32_t *pValue, uint32_t index,
static TEE_Result tee_otp_read_secure(uint32_t *value, uint32_t index,
uint32_t count)
{
vaddr_t base = (vaddr_t)phys_to_virt(OTP_S_BASE, MEM_AREA_IO_SEC,
OTP_S_SIZE);
uint32_t int_status = 0;
uint32_t i = 0;
uint32_t val = 0;

/* Setup read: index, count, command = READ */
uint32_t auto_ctrl_val = (index << ADDR_SHIFT) |
(count << BURST_SHIFT) |
CMD_READ;
uint32_t auto_ctrl_val = 0;
TEE_Result res = TEE_SUCCESS;

if (!base)
panic("OTP_S base not mapped");

/* Check for invalid parameters or exceeding hardware burst limit */
if (!pValue || !count || count > BURST_SIZE)
if (!value || !count || count > BURST_SIZE ||
(index + count > MAX_INDEX))
return TEE_ERROR_BAD_PARAMETERS;

/* Setup read: index, count, command = READ */
auto_ctrl_val = SHIFT_U32(index, ADDR_SHIFT) |
SHIFT_U32(count, BURST_SHIFT) |
CMD_READ;

/* Clear any pending interrupts by reading & writing back INT_ST */
io_write32(base + OTP_S_INT_ST,
io_read32(base + OTP_S_INT_ST));
@@ -223,60 +227,72 @@ static TEE_Result tee_otp_read_secure(uint32_t *pValue, uint32_t index,
/* Enable read */
io_write32(base + OTP_S_AUTO_EN, EN_ENABLE);

/* Wait for RD_DONE bit using IO_READ32_POLL_TIMEOUT */
if (IO_READ32_POLL_TIMEOUT(base + OTP_S_INT_ST,
int_status,
int_status & OTP_S_RD_DONE_BIT,
OTP_POLL_PERIOD_US,
OTP_POLL_TIMEOUT_US)) {
return TEE_ERROR_BUSY;
}
/* Wait for RD_DONE or ERROR bits */
res = IO_READ32_POLL_TIMEOUT(base + OTP_S_INT_ST,
int_status,
(int_status & OTP_S_RD_DONE_BIT) ||
(int_status & OTP_S_ERROR_BIT),
OTP_POLL_PERIOD_US,
OTP_POLL_TIMEOUT_US);

/* Clear the interrupt again */
io_write32(base + OTP_S_INT_ST,
io_read32(base + OTP_S_INT_ST));

if (int_status & OTP_S_ERROR_BIT) {
EMSG("OTP_S Error");
return TEE_ERROR_GENERIC;
}
if (res) {
EMSG("OTP_S Timeout");
return TEE_ERROR_BUSY;
}

/* Read out the data */
for (i = 0; i < count; i++) {
val = io_read32(base + OTP_S_DOUT +
(i * sizeof(uint32_t)));
pValue[i] = val;
value[i] = val;
}

return TEE_SUCCESS;
}

static TEE_Result tee_otp_write_secure(const uint32_t *pValue, uint32_t index,
static TEE_Result tee_otp_write_secure(const uint32_t *value, uint32_t index,
uint32_t count)
{
vaddr_t base = (vaddr_t)phys_to_virt(OTP_S_BASE, MEM_AREA_IO_SEC,
OTP_S_SIZE);
uint32_t int_status = 0;
uint32_t i = 0;

if (!base)
panic("OTP_S base not mapped");

/* Check for invalid parameters or exceeding hardware limits */
if (!pValue || !count || count > BURST_SIZE ||
if (!value || !count || count > BURST_SIZE ||
(index + count > MAX_INDEX))
return TEE_ERROR_BAD_PARAMETERS;

/* Program OTP words */
for (uint32_t i = 0; i < count; i++) {
uint32_t old_val, new_val = 0;
for (i = 0; i < count; i++) {
uint32_t old_val = 0;
uint32_t new_val = 0;
uint32_t curr_idx = index + i;
TEE_Result res = 0;
TEE_Result res = TEE_SUCCESS;

/* Setup write: curr_idx, command = WRITE */
uint32_t auto_ctrl_val = (curr_idx << ADDR_SHIFT) | CMD_WRITE;
uint32_t auto_ctrl_val = SHIFT_U32(curr_idx, ADDR_SHIFT) |
CMD_WRITE;

/* Read existing OTP word to see which bits can be set */
res = tee_otp_read_secure(&old_val, curr_idx, OTP_WORD);
if (res != TEE_SUCCESS)
return res;

/* Only program bits that are currently 0 (0->1) */
new_val = *pValue++ & ~old_val;
new_val = *value & ~old_val;
value++;
if (!new_val)
continue;

@@ -302,6 +318,9 @@ static TEE_Result tee_otp_write_secure(const uint32_t *pValue, uint32_t index,
OTP_POLL_PERIOD_US,
OTP_POLL_TIMEOUT_US);

/* Clear INT status bits */
io_write32(base + OTP_S_INT_ST, int_status);

/* Check for VERIFY_FAIL, ERROR or timeout */
if (int_status & OTP_S_VERIFY_BIT) {
EMSG("OTP_S Verification fail");
@@ -315,9 +334,6 @@ static TEE_Result tee_otp_write_secure(const uint32_t *pValue, uint32_t index,
EMSG("OTP_S Timeout");
return TEE_ERROR_BUSY;
}

/* Clear INT status bits */
io_write32(base + OTP_S_INT_ST, int_status);
}

return TEE_SUCCESS;
@@ -326,60 +342,56 @@ static TEE_Result tee_otp_write_secure(const uint32_t *pValue, uint32_t index,
TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
{
TEE_Result res = 0;
uint32_t buffer[HW_UNIQUE_KEY_SIZE / sizeof(uint32_t)];
uint32_t buffer[HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t)] = {0};
bool key_is_empty = true;
size_t i = 0;

if (!hwkey)
return TEE_ERROR_BAD_PARAMETERS;

mutex_lock(&huk_mutex);

/* Read 4 words (16 bytes) from OTP at HW_UNIQUE_KEY_INDEX */
memset(buffer, 0, sizeof(buffer));
res = tee_otp_read_secure(buffer, HW_UNIQUE_KEY_INDEX,
HW_UNIQUE_KEY_SIZE / sizeof(uint32_t));
if (res != TEE_SUCCESS) {
res = tee_otp_read_secure(buffer,
HW_UNIQUE_KEY_INDEX,
HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t));
if (res) {
mutex_unlock(&huk_mutex);
return res;
}

/* Check if the buffer is all zero => HUK not present */
for (size_t i = 0; i < ARRAY_SIZE(buffer); i++) {
for (i = 0; i < ARRAY_SIZE(buffer); i++) {
if (buffer[i] != 0) {
key_is_empty = false;
break;
}
}

if (key_is_empty) {
/* HUK is empty => generate random key and program it */
uint8_t rand_bytes[HW_UNIQUE_KEY_SIZE];
uint32_t words[HW_UNIQUE_KEY_SIZE / sizeof(uint32_t)];

/* Generate random 128-bit key from TRNG */
res = hw_get_random_bytes(rand_bytes, sizeof(rand_bytes));
if (res != TEE_SUCCESS) {
res = hw_get_random_bytes(buffer, sizeof(buffer));
if (res) {
mutex_unlock(&huk_mutex);
return res;
}

/* Convert random bytes -> 32-bit words */
memcpy(words, rand_bytes, sizeof(words));

/* Write the new HUK into OTP at HW_UNIQUE_KEY_INDEX */
res = tee_otp_write_secure(words, HW_UNIQUE_KEY_INDEX,
ARRAY_SIZE(words));
if (res != TEE_SUCCESS) {
res = tee_otp_write_secure(buffer,
HW_UNIQUE_KEY_INDEX,
HW_UNIQUE_KEY_LENGTH /
sizeof(uint32_t));
if (res) {
mutex_unlock(&huk_mutex);
return res;
}

/* Update buffer with the newly generated words */
memcpy(buffer, words, sizeof(buffer));
}

/* Copy HUK into hwkey->data */
memcpy(hwkey->data, buffer, HW_UNIQUE_KEY_SIZE);
memcpy(hwkey->data, buffer, HW_UNIQUE_KEY_LENGTH);

/* Clear buffer memory */
memzero_explicit(buffer, sizeof(buffer));

mutex_unlock(&huk_mutex);