Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  stm32-bsec-optee-ta.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver
 *
 * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
 */


#include <linux/tee_drv.h>

#include "stm32-bsec-optee-ta.h"

/*
 * Read OTP memory
 *
 * [in] value[0].a OTP start offset in byte
 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
 * [out] memref[1].buffer Output buffer to store read values
 * [out] memref[1].size Size of OTP to be read
 *
 * Return codes:
 * TEE_SUCCESS - Invoke command success
 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
 */

#define PTA_BSEC_READ_MEM  0x0

/*
 * Write OTP memory
 *
 * [in] value[0].a OTP start offset in byte
 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
 * [in] memref[1].buffer Input buffer to read values
 * [in] memref[1].size Size of OTP to be written
 *
 * Return codes:
 * TEE_SUCCESS - Invoke command success
 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
 */

#define PTA_BSEC_WRITE_MEM  0x1

/* value of PTA_BSEC access type = value[in] b */
#define SHADOW_ACCESS 0
#define FUSE_ACCESS 1
#define LOCK_ACCESS 2

/* Bitfield definition for LOCK status */
#define LOCK_PERM   BIT(30)

/* OP-TEE STM32MP BSEC TA UUID */
static const uuid_t stm32mp_bsec_ta_uuid =
 UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5,
    0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03);

/*
 * Check whether this driver supports the BSEC TA in the TEE instance
 * represented by the params (ver/data) to this function.
 */

static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver,
         const void *data)
{
 /* Currently this driver only supports GP compliant, OP-TEE based TA */
 if ((ver->impl_id == TEE_IMPL_ID_OPTEE) &&
  (ver->gen_caps & TEE_GEN_CAP_GP))
  return 1;
 else
  return 0;
}

/* Open a session to OP-TEE for STM32MP BSEC TA */
static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id)
{
 struct tee_ioctl_open_session_arg sess_arg;
 int rc;

 memset(&sess_arg, 0, sizeof(sess_arg));
 export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid);
 sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
 sess_arg.num_params = 0;

 rc = tee_client_open_session(ctx, &sess_arg, NULL);
 if ((rc < 0) || (sess_arg.ret != 0)) {
  pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n",
         __func__, sess_arg.ret, rc);
  if (!rc)
   rc = -EINVAL;
 } else {
  *id = sess_arg.session;
 }

 return rc;
}

/* close a session to OP-TEE for STM32MP BSEC TA */
static void stm32_bsec_ta_close_session(void *ctx, u32 id)
{
 tee_client_close_session(ctx, id);
}

/* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */
int stm32_bsec_optee_ta_open(struct tee_context **ctx)
{
 struct tee_context *tee_ctx;
 u32 session_id;
 int rc;

 /* Open context with TEE driver */
 tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL);
 if (IS_ERR(tee_ctx)) {
  rc = PTR_ERR(tee_ctx);
  if (rc == -ENOENT)
   return -EPROBE_DEFER;
  pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc);

  return rc;
 }

 /* Check STM32MP BSEC TA presence */
 rc = stm32_bsec_ta_open_session(tee_ctx, &session_id);
 if (rc) {
  tee_client_close_context(tee_ctx);
  return rc;
 }

 stm32_bsec_ta_close_session(tee_ctx, session_id);

 *ctx = tee_ctx;

 return 0;
}

/* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */
void stm32_bsec_optee_ta_close(void *ctx)
{
 tee_client_close_context(ctx);
}

/* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */
int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
        void *buf, size_t bytes)
{
 struct tee_shm *shm;
 struct tee_ioctl_invoke_arg arg;
 struct tee_param param[2];
 u8 *shm_buf;
 u32 start, num_bytes;
 int ret;
 u32 session_id;

 ret = stm32_bsec_ta_open_session(ctx, &session_id);
 if (ret)
  return ret;

 memset(&arg, 0, sizeof(arg));
 memset(¶m, 0, sizeof(param));

 arg.func = PTA_BSEC_READ_MEM;
 arg.session = session_id;
 arg.num_params = 2;

 /* align access on 32bits */
 start = ALIGN_DOWN(offset, 4);
 num_bytes = round_up(offset + bytes - start, 4);
 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
 param[0].u.value.a = start;
 param[0].u.value.b = SHADOW_ACCESS;

 shm = tee_shm_alloc_kernel_buf(ctx, num_bytes);
 if (IS_ERR(shm)) {
  ret = PTR_ERR(shm);
  goto out_tee_session;
 }

 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
 param[1].u.memref.shm = shm;
 param[1].u.memref.size = num_bytes;

 ret = tee_client_invoke_func(ctx, &arg, param);
 if (ret < 0 || arg.ret != 0) {
  pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n",
   arg.ret, ret);
  if (!ret)
   ret = -EIO;
 }
 if (!ret) {
  shm_buf = tee_shm_get_va(shm, 0);
  if (IS_ERR(shm_buf)) {
   ret = PTR_ERR(shm_buf);
   pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
  } else {
   /* read data from 32 bits aligned buffer */
   memcpy(buf, &shm_buf[offset % 4], bytes);
  }
 }

 tee_shm_free(shm);

out_tee_session:
 stm32_bsec_ta_close_session(ctx, session_id);

 return ret;
}

/* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */
int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
         unsigned int offset, void *buf, size_t bytes)
struct tee_shm *shm;
 struct tee_ioctl_invoke_arg arg;
 struct tee_param param[2];
 u8 *shm_buf;
 int ret;
 u32 session_id;

 ret = stm32_bsec_ta_open_session(ctx, &session_id);
 if (ret)
  return ret;

 /* Allow only writing complete 32-bits aligned words */
 if ((bytes % 4) || (offset % 4))
  return -EINVAL;

 memset(&arg, 0, sizeof(arg));
 memset(¶m, 0, sizeof(param));

 arg.func = PTA_BSEC_WRITE_MEM;
 arg.session = session_id;
 arg.num_params = 2;

 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
 param[0].u.value.a = offset;
 param[0].u.value.b = FUSE_ACCESS;

 shm = tee_shm_alloc_kernel_buf(ctx, bytes);
 if (IS_ERR(shm)) {
  ret = PTR_ERR(shm);
  goto out_tee_session;
 }

 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
 param[1].u.memref.shm = shm;
 param[1].u.memref.size = bytes;

 shm_buf = tee_shm_get_va(shm, 0);
 if (IS_ERR(shm_buf)) {
  ret = PTR_ERR(shm_buf);
  pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
  tee_shm_free(shm);

  goto out_tee_session;
 }

 memcpy(shm_buf, buf, bytes);

 ret = tee_client_invoke_func(ctx, &arg, param);
 if (ret < 0 || arg.ret != 0) {
  pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
  if (!ret)
   ret = -EIO;
 }
 pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret);

 /* Lock the upper OTPs with ECC protection, word programming only */
 if (!ret && ((offset + bytes) >= (lower * 4))) {
  u32 start, nb_lock;
  u32 *lock = (u32 *)shm_buf;
  int i;

  /*
 * don't lock the lower OTPs, no ECC protection and incremental
 * bit programming, a second write is allowed
 */

  start = max_t(u32, offset, lower * 4);
  nb_lock = (offset + bytes - start) / 4;

  param[0].u.value.a = start;
  param[0].u.value.b = LOCK_ACCESS;
  param[1].u.memref.size = nb_lock * 4;

  for (i = 0; i < nb_lock; i++)
   lock[i] = LOCK_PERM;

  ret = tee_client_invoke_func(ctx, &arg, param);
  if (ret < 0 || arg.ret != 0) {
   pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
   if (!ret)
    ret = -EIO;
  }
  pr_debug("Lock upper OTPs %d to %d, ret=%d\n",
    start / 4, start / 4 + nb_lock, ret);
 }

 tee_shm_free(shm);

out_tee_session:
 stm32_bsec_ta_close_session(ctx, session_id);

 return ret;
}

Messung V0.5
C=88 H=93 G=90

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge