DRA821U: DRA821 key revoke feature in u-boot

Part Number: DRA821U
Other Parts Discussed in Thread: DRA821

Tool/software:

Dear champ, 

My customer had developed Key Revoke feature in u-boot by working with Sitara AE Hong Guan. 

Now we need some help for same implementation on DRA821 since TISCI in SYSFW is different from DRA821 to AM64x and AM62x. 

OPTEE is required for the implementation. 

Attached files are the modifications were created for Sitara part. 

// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ 
 *	Andrew F. Davis <afd@ti.com>
 */

#include <console.h>
#include <drivers/gic.h>
#include <drivers/sec_proxy.h>
#include <drivers/serial8250_uart.h>
#include <drivers/ti_sci.h>
#include <kernel/boot.h>
#include <kernel/panic.h>
#include <kernel/tee_common_otp.h>
#include <mm/core_memprot.h>
#include <mm/tee_pager.h>
#include <platform_config.h>
#include <stdint.h>
#include <string_ext.h>
#include "dual_cert_keyrev.h"

static struct serial8250_uart_data console_data;

register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GICC_SIZE);
register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GICD_SIZE);
register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE,
		  SERIAL8250_UART_REG_SIZE);
register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_DATA_BASE,
			SEC_PROXY_DATA_SIZE);
register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_SCFG_BASE,
			SEC_PROXY_SCFG_SIZE);
register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE);
register_ddr(DRAM0_BASE, DRAM0_SIZE);
register_ddr(DRAM1_BASE, DRAM1_SIZE);

void primary_init_intc(void)
{
	gic_init(GICC_BASE, GICD_BASE);
}

void main_secondary_init_intc(void)
{
	gic_cpu_init();
}

void console_init(void)
{
	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
	register_serial_console(&console_data.chip);
}

static TEE_Result init_ti_sci(void)
{
	TEE_Result ret = TEE_SUCCESS;

	ret = k3_sec_proxy_init();
	if (ret != TEE_SUCCESS)
		return ret;

	ret = ti_sci_init();
	if (ret)
		return TEE_ERROR_GENERIC;

	return TEE_SUCCESS;
}

service_init(init_ti_sci);

static TEE_Result secure_boot_information(void)
{
	uint32_t keycnt = 0;
	uint32_t keyrev = 0;
	uint32_t swrev = 0;
	const uint8_t gKeyCert[KEYCERT_SIZE_IN_BYTES] __attribute__((aligned(128))) = KEYCERT;

	if (!ti_sci_get_swrev(&swrev))
		IMSG("Secure Board Configuration Software: Rev %"PRIu32,
		     swrev);

	if (!ti_sci_get_keycnt_keyrev(&keycnt, &keyrev))
		IMSG("Secure Boot Keys: Count %"PRIu32 ", Rev %"PRIu32,
		     keycnt, keyrev);

	/* unit test for ti_sci_set_keyrev() */
	IMSG(">>>> ti_sci_set_keyrev() unit test start");
	if (!ti_sci_set_keyrev(&gKeyCert[0], KEYCERT_SIZE_IN_BYTES))
		IMSG(">>>> ti_sci_set_keyrev() return success!!!");

	return TEE_SUCCESS;
}

service_init_late(secure_boot_information);

TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
{
	uint8_t dkek[SA2UL_DKEK_KEY_LEN] = { };
	int ret = 0;

	assert(SA2UL_DKEK_KEY_LEN >= HW_UNIQUE_KEY_LENGTH);

	ret = ti_sci_get_dkek(0, "OP-TEE", "DKEK", dkek);
	if (ret) {
		EMSG("Could not get HUK");
		return TEE_ERROR_SECURITY;
	}

	memcpy(&hwkey->data[0], dkek, sizeof(hwkey->data));
	memzero_explicit(&dkek, sizeof(dkek));

	IMSG("HUK Initialized");

	return TEE_SUCCESS;
}
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Texas Instruments System Control Interface Driver
 *   Based on TF-A implementation
 *
 * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ 
 *	Manorit Chawdhry <m-chawdhry@ti.com>
 */

#include <assert.h>
#include <malloc.h>
#include <platform_config.h>
#include <string.h>
#include <string_ext.h>
#include <tee_api_defines.h>
#include <trace.h>

#include "sec_proxy.h"
#include "ti_sci.h"
#include "ti_sci_protocol.h"
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
#include "dual_cert_keyrev.h"

static uint8_t message_sequence;

/**
 * struct ti_sci_xfer - Structure representing a message flow
 * @tx_message:	Transmit message
 * @rx_message:	Receive message
 */
struct ti_sci_xfer {
	struct k3_sec_proxy_msg tx_message;
	struct k3_sec_proxy_msg rx_message;
};

#define SRAM_SCRATCH_BASE 	0x43C3B000
#define SRAM_SCRATCH_SIZE 	0x4000
register_phys_mem_pgdir(MEM_AREA_IO_SEC, SRAM_SCRATCH_BASE, SRAM_SCRATCH_SIZE);

/**
 * ti_sci_setup_xfer() - Setup message transfer
 *
 * @msg_type:	Message type
 * @msg_flags:	Flag to set for the message
 * @tx_buf:	Buffer to be sent to mailbox channel
 * @tx_message_size: transmit message size
 * @rx_buf:	Buffer to be received from mailbox channel
 * @rx_message_size: receive message size
 * @xfer:	Transfer message
 *
 * Helper function which is used by various command functions that are
 * exposed to clients of this driver for allocating a message traffic event.
 *
 * Return: 0 if all goes well, else appropriate error message
 */
static int ti_sci_setup_xfer(uint16_t msg_type, uint32_t msg_flags,
			     void *tx_buf,
			     size_t tx_message_size,
			     void *rx_buf,
			     size_t rx_message_size,
			     struct ti_sci_xfer *xfer)
{
	struct ti_sci_msg_hdr *hdr = NULL;

	/* Ensure we have sane transfer sizes */
	if (rx_message_size > SEC_PROXY_MAX_MSG_SIZE ||
	    tx_message_size > SEC_PROXY_MAX_MSG_SIZE ||
	    rx_message_size < sizeof(*hdr) ||
	    tx_message_size < sizeof(*hdr)) {
		EMSG("Message transfer size not sane");
		return TEE_ERROR_SHORT_BUFFER;
	}

	hdr = (struct ti_sci_msg_hdr *)tx_buf;
	hdr->seq = ++message_sequence;
	hdr->type = msg_type;
	hdr->host = OPTEE_HOST_ID;
	hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;

	xfer->tx_message.buf = tx_buf;
	xfer->tx_message.len = tx_message_size;

	xfer->rx_message.buf = rx_buf;
	xfer->rx_message.len = rx_message_size;

	return 0;
}

/**
 * ti_sci_get_response() - Receive response from mailbox channel
 *
 * @xfer:	Transfer to initiate and wait for response
 *
 * Return: 0 if all goes well, else appropriate error message
 */
static inline int ti_sci_get_response(struct ti_sci_xfer *xfer)
{
	struct k3_sec_proxy_msg *msg = &xfer->rx_message;
	struct ti_sci_msg_hdr *hdr = NULL;
	unsigned int retry = 5;
	int ret = 0;

	for (; retry > 0; retry--) {
		/* Receive the response */
		ret = k3_sec_proxy_recv(msg);
		if (ret) {
			EMSG("Message receive failed (%d)", ret);
			return ret;
		}

		/* msg is updated by Secure Proxy driver */
		hdr = (struct ti_sci_msg_hdr *)msg->buf;

		/* Sanity check for message response */
		if (hdr->seq == message_sequence)
			break;

		IMSG("Message with sequence ID %u is not expected", hdr->seq);
	}
	if (!retry) {
		EMSG("Timed out waiting for message");
		return TEE_ERROR_BUSY;
	}

	if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) {
		DMSG("Message not acknowledged");
		return TEE_ERROR_ACCESS_DENIED;
	}

	return 0;
}

/**
 * ti_sci_do_xfer() - Do one transfer
 *
 * @xfer: Transfer to initiate and wait for response
 *
 * Return: 0 if all goes well, else appropriate error message
 */
static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
{
	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
	int ret = 0;

	/* Send the message */
	ret = k3_sec_proxy_send(msg);
	if (ret) {
		EMSG("Message sending failed (%d)", ret);
		return ret;
	}

	/* Get the response */
	ret = ti_sci_get_response(xfer);
	if (ret) {
		if ((TEE_Result)ret != TEE_ERROR_ACCESS_DENIED)
			EMSG("Failed to get response (%d)", ret);
		return ret;
	}

	return 0;
}

int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info)
{
	struct ti_sci_msg_req_version req = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_VERSION, 0x0,
				&req, sizeof(req),
				rev_info, sizeof(*rev_info),
				&xfer);
	if (ret)
		return ret;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	return 0;
}

static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
{
	struct ti_sci_msg_req_set_device_state req = { };
	struct ti_sci_msg_resp_set_device_state resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags,
				&req, sizeof(req),
				&resp, sizeof(resp),
				&xfer);
	if (ret)
		return ret;

	req.id = id;
	req.state = state;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	return 0;
}

int ti_sci_device_get(uint32_t id)
{
	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON);
}

int ti_sci_device_put(uint32_t id)
{
	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
}

int ti_sci_set_fwl_region(uint16_t fwl_id, uint16_t region,
			  uint32_t n_permission_regs, uint32_t control,
			  const uint32_t permissions[FWL_MAX_PRIVID_SLOTS],
			  uint64_t start_address, uint64_t end_address)
{
	struct ti_sci_msg_req_fwl_set_firewall_region req = { };
	struct ti_sci_msg_resp_fwl_set_firewall_region resp = { };
	struct ti_sci_xfer xfer = { };
	unsigned int i = 0;
	int ret = 0;

	assert(n_permission_regs <= FWL_MAX_PRIVID_SLOTS);

	ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_SET, 0,
				&req, sizeof(req),
				&resp, sizeof(resp),
				&xfer);
	if (ret)
		return ret;

	req.fwl_id = fwl_id;
	req.region = region;
	req.n_permission_regs = n_permission_regs;
	req.control = control;
	for (i = 0; i < n_permission_regs; i++)
		req.permissions[i] = permissions[i];
	req.start_address = start_address;
	req.end_address = end_address;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	return 0;
}

int ti_sci_get_fwl_region(uint16_t fwl_id, uint16_t region,
			  uint32_t n_permission_regs, uint32_t *control,
			  uint32_t permissions[FWL_MAX_PRIVID_SLOTS],
			  uint64_t *start_address, uint64_t *end_address)
{
	struct ti_sci_msg_req_fwl_get_firewall_region req = { };
	struct ti_sci_msg_resp_fwl_get_firewall_region resp = { };
	struct ti_sci_xfer xfer = { };
	unsigned int i = 0;
	int ret = 0;

	assert(n_permission_regs <= FWL_MAX_PRIVID_SLOTS);

	ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_GET, 0,
				&req, sizeof(req),
				&resp, sizeof(resp),
				&xfer);
	if (ret)
		return ret;

	req.fwl_id = fwl_id;
	req.region = region;
	req.n_permission_regs = n_permission_regs;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	*control = resp.control;
	for (i = 0; i < n_permission_regs; i++)
		permissions[i] = resp.permissions[i];
	*start_address = resp.start_address;
	*end_address = resp.end_address;

	return 0;
}

int ti_sci_change_fwl_owner(uint16_t fwl_id, uint16_t region,
			    uint8_t owner_index, uint8_t *owner_privid,
			    uint16_t *owner_permission_bits)
{
	struct ti_sci_msg_req_fwl_change_owner_info req = { };
	struct ti_sci_msg_resp_fwl_change_owner_info resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_CHANGE_OWNER, 0,
				&req, sizeof(req),
				&resp, sizeof(resp),
				&xfer);
	if (ret)
		return ret;

	req.fwl_id = fwl_id;
	req.region = region;
	req.owner_index = owner_index;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	*owner_privid = resp.owner_privid;
	*owner_permission_bits = resp.owner_permission_bits;

	return 0;
}

int ti_sci_get_dkek(uint8_t sa2ul_instance,
		    const char *context, const char *label,
		    uint8_t dkek[SA2UL_DKEK_KEY_LEN])
{
	struct ti_sci_msg_req_sa2ul_get_dkek req = { };
	struct ti_sci_msg_resp_sa2ul_get_dkek resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_SA2UL_GET_DKEK, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;

	req.sa2ul_instance = sa2ul_instance;
	req.kdf_label_len = strlen(label);
	req.kdf_context_len = strlen(context);
	if (req.kdf_label_len + req.kdf_context_len >
	    KDF_LABEL_AND_CONTEXT_LEN_MAX) {
		EMSG("Context and Label too long");
		return TEE_ERROR_BAD_PARAMETERS;
	}
	memcpy(req.kdf_label_and_context, label, strlen(label));
	memcpy(req.kdf_label_and_context + strlen(label), context,
	       strlen(context));

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	memcpy(dkek, resp.dkek, sizeof(resp.dkek));
	memzero_explicit(&resp, sizeof(resp));
	return 0;
}

int ti_sci_read_otp_mmr(uint8_t mmr_idx, uint32_t *val)
{
	struct ti_sci_msg_req_read_otp_mmr req = { };
	struct ti_sci_msg_resp_read_otp_mmr resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_OTP_MMR, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		goto exit;

	req.mmr_idx = mmr_idx;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		goto exit;

	*val = resp.mmr_val;

exit:
	memzero_explicit(&resp, sizeof(resp));
	return ret;
}

int ti_sci_write_otp_row(uint8_t row_idx, uint32_t row_val, uint32_t row_mask)
{
	struct ti_sci_msg_req_write_otp_row req = { };
	struct ti_sci_msg_resp_write_otp_row resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_WRITE_OTP_ROW, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		goto exit;

	req.row_idx = row_idx;
	req.row_val = row_val;
	req.row_mask = row_mask;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		goto exit;

	DMSG("resp.row_val: 0x%08x", resp.row_val);

	if (resp.row_val != (req.row_val & req.row_mask)) {
		EMSG("Value not written correctly");
		DMSG("req.row_val : 0x%08"PRIx32, req.row_val);
		DMSG("req.row_mask: 0x%08"PRIx32, req.row_mask);
		ret = TEE_ERROR_BAD_STATE;
	}

exit:
	memzero_explicit(&resp, sizeof(resp));
	memzero_explicit(&req, sizeof(req));
	return ret;
}

int ti_sci_lock_otp_row(uint8_t row_idx, uint8_t hw_write_lock,
			uint8_t hw_read_lock, uint8_t row_soft_lock)
{
	struct ti_sci_msg_req_lock_otp_row req = { };
	struct ti_sci_msg_resp_lock_otp_row resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_LOCK_OTP_ROW, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;

	req.row_idx = row_idx;
	req.hw_write_lock = hw_write_lock;
	req.hw_read_lock = hw_read_lock;
	req.row_soft_lock = row_soft_lock;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	return 0;
}

int ti_sci_get_swrev(uint32_t *swrev)
{
	struct ti_sci_msq_req_get_swrev req = { };
	struct ti_sci_msq_resp_get_swrev resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_SWREV, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;

	req.identifier = OTP_REV_ID_SEC_BRDCFG;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	*swrev = resp.swrev;
	memzero_explicit(&resp, sizeof(resp));
	return 0;
}

int ti_sci_get_keycnt_keyrev(uint32_t *key_cnt, uint32_t *key_rev)
{
	struct ti_sci_msq_req_get_keycnt_keyrev req = { };
	struct ti_sci_msq_resp_get_keycnt_keyrev resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_KEYCNT_KEYREV, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	*key_cnt = resp.keycnt;
	*key_rev = resp.keyrev;
	memzero_explicit(&resp, sizeof(resp));
	return 0;
}

