From patchwork Tue Sep 25 14:40:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 147474 Delivered-To: patches@linaro.org Received: by 2002:a2e:8595:0:0:0:0:0 with SMTP id b21-v6csp812642lji; Tue, 25 Sep 2018 07:40:46 -0700 (PDT) X-Received: by 2002:a2e:84c6:: with SMTP id q6-v6mr1267120ljh.65.1537886446034; Tue, 25 Sep 2018 07:40:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537886446; cv=none; d=google.com; s=arc-20160816; b=R9VpQxpINOtI0UkwUtqzk2ui1Zf2rt1vwr2T51DA1fYL257Ih0cgK/0U4dGcm8aDae SxjkRB7TymL21sz20y74LFT5H8v0cMQrjZcNZZ3vntBHetUtZj75/LHnpM3uKlYiHuZL aBXXsQfca+gZFP+6bPD7C1W+S0eHAkoKKxo7XPPH+wW7emrEZg6VP+6CKJtw305QoT+l dvkMSrmRQq6T1LKIcF2z5ktJIPzI/z8+Kgwfw+fBTD0RckNT/e/i37bAckvl9PoCA3OR UmS0WS/1JdcMHiSVP/Zdn38qpXpSPbleyfZOtPv7m41a1WYUvVnhaREm1r2DufnpcXcM eoWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=tBbBJe8/MVi9pxS8uyiw1IWis6hb4TT0xsmEuxzdBB8=; b=VXpPKpkU0eJb9Z8Yy7ApvZuva0XN0t1h3qB2GZ+PprBC0gadeQQVlYpyq65W/EoB72 gXTgsKqfQZd/9Oje07NKTf1D+crjIKwuSKSS9uYYYRfj47Ujp7QVDmiQAZBYYzBqH5Xp nD4UCiojfYGsaKp/GQFMYlUQGSiPdEsZNNDMpaEJVoJL2FI17k7hzCvkvEZd0/9GiUyC gjS9XQH9PGvCAfveRo28lYBiDUvgMNig6PMWennfkaz1xAlI37rP1OZqO1X66gsRCzI+ wn+uLZ3UH9PhTe2qqBEdacu6kkjJQTYNv34u7wPYeJ1ffBY8HnAwacKEPWdlSiApra/b j8lQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=MlF+Uy6d; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 209.85.220.41 as permitted sender) smtp.mailfrom=jens.wiklander@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id t18-v6sor1597994lje.37.2018.09.25.07.40.45 for (Google Transport Security); Tue, 25 Sep 2018 07:40:46 -0700 (PDT) Received-SPF: pass (google.com: domain of jens.wiklander@linaro.org designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=MlF+Uy6d; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 209.85.220.41 as permitted sender) smtp.mailfrom=jens.wiklander@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tBbBJe8/MVi9pxS8uyiw1IWis6hb4TT0xsmEuxzdBB8=; b=MlF+Uy6dMKjodMLb2CUo5erLgnCyDWSZyd0GskY8CcISP5SMh3RaH756r0KuIs8uLB od6segqAx3IoHndAlRZNnpYpNrHo61dPXdSiPbaRbZ3LJV6IiXnl1hybfPokWo7FIJb9 R10B/UGH3sT1V8oFFdlYurJcc2Jmv7aSUQguM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tBbBJe8/MVi9pxS8uyiw1IWis6hb4TT0xsmEuxzdBB8=; b=itLYZJVwhC8t/eXyMsd0yoThCtrAA29JPa+mqaRSFFiJtCdL0tE3Rkvcf9klZgW70s eALrNLFbU7dt8wcXzSM/oAP9cLPgjYm2EC3kvLyDYmQYaiA9wAWBuUgUDwojbF+vBBuv 9Nn046FniuL7XHljkGG/GVVlOdmNIk+gNFZtWexPgiuzw7w1mo6zfTL/bYvJiMvIpgdO CgkODtAh4S4JopLRrakb0hDrUWG8raP3a9UGLv5XqtoPKUM18gTuNjERMXzp35hD4ZXl c2Gc1DNU0Q16BpZHzQ0kVgXry48fHEkbJj9IW/qvKfK88Sh1dGtfaxCqHUcIX+t4ys7h 69Cg== X-Gm-Message-State: ABuFfoj0nPA8nf+33tJe7PAmuHnB4KTYXBlr7cJuganD2HKiN/uwVjen Hp5no+zytyF3U9Mch7yoWdjpRjEs X-Google-Smtp-Source: ACcGV62Nvthzlt0goc+4E1V5rfQcCRvqN0Ci7ubpZa9Jk5cFYTTGARpQbfTgkfk406ekQRsZXZZu8A== X-Received: by 2002:a2e:8807:: with SMTP id x7-v6mr1164114ljh.98.1537886445576; Tue, 25 Sep 2018 07:40:45 -0700 (PDT) Return-Path: Received: from jax.urgonet (h-84-105.A175.priv.bahnhof.se. [79.136.84.105]) by smtp.gmail.com with ESMTPSA id g14-v6sm14483lja.96.2018.09.25.07.40.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 25 Sep 2018 07:40:44 -0700 (PDT) From: Jens Wiklander To: u-boot@lists.denx.de Cc: Simon Glass , Igor Opaniuk , Tom Rini , Jaehoon Chung , Pierre Aubert , Albert Aribaud , Peter Griffin , Michal Simek , Jens Wiklander Subject: [PATCH v4 10/19] optee: support routing of rpmb data frames to mmc Date: Tue, 25 Sep 2018 16:40:14 +0200 Message-Id: <20180925144023.24555-11-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180925144023.24555-1-jens.wiklander@linaro.org> References: <20180925144023.24555-1-jens.wiklander@linaro.org> Adds support in optee supplicant to route signed (MACed) RPMB frames from OP-TEE Secure OS to MMC and vice versa to manipulate the RPMB partition. Tested-by: Igor Opaniuk Signed-off-by: Jens Wiklander --- drivers/tee/optee/Makefile | 1 + drivers/tee/optee/core.c | 8 ++ drivers/tee/optee/optee_private.h | 55 ++++++++- drivers/tee/optee/rpmb.c | 181 ++++++++++++++++++++++++++++++ drivers/tee/optee/supplicant.c | 3 + 5 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 drivers/tee/optee/rpmb.c -- 2.17.1 Reviewed-by: Simon Glass diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 6148feb474a5..928d3f80027f 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -2,3 +2,4 @@ obj-y += core.o obj-y += supplicant.o +obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 726382da9bb8..7f870f2f735d 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -315,6 +315,13 @@ static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg) param.a3 = res.a3; handle_rpc(dev, ¶m, &page_list); } else { + /* + * In case we've accessed RPMB to serve an RPC + * request we need to restore the previously + * selected partition as the caller may expect it + * to remain unchanged. + */ + optee_suppl_rpmb_release(dev); return call_err_to_res(res.a0); } } @@ -651,4 +658,5 @@ U_BOOT_DRIVER(optee) = { .probe = optee_probe, .ops = &optee_ops, .platdata_auto_alloc_size = sizeof(struct optee_pdata), + .priv_auto_alloc_size = sizeof(struct optee_private), }; diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 35adb83afcc7..9442d1c176bc 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -6,7 +6,60 @@ #ifndef __OPTEE_PRIVATE_H #define __OPTEE_PRIVATE_H +#include +#include + +/** + * struct optee_private - OP-TEE driver private data + * @rpmb_mmc: mmc device for the RPMB partition + * @rpmb_dev_id: mmc device id matching @rpmb_mmc + * @rpmb_original_part: the previosly active partition on the mmc device, + * used to restore active the partition when the RPMB + * accesses are finished + */ +struct optee_private { + struct mmc *rpmb_mmc; + int rpmb_dev_id; + int rpmb_original_part; +}; + +struct optee_msg_arg; + +void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg, + void **page_list); + +#ifdef CONFIG_SUPPORT_EMMC_RPMB +/** + * optee_suppl_cmd_rpmb() - route RPMB frames to mmc + * @dev: device with the selected RPMB partition + * @arg: OP-TEE message holding the frames to transmit to the mmc + * and space for the response frames. + * + * Routes signed (MACed) RPMB frames from OP-TEE Secure OS to MMC and vice + * versa to manipulate the RPMB partition. + */ +void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg); + +/** + * optee_suppl_rpmb_release() - release mmc device + * @dev: mmc device + * + * Releases the mmc device and restores the previously selected partition. + */ +void optee_suppl_rpmb_release(struct udevice *dev); +#else +static inline void optee_suppl_cmd_rpmb(struct udevice *dev, + struct optee_msg_arg *arg) +{ + debug("OPTEE_MSG_RPC_CMD_RPMB not implemented\n"); + arg->ret = TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline void optee_suppl_rpmb_release(struct udevice *dev) +{ +} +#endif + void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr); -void optee_suppl_cmd(struct udevice *dev, void *shm, void **page_list); #endif /* __OPTEE_PRIVATE_H */ diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c new file mode 100644 index 000000000000..955155b3f8b1 --- /dev/null +++ b/drivers/tee/optee/rpmb.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018 Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "optee_msg.h" +#include "optee_private.h" + +/* + * Request and response definitions must be in sync with the secure side of + * OP-TEE. + */ + +/* Request */ +struct rpmb_req { + u16 cmd; +#define RPMB_CMD_DATA_REQ 0x00 +#define RPMB_CMD_GET_DEV_INFO 0x01 + u16 dev_id; + u16 block_count; + /* Optional data frames (rpmb_data_frame) follow */ +}; + +#define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1)) + +/* Response to device info request */ +struct rpmb_dev_info { + u8 cid[16]; + u8 rpmb_size_mult; /* EXT CSD-slice 168: RPMB Size */ + u8 rel_wr_sec_c; /* EXT CSD-slice 222: Reliable Write Sector */ + /* Count */ + u8 ret_code; +#define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00 +#define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01 +}; + +static void release_mmc(struct optee_private *priv) +{ + int rc; + + if (!priv->rpmb_mmc) + return; + + rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id, + priv->rpmb_original_part); + if (rc) + debug("%s: blk_select_hwpart_devnum() failed: %d\n", + __func__, rc); + + priv->rpmb_mmc = NULL; +} + +static struct mmc *get_mmc(struct optee_private *priv, int dev_id) +{ + struct mmc *mmc; + int rc; + + if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id) + return priv->rpmb_mmc; + + release_mmc(priv); + + mmc = find_mmc_device(dev_id); + if (!mmc) { + debug("Cannot find RPMB device\n"); + return NULL; + } + if (!(mmc->version & MMC_VERSION_MMC)) { + debug("Device id %d is not an eMMC device\n", dev_id); + return NULL; + } + if (mmc->version < MMC_VERSION_4_41) { + debug("Device id %d: RPMB not supported before version 4.41\n", + dev_id); + return NULL; + } + + priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart; + + rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB); + if (rc) { + debug("Device id %d: cannot select RPMB partition: %d\n", + dev_id, rc); + return NULL; + } + + priv->rpmb_mmc = mmc; + priv->rpmb_dev_id = dev_id; + return mmc; +} + +static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info) +{ + struct mmc *mmc = find_mmc_device(dev_id); + + if (!mmc) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (!mmc->ext_csd) + return TEE_ERROR_GENERIC; + + memcpy(info->cid, mmc->cid, sizeof(info->cid)); + info->rel_wr_sec_c = mmc->ext_csd[222]; + info->rpmb_size_mult = mmc->ext_csd[168]; + info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK; + + return TEE_SUCCESS; +} + +static u32 rpmb_process_request(struct optee_private *priv, void *req, + ulong req_size, void *rsp, ulong rsp_size) +{ + struct rpmb_req *sreq = req; + struct mmc *mmc; + + if (req_size < sizeof(*sreq)) + return TEE_ERROR_BAD_PARAMETERS; + + switch (sreq->cmd) { + case RPMB_CMD_DATA_REQ: + mmc = get_mmc(priv, sreq->dev_id); + if (!mmc) + return TEE_ERROR_ITEM_NOT_FOUND; + if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req), + req_size - sizeof(struct rpmb_req), + rsp, rsp_size)) + return TEE_ERROR_BAD_PARAMETERS; + return TEE_SUCCESS; + + case RPMB_CMD_GET_DEV_INFO: + if (req_size != sizeof(struct rpmb_req) || + rsp_size != sizeof(struct rpmb_dev_info)) { + debug("Invalid req/rsp size\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + return rpmb_get_dev_info(sreq->dev_id, rsp); + + default: + debug("Unsupported RPMB command: %d\n", sreq->cmd); + return TEE_ERROR_BAD_PARAMETERS; + } +} + +void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg) +{ + struct tee_shm *req_shm; + struct tee_shm *rsp_shm; + void *req_buf; + void *rsp_buf; + ulong req_size; + ulong rsp_size; + + if (arg->num_params != 2 || + arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT || + arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) { + arg->ret = TEE_ERROR_BAD_PARAMETERS; + return; + } + + req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref; + req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs; + req_size = arg->params[0].u.rmem.size; + + rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref; + rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs; + rsp_size = arg->params[1].u.rmem.size; + + arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size, + rsp_buf, rsp_size); +} + +void optee_suppl_rpmb_release(struct udevice *dev) +{ + release_mmc(dev_get_priv(dev)); +} diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c index 2239b1bf7b37..b1ea65bdb2e3 100644 --- a/drivers/tee/optee/supplicant.c +++ b/drivers/tee/optee/supplicant.c @@ -85,6 +85,9 @@ void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg, debug("OPTEE_MSG_RPC_CMD_FS not implemented\n"); arg->ret = TEE_ERROR_NOT_IMPLEMENTED; break; + case OPTEE_MSG_RPC_CMD_RPMB: + optee_suppl_cmd_rpmb(dev, arg); + break; default: arg->ret = TEE_ERROR_NOT_IMPLEMENTED; }