#define DEBUG_PRT
int ti_sci_set_keyrev(const uint8_t* dual_cert_ptr, uint32_t dual_cert_len)
{
	struct ti_sci_msq_req_set_keyrev req = { };
	struct ti_sci_msq_resp_set_keyrev resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;
	uint8_t *cert_ptr;

	cert_ptr = (uint8_t *)phys_to_virt(SRAM_SCRATCH_BASE, MEM_AREA_IO_SEC, SRAM_SCRATCH_SIZE);
	memcpy(cert_ptr, dual_cert_ptr, dual_cert_len);

	ret = ti_sci_setup_xfer(TI_SCI_MSG_WRITE_KEYREV, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;
	req.value		= 2;
	req.cert_addr_lo	= SRAM_SCRATCH_BASE;
	req.cert_addr_hi	= 0;
#ifdef DEBUG_PRT
	IMSG("req.value = 0x%08X  \n", req.value);
	IMSG("req.cert_addr_lo = 0x%08X  \n", req.cert_addr_lo);
	IMSG("req.cert_addr_hi = 0x%08X  \n", req.cert_addr_hi);
	IMSG("req.hdr.type = 0x%0X  \n", req.hdr.type);
	IMSG("req.hdr.host = 0x%0X  \n", req.hdr.host);
	IMSG("req.hdr.seq = 0x%0X  \n", req.hdr.seq);
	IMSG("req.hdr.flags = 0x%0X  \n", req.hdr.flags);
#endif
	ret = ti_sci_do_xfer(&xfer);
	if (ret){
		EMSG(">>>> ti_sci_do_xfer() failed with ret = 0x%0x  \n", ret);
		return ret;
	}
#ifdef DEBUG_PRT
	IMSG("resp.hdr.type = 0x%0X  \n", resp.hdr.type);
	IMSG("resp.hdr.host = 0x%0X  \n", resp.hdr.host);
	IMSG("resp.hdr.seq = 0x%0X  \n", resp.hdr.seq);
	IMSG("resp.hdr.flags = 0x%0X  \n", resp.hdr.flags);
#endif
	memzero_explicit(&resp, sizeof(resp));
	return 0;
}

int ti_sci_init(void)
{
	struct ti_sci_msg_resp_version rev_info = { };
	int ret = 0;

	ret = ti_sci_get_revision(&rev_info);
	if (ret) {
		EMSG("Unable to communicate with control firmware (%d)", ret);
		return ret;
	}

	IMSG("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')",
	     rev_info.abi_major, rev_info.abi_minor,
	     rev_info.firmware_revision,
	     rev_info.firmware_description);

	return 0;
}
ti_sci.h

Please help to enable key revoke on DRA821.  

BR, Rich 

  • Rich, 

    What exactly do you mean by key revoke?

    On dra821 only key writer is allowed to burn keys to efuse.

    Runtime APIs only support incrementing the key version. 

    No support to touch keys in u-boot.

    Best Regards,

    Keerthy 

  • HI Rich

    Based on the earlier implementation i assume you want to update the KEYREV value using optee interface not using uboot. If that is the case you can use the same code on DRA821 as well .

    Eventually OPTEE is making use of TIFS service to update the value in the effuses. These APIs are still valid for DRA821 as well.One thing which we need to make sure that we have enabled the VPP before burning anything on to the effuses.

    Regards
    Diwakar

  • Diwakar, 

    That was a good point and we verified VPP voltage and enable it all the time. 

    For migrating revoke onto DRA821, there are two gaps.

    1.  OPTEE needs to get authorization in DMSC but new SDK is no longer to support rebuild SYSFW (DMSC?) 

     The modified code requires to rebuild SYSFW, right? 

    2. There is a address define for Scartchpad for AM62x and assume there is a corresponding address for DRA821 but could not find it.  

    AM62

    #define SRAM_SCRATCH_BASE       0x43C3B000

    Nd assists to enable key revoke on DRA821.  

    ti-optee-os/core/arch/arm/plat-k3/drivers/ti_sci.c

    /*
     * K3 System Firmware Security Configuration Data
     *
     * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/ 
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include "common.h"
    
    
    #define SYSFW_TEST_HOST_ID HOST_ID_MAIN_0_R5_0
    #define OTHER_HOST_ID HOST_ID_A53_0
    
    const struct boardcfg_security am62_boardcfg_security_data = {
    	/* boardcfg_abi_rev */
    	.rev = {
    		.boardcfg_abi_maj = 0x0,
    		.boardcfg_abi_min = 0x1,
    	},
    
    	/* boardcfg_proc_acl */
    	.processor_acl_list = {
    		.subhdr = {
    			.magic = BOARDCFG_PROC_ACL_MAGIC_NUM,
    			.size = sizeof(struct boardcfg_proc_acl),
    		},
    		.proc_acl_entries = {{ 0 }},
    	},
    
    	/* boardcfg_host_hierarchy */
    	.host_hierarchy = {
    		.subhdr = {
    			.magic = BOARDCFG_HOST_HIERARCHY_MAGIC_NUM,
    			.size = sizeof(struct boardcfg_host_hierarchy),
    		},
    		.host_hierarchy_entries = {{ 0 }},
    	},
    
    	/* OTP access configuration */
    	.otp_config = {
    		.subhdr = {
    			.magic = BOARDCFG_OTP_CFG_MAGIC_NUM,
    			.size = sizeof(struct boardcfg_extended_otp),
    		},
    		/* Host ID 0 is DMSC. This means no host has write access to OTP array */
    		.write_host_id = 11,
    		/* This is an array with 32 entries */
    		.otp_entry = {{ 0 } },
    	},
    
    	/* DKEK configuration */
    	.dkek_config = {
    		.subhdr = {
    			.magic = BOARDCFG_DKEK_CFG_MAGIC_NUM,
    			.size = sizeof(struct boardcfg_dkek),
    		},
    		.allowed_hosts = { HOST_ID_ALL, 0, 0, 0 },
    		.allow_dkek_export_tisci = 0x5A,
    		.rsvd = {0, 0, 0},
    	},
    
    	/* SA2UL configuration */
    	.sa2ul_cfg = {
    		.subhdr = {
    			.magic = BOARDCFG_SA2UL_CFG_MAGIC_NUM_RSVD,
    			.size = 0,
    		},
    		.auth_resource_owner = 0,
    		.enable_saul_psil_global_config_writes = 0x5A,
    		.rsvd = {0, 0},
    	},
    
    	/* Secure JTAG Unlock Configuration */
    	.sec_dbg_config = {
    		.subhdr = {
    			.magic = BOARDCFG_SEC_DBG_CTRL_MAGIC_NUM,
    			.size = sizeof(struct boardcfg_secure_debug_config),
    		},
    		.allow_jtag_unlock = 0x5A,
    		.allow_wildcard_unlock = 0x5A,
    		.min_cert_rev = 0x0,
    		.jtag_unlock_hosts = {0, 0, 0, 0},
    	},
    
    	.sec_handover_cfg = {
    		.subhdr = {
    			.magic = BOARDCFG_SEC_HANDOVER_CFG_MAGIC_NUM,
    			.size = sizeof(struct boardcfg_sec_handover),
    		},
    		.handover_msg_sender = 0,
    		.handover_to_host_id = 0,
    		.rsvd = {0,0,0,0},
    	},
    };
    

     

                            .size = sizeof(struct boardcfg_extended_otp),

                    },

                    /* Host ID 0 is DMSC. This means no host has write access to OTP array */

    -               .write_host_id = 0,

    +               .write_host_id = 11,

                    /* This is an array with 32 entries */

                    .otp_entry = {{ 0 } },

            },

    BR, Rich

  • Hi Rich,

    They are copying the dual signed certificate to scratch memory before sending it to TIFS. You can also use the OCMC memory on DRA821.

    MCU_MSRAM_1MB0_RAM      0x0041C000000 - x0041CFFFFF  (1 MB)

    Regards
    Diwakar

  • Diwakar, 

    Customer can try to use OCRAM for the copy. Keep the original define SRAM_SCRATCH_BASE and replace the address as 0x41C00000?

    Your reply show 0x0041C000000, is that a typo for a additional 0? 

    #define SRAM_SCRATCH_BASE       0x41C00000   

    What about the first question? Will you be able to create a new SYSFW (DM?) for revoke? Customer cannot build it now since it is no longer supported to be build. 

    BR, Rich

  • Hi Rich,

    Your reply show 0x0041C000000, is that a typo for a additional 0? 

    Yes there was a typo it is 0x0041C00000.

    What about the first question? Will you be able to create a new SYSFW (DM?) for revoke? Customer cannot build it now since it is no longer supported to be build. 

    We dont have to rebuild the TIFS binary for this,by default TIFS support this functionality on HS-SE device.You just need to send the TISCI_MSG_WRITE_KEYREV with dual signed certificate.

    Regards
    Diwakar

  • U-Boot SPL 2024.04-ged60d191-dirty (Aug 14 2025 - 16:01:32 +0800)
    SYSFW ABI: 4.0 (firmware rev 0x000b '11.0.9--v11.00.09+ (Fancy Rat)')

    Hi Ti 

    It still do not work. I include dual_cert_keyrev.h , same as tiboo3.bin for change CUP type (HS-FS -> HS-SE)



    DDR type: Micron LPDDR4 4G

    Trying to boot from SPI
    Authentication passed
    Authentication passed
    Authentication passed
    Loading Environment from SPIFlash... *** Warning - bad CRC, using default environment

    Authentication passed
    Authentication passed
    Starting ATF on ARM64 core...

    NOTICE: BL31: v2.10.0(release):ed60d191-dirty
    NOTICE: BL31: Built : 16:02:47, Aug 14 2025
    I/TC:
    I/TC: Primary CPU initializing
    I/TC: SYSFW ABI: 4.0 (firmware rev 0x000b '11.0.9--v11.00.09+ (Fancy Rat)')
    I/TC: Secure Board Configuration Software: Rev 1
    I/TC: Secure Boot Keys: Count 2, Rev 1
    I/TC: >>>> ti_sci_set_keyrev() unit test start
    I/TC: req.value = 0x00000002
    I/TC: req.cert_addr_lo = 0x41C00000
    I/TC: req.cert_addr_hi = 0x00000000
    I/TC: req.hdr.type = 0x9035
    I/TC: req.hdr.host = 0xB
    I/TC: req.hdr.seq = 0x4
    I/TC: req.hdr.flags = 0x2
    E/TC:0 0 ti_sci_set_keyrev:516 >>>> ti_sci_do_xfer() failed with ret = 0xffff0001
    I/TC: HUK Initialized
    I/TC: Activated SA2UL device
    I/TC: Enabled firewalls for SA2UL TRNG device
    I/TC: SA2UL TRNG initialized
    I/TC: SA2UL Drivers initialized
    E/TC:0 0 Dead canary at end of 'stack_abt[7]' (0x9e8a83fc)
    E/TC:0 0 Panic at core/kernel/thread.c:146 <thread_check_canaries>
    E/TC:0 0 TEE load address @ 0x9e800000
    E/TC:0 0 Call stack:
    E/TC:0 0 0x9e808008
    E/TC:0 0 0x9e81f168
    E/TC:0 0 0x9e822594
    E/TC:0 0 0x9e82281c
    E/TC:0 0 0x9e807df8

  • --- a/k3-image-gen/ti-optee-os/core/arch/arm/plat-k3/drivers/ti_sci.c
    +++ b/k3-image-gen/ti-optee-os/core/arch/arm/plat-k3/drivers/ti_sci.c
    @@ -34,7 +34,7 @@ struct ti_sci_xfer {
    struct k3_sec_proxy_msg rx_message;
    };

    -#define SRAM_SCRATCH_BASE 0x43C3B000
    +#define SRAM_SCRATCH_BASE 0x0041C00000

  • Hi Chen,

    Can you connect to the core and see if the dual signed certificate is there at address 0x41C00000.

    Regards
    Diwakar

  • No I can not. 

    E/TC:0 0 Panic at core/kernel/thread.c:146 <thread_check_canaries>

  • Hi Alvin, 

    What is the boot flow you are using ?

    No I can not. 

    Did you mean you are not able to dump the data from location 0x41C00000. You can connect to MCU R5F core and see if the debug certificate is there or not.

    As you are including dual signed certificate into your application, other thing which you can try is instead of copying the data to OCMC RAM just pass the physical address of the array (By converting virtual address to physical)

    Regards
    Diwakar

  • Diwakar, 

    Alvin is using QSPI NOR flash boot. 

    I will be in customer side tomorrow and we can have WebEX by then about noon your time. 

    BR, Rich 

  • Hi Rich, 

    As suggested dont do intermediate copy and directly pass the physical address of the cert , see if it works.

    Also please enable the TIFS traces to get more details.

    Regards
    Diwakar

  • Diwakar, 

    As we updated that old OPTEE code doesn't work with the modifications you suggested. 

    Do you get feedback from team on the new OPTEE in git? How can we send dual_cert via TISCI to SYSFW? 

    Please provide a working sample code we can use it directly since you mentioned this is verified by team.   

    BR, Rich

  • Diwakar, 

    Do you get a sample code for new OPTEE from developer?

    BR, Rich

  • Hi Rich,

    I got feedback from internal team they only added support for KEY rev update message. Ideally this should work after passing valid dual signed certificate.

    As we updated that old OPTEE code doesn't work with the modifications you suggested. 

    Allow me sometime to validate this at my end will update you by EOW.

    Regards
    Diwakar

  • Diwakar, 

    Yes, please get a way to pass dual signed certification via OPTEE to get the eFUSE register been updated. 

    We are worried there is limitation on access right from different core. 

    BR, Rich

  • Hi Rich, 

    can you share the dual signed certificate in.h format which I can test with?

    Regards
    Diwakar

  • Hi Rich,

    Thanks for sharing the cert i will test it out at my end.

    Regards
    Diwakar

  • Hi Rich,

    i am trying to arrange board but it will take some time in the meantime can customer do similar kind of change and test it out.

    in optee user space application do below kind of changes:

    diff --git a/otp_keywriting/host/main.c b/otp_keywriting/host/main.c
    index 8ec2ab5..7f68d81 100644
    --- a/otp_keywriting/host/main.c
    +++ b/otp_keywriting/host/main.c
    @@ -34,7 +34,7 @@
     
     /* OP-TEE TEE client API (built by optee_client) */
     #include <tee_client_api.h>
    -
    +#include "keycert.h"
     /* TA API: UUID and command IDs */
     #include <otp_keywriting_ta.h>
     
    @@ -135,6 +135,35 @@ TEEC_Result lock_otp_row(struct test_ctx *ctx, uint8_t index_row, uint8_t lock_m
     
            return res;
     }
    +TEEC_Result update_kevrev(struct test_ctx *ctx)
    +{
    +       TEEC_Operation op;
    +       uint32_t origin;
    +       TEEC_Result res;
    +       const uint8_t gKeyCert[KEYCERT_SIZE_IN_BYTES] __attribute__((aligned(128))) = KEYCERT;
    +
    +       fprintf(stderr, "Updating KEVREV\n");
    +
    +       op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_VALUE_INPUT,
    +                                        TEEC_NONE, TEEC_NONE);
    +
    +       op.params[0].tmpref.buffer = gKeyCert;
    +       op.params[1].value.a = 2;
    +
    +       fprintf(stderr,"invoke update kevrev\n");
    +       res = TEEC_InvokeCommand(&ctx->sess, TA_OTP_KEYWRITING_CMD_UPDATE_KEVREV,&op, &origin);
    +
    +       switch (res) {
    +       case TEEC_SUCCESS:
    +       case TEEC_ERROR_ITEM_NOT_FOUND:
    +               break;
    +       default:
    +               fprintf(stderr, "Command READ_RAW failed: 0x%x / %u\n", res,
    +                       origin);
    +       }
    +
    +       return res;
    +}
     
     void print_usage()
     {
    @@ -143,10 +172,11 @@ void print_usage()
                            "\t--write <hexval>     Write OTP row with value\n"
                            "\t--mask <hexval>      Mask while writing value\n"
                            "\t--read               Read OTP mmr\n"
    -                       "\t--lock               Lock OTP row\n");
    +                       "\t--lock               Lock OTP row\n"
    +                       "\t--kevrev             update kevrev\n");
     }
     
    -enum args { ARGS_READ = 20, ARGS_WRITE, ARGS_VAL, ARGS_MASK, ARGS_LOCK, ARGS_INDEX };
    +enum args { ARGS_READ = 20, ARGS_WRITE, ARGS_VAL, ARGS_MASK, ARGS_LOCK, ARGS_INDEX,ARGS_KEYREV };
     
     int main(int argc, char **argv)
     {
    @@ -165,6 +195,7 @@ int main(int argc, char **argv)
                    { "mask", required_argument, NULL, ARGS_MASK},
                    { "lock", no_argument, &method, ARGS_LOCK },
                    { "index", required_argument, NULL, ARGS_INDEX },
    +               { "keyrev",no_argument, &method,ARGS_KEYREV },
                    { NULL, 0, NULL, 0 }
            };
     
    @@ -179,7 +210,7 @@ int main(int argc, char **argv)
                            break;
                    case ARGS_MASK:
                            sscanf(optarg, "%x", &mask);
    -                       break;
    +                       break;  
                    case '?':
                            fprintf(stderr, "Unknown option %s\n",
                                    long_options[option_index].name);
    @@ -193,8 +224,8 @@ int main(int argc, char **argv)
     
            printf("val: 0x%08x\n", val);
            printf("mask: 0x%08x\n", mask);
    -
    -       if (index == -1)
    +       printf("opt: %d\n", opt);
    +       if (index == -1 && method != ARGS_KEYREV)       
            {
                    ret = -EINVAL;
                    goto err_exit;
    @@ -225,6 +256,12 @@ int main(int argc, char **argv)
                    if (ret != TEEC_SUCCESS)
                            errx(1, "Failed to lock row: %d\n", ret);
                    break;
    +       case ARGS_KEYREV:
    +               fprintf(stderr, "- Nw Update KEVREV\n");        
    +               ret = update_kevrev(&ctx);
    +               if (ret != TEEC_SUCCESS)
    +                       errx(1, "Failed to update KEVREV: %d\n", ret);
    +               break;
     
            }
            }
    

    while at optee PTA side:

    • Apply upstream patch for tisci api support:/cfs-file/__key/communityserver-discussions-components-files/791/0001_2D00_plat_2D00_k3_2D00_drivers_2D00_ti_2D00_sci_2D00_Add_2D00_support_2D00_for_2D00_setting_2D00_KEYRE.patch
    • make similar changes in trusted application.

      diff --git a/core/pta/k3/otp.c b/core/pta/k3/otp.c
      index bfe87a37e..84d445d2c 100644
      --- a/core/pta/k3/otp.c
      +++ b/core/pta/k3/otp.c
      @@ -10,7 +10,8 @@
       #include <inttypes.h>
       #include <k3/otp_keywriting_ta.h>
       #include <kernel/pseudo_ta.h>
      -
      +#include <mm/core_memprot.h>                                                                                                            
      +#include <mm/core_mmu.h>   
       static TEE_Result write_otp_row(uint32_t param_types, TEE_Param params[4])
       {
       	TEE_Result ret = TEE_SUCCESS;
      @@ -96,6 +97,42 @@ static TEE_Result lock_otp_row(uint32_t param_types, TEE_Param params[4])
       	return TEE_SUCCESS;
       }
       
      +static TEE_Result update_otp_key_revoke(uint32_t param_types,
      +					TEE_Param params[4])
      +{
      +	TEE_Result ret = TEE_SUCCESS;
      +	uint32_t phys_address = 0;
      +	const uint32_t exp_param_types =
      +		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
      +				TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE,
      +				TEE_PARAM_TYPE_NONE);
      +	
      +	DMSG("Revoke the cert: 0x%08"PRIx32, params[0].memref.buffer);
      +	DMSG("Revoke the key: 0x%08"PRIx32, params[1].value.a);
      +	phys_address = virt_to_phys((uint8_t *)params[0].memref.buffer);		
      +	if(phys_address == 0)
      +	{
      +		return TEE_ERROR_BAD_PARAMETERS;
      +	}
      +	else
      +	{
      +		EMSG("Physical address: 0x%08"PRIx32, phys_address);
      +	}
      +	/*
      +	 * Safely get the invocation parameters
      +	 */
      +	if (param_types != exp_param_types)
      +		return TEE_ERROR_BAD_PARAMETERS;
      +
      +	ret = ti_sci_set_keyrev(params[1].value.a, phys_address,0);
      +	if (ret)
      +		return ret;
      +	DMSG("Revoke the key: 0x%08"PRIx32, params[0].value.a);
      +
      +	return TEE_SUCCESS;
      +}
      +
      +
       static TEE_Result invoke_command(void *session __unused,
       				 uint32_t command, uint32_t param_types,
       				 TEE_Param params[4])
      @@ -107,6 +144,8 @@ static TEE_Result invoke_command(void *session __unused,
       		return write_otp_row(param_types, params);
       	case TA_OTP_KEYWRITING_CMD_LOCK_ROW:
       		return lock_otp_row(param_types, params);
      +	case TA_OTP_KEYWRITING_CMD_UPDATE_KEVREV:
      +		return update_otp_key_revoke(param_types, params);
       	default:
       		EMSG("Command ID 0x%"PRIx32" is not supported", command);
       		return TEE_ERROR_NOT_SUPPORTED;
    • make  below change in config.mk to avoid any stack related issue.
      CFG_STACK_THREAD_EXTRA ?= 150000

    See if it works.

    Regards
    Diwakar

  • Hi TI

    I have try revoke under linux(TA) ,   but it still do not work. 

    I think revoke by optee of uboot or optee of linux is same.

  • Diwakar, 

    First, we would like to confirm the patch you provided is based on new OPTEE which is in SDK 11 already.

    Second, had this patch been verified on SDK 11 with TI keys? 

    Please have one socket board with TI key programmed then revoke it to switch to second key and provide the historical logs so we can follow the process to implement on customer board. 

    We can arrange remote debug section if we cannot complete it follow your steps and logs.

    BR, Rich

  • Hi Alvin,

    Are you still seeing a crash, please provide more details.

    Help me with logs also help me with TIFS logs as well to see if the request reaches to TIFS or not.

    Regards
    Diwakar

  • Diwakar, 

    There is no response after sending TISCI commend through OPTEE. 

    Linux doesn't crash but just no response. 

    Customer board doesn't have MCU_UART reserved so there is no way to get TIFS logs.

    Please provide sample code and address to dump for the TISCI status you would like to check. 

    VPP is enabled. 

    Boot config 0x11 is set. 

    BR, Rich

  • Hi Rich,

    Do customer have a support for wakeup UART, if yes please enable the TIFS traces with below changes and share the traces.

    diff --git a/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi b/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi
    index 9affb20a..399e660f 100644
    --- a/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi
    +++ b/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi
    @@ -154,3 +154,7 @@
     &chipid {
            bootph-all;
     };
    +
    +&wkup_uart0_pins_default{
    +       bootph-all;
    +};
    

    diff --git a/board/ti/j721s2/board-cfg.yaml b/board/ti/j721s2/board-cfg.yaml
    index 94e61ab1..4af4c0db 100644
    --- a/board/ti/j721s2/board-cfg.yaml
    +++ b/board/ti/j721s2/board-cfg.yaml
    @@ -32,5 +32,5 @@ board-cfg:
             subhdr:
                 magic: 0x020C
                 size: 8
    -        trace_dst_enables: 0x00
    -        trace_src_enables: 0x00
    +        trace_dst_enables: 0x0D
    +        trace_src_enables: 0x1F
    

    Please provide sample code and address to dump for the TISCI status you would like to check. 

    They can refer to this code customer need to dump the data from 0x4406B000 with size of 0x1000. 

    I tested at my end with the same changes which i provided in the e2e and could see message is reaching to TIFS.

    Regards
    Diwakar

  • Diwakar, 

    Customer is using SDK10 and the original OPTEE and patches were from SDK8. 

    The OPTEE implementation (new) on SDK10 and SDK11 looks the same and customer software will Mass Production with SDK10 based. 

    Please verify key revoke feature on TI EVM with SDK 10 package then customer can follow the same procedure to enable it. 

    BR, Rich 

  • HI Rich,

    Below are the reference patchs which I tested at my end on TI EVM. I checked the TIFS traces and the call reaching to TIFS and validation of dual certificate is passing.

    It should work if we enable the VPP. I am working internally to test this on sockected board, which will take some time.In the meantime, customer can do similar changes .

    optee_example reference patch:

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/optee_5F00_example_5F00_keyrevoke.patch

    optee_os trusted application patch:I am copying the dual cert to 0x41CFEFFF address as it is not used by any component on TI EVM.

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/trusted_5F00_application_5F00_patch_5F00_optee_5F00_os.patch

    Board config changes :

    diff --git a/board/ti/j721s2/sec-cfg.yaml b/board/ti/j721s2/sec-cfg.yaml
    index d0f3a161..9fc786e4 100644
    --- a/board/ti/j721s2/sec-cfg.yaml
    +++ b/board/ti/j721s2/sec-cfg.yaml
    @@ -248,104 +248,104 @@ sec-cfg:
             subhdr:
                 magic: 0x4081
                 size: 69
    -        write_host_id: 0
    +        write_host_id: 11
    

    TIFS traces on TI EVM.

    Here error code 4 means certficate validation passed and failed and while writing to OTP as VPP is not enabled.

    Regards
    Diwakar

  • Hi Rich,

    I was able to arrange one TDA4AL socketed board and tested the same patches on that and could see keyrev is getting updated. Please find below logs.

    Before key revoke:

    -----------------------
    SoC ID Header Info:
    -----------------------
    NumBlocks            : 2
    -----------------------
    SoC ID Public ROM Info:
    -----------------------
    SubBlockId           : 1
    SubBlockSize         : 26
    DeviceName           : j7aep
    DeviceType           : HSSE
    DMSC ROM Version     : [0, 1, 0, 1]
    R5 ROM Version       : [0, 1, 0, 1]
    -----------------------
    SoC ID Secure ROM Info:
    -----------------------
    Sec SubBlockId       : 2
    Sec SubBlockSize     : 166
    Sec Prime            : 0
    Sec Key Revision     : 1
    Sec Key Count        : 2
    Sec TI MPK Hash      : bf0efb75bade39aa63eab5514b98ebda84cb1dd8a35e07b7a0f473760592a465d82f4945ee60da406209b1748f16074e47ccd30cea5c2ba494eca747ad876d1c
    Sec Cust MPK Hash    : 1f6002b07cd9b0b7c47d9ca8d1aae57b8e8784a12f636b2b760d7d98a18f189760dfd0f23e2b0cb10ec7edc7c6edac3d9bdfefe0eddc3fff7fe9ad875195527d
    Sec Unique ID        : 8ed01cc5eafff89affa2b44942b8659ff5c57a2159878c3cbfb656c78c130699
    
    

    Linux logs:

    invoke update kevrev
    D/TC:? 0 update_otp_key_revoke:117 Revoke the key: 0x00000002
    D/TC:? 0 update_otp_key_revoke:119 vir_address: 0x9acfefff
    F/TC:? 0 k3_sec_proxy_send:131 Verifying the thread
    F/TC:? 0 k3_sec_proxy_verify_thread:71 Check for thread corruption
    F/TC:? 0 k3_sec_proxy_verify_thread:88 Check for thread direction
    F/TC:? 0 k3_sec_proxy_verify_thread:100 Check for thread queue
    F/TC:? 0 k3_sec_proxy_verify_thread:113 Success
    F/TC:? 0 k3_sec_proxy_recv:193 Verifying thread
    F/TC:? 0 k3_sec_proxy_verify_thread:71 Check for thread corruption
    F/TC:? 0 k3_sec_proxy_verify_thread:88 Check for thread direction
    F/TC:? 0 k3_sec_proxy_verify_thread:100 Check for thread queue
    F/TC:? 0 k3_sec_proxy_verify_thread:113 Success
    D/TC:? 0 update_otp_key_revoke:132 Revoke the key: 0x9c601088
    
    D/TC:? 0 tee_ta_close_session:460 csess 0x9e8a4690 id 3
    We're done, close and release TEE resources
    D/TC:? 0 tee_ta_close_session:479 Destroy session
    

    After key revoke:

    -----------------------
    SoC ID Header Info:
    -----------------------
    NumBlocks            : 2
    -----------------------
    SoC ID Public ROM Info:
    -----------------------
    SubBlockId           : 1
    SubBlockSize         : 26
    DeviceName           : j7aep
    DeviceType           : HSSE
    DMSC ROM Version     : [0, 1, 0, 1]
    R5 ROM Version       : [0, 1, 0, 1]
    -----------------------
    SoC ID Secure ROM Info:
    -----------------------
    Sec SubBlockId       : 2
    Sec SubBlockSize     : 166
    Sec Prime            : 0
    Sec Key Revision     : 2
    Sec Key Count        : 2
    Sec TI MPK Hash      : bf0efb75bade39aa63eab5514b98ebda84cb1dd8a35e07b7a0f473760592a465d82f4945ee60da406209b1748f16074e47ccd30cea5c2ba494eca747ad876d1c
    Sec Cust MPK Hash    : 1f6002b07cd9b0b7c47d9ca8d1aae57b8e8784a12f636b2b760d7d98a18f189760dfd0f23e2b0cb10ec7edc7c6edac3d9bdfefe0eddc3fff7fe9ad875195527d
    Sec Unique ID        : 8ed01cc5eafff89affa2b44942b8659ff5c57a2159878c3cbfb656c78c130699
    
    

    I am pretty confident that things will work on customer board as well.

    Regards
    Diwakar

  • Hi Ti

    Can you provide all detailed operations?? It look work. But I do not know how to do it .

    1. Your optee patch.

    2. how to create dual_key.h

    3. how to revoke under linux?? ...

  • Hi Alvin.

    Patches are present in my previous response  RE: DRA821U: DRA821 key revoke feature in u-boot 

    Regards 

    Diwakar 

  • Diwakar, 

    Could you provide CA example, it is the last step? 

    BR, Rich

  • Hi Alvin.

    optee_example_keyrevoke.patch is a CA patch, Here we are sending dual signed cert to optee trusted application, my dual signed cert is included in the form of header file keycert.h. I am passing the address of this cert to TA.

    trusted_application_patch_optee_os.patch is a trusted application patch. In this patch, we are copying the dual cert to OCMC memory and then sending it to TIFS.

    Regards
    Diwakar

  • Whare download the CA app you used ??

  • HI Alvin 

    Not sure if i understood your question correctly, i generated the client application and copied to my rootfs.

    After booting the device I ran my application like 

    /optee_example_otp_keyrev  

    Regards
    Diwakar

  • Diwakar, 

    Could you provide the code base you use for optee_example_otp_keyrev? 

    There is only patch and customer want to code base for reference. 

    BR, Rich

  • Hi Rich,

    This is the repo which I used for building the example.

    https://github.com/linaro-swg/optee_examples

    My question would be how customer was building earlier ? They were using client application earlier as well.

     They have to refer update_kevrev function from the patch and make changes accordingly in their application.

    Regarsds
    Diwakar

  • Diwakar, 

    Customer has verified all the process and there is still a suspect part on keycert.h.

    Could you provide a instruction on the process how to generate it step by step?

    Don't use script because customer private keys need to access from HSM machine so they need to break down the procedure and bind their key separately. 

    BR, Rich 

  • Hi Rich,

    I have created FAQ for the same, mentioning all steps, including steps to create keycert.

    Regards
    Diwakar

  • Diwakar, 

    Thanks for the FAQ, it does help and customer successful revoke key now. 

    OPTEE actually can send commend and certification to TIFS successfully but the certification was incorrect.  

    The gating point is actually the way customer keys which creates certification are store in HSM machine and all the script in FAQ are still based on keys store in local build machine.

    Customer has to tear down the script and re-create the way to decrypt and encrypt by retrieve their keys from HSM server to generate the certification. 

    The more scripts we use, the more teardown and re-write commends they need to implement.

    It takes long time to verify the feature which is originally verified. Just because the way which keys were used are not practical to customer.  

    Thanks for your assistant. We have to create a script or other way to hook with HSM machine so this will not be a customized task to customer again.  

    BR, Rich 

       

  • Hi Rich,

    The gating point is actually the way customer keys which creates certification are store in HSM machine and all the script in FAQ are still based on keys store in local build machine.

    TI always showcases a reference and uses the available TI Dummy Keys to demonstrate features.

    We cannot support any HS-SE devices in TI SDKs, if you are saying we should not be using any scripts. FWIW, all of TI's signing is based on standard openssl commands.

    Customer has to tear down the script and re-create the way to decrypt and encrypt by retrieve their keys from HSM server to generate the certification. 

    FWIW, this will always be the case. I am not sure what you are suggesting to be done here. The signing of images will always be dependent on the HSM server infrastructure that a customer has, and the interfaces their HSM server provides for performing various operations.

    We can only provide examples w.r.t the public SDK. 

    regards

    Suman