All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Tomas Winkler <tomas.winkler@intel.com>
Cc: "Ulf Hansson" <ulf.hansson@linaro.org>,
	"Adrian Hunter" <adrian.hunter@intel.com>,
	"James Bottomley" <James.Bottomley@HansenPartnership.com>,
	"Martin K. Petersen" <martin.petersen@oracle.com>,
	"Vinayak Holikatti" <vinholikatti@gmail.com>,
	"Andy Lutomirski" <luto@kernel.org>,
	"Arve Hjønnevåg" <arve@android.com>,
	"Michael Ryleev" <gmar@google.com>,
	"Joao Pinto" <Joao.Pinto@synopsys.com>,
	"Christoph Hellwig" <hch@lst.de>,
	"Yaniv Gardi" <ygardi@codeaurora.org>,
	linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org,
	linux-scsi@vger.kernel.org
Subject: Re: [PATCH v5 5/8] char: rpmb: add RPMB simulation device
Date: Wed, 31 Aug 2016 12:58:45 +0200	[thread overview]
Message-ID: <20160831105845.GE10180@kroah.com> (raw)
In-Reply-To: <1468873673-21776-6-git-send-email-tomas.winkler@intel.com>

On Mon, Jul 18, 2016 at 11:27:50PM +0300, Tomas Winkler wrote:
> This is a simple platform device used for testing
> the RPMB subsystem.
> 
> The module currently supports two configuration options:
> 1. max_wr_blks: for specifying max blocks that can be written
> in a single command
> 2. daunits:  used to set storage capacity in 128K units.
> 
> 
> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
> ---
> V2: remove .owner setting, it is set automatically
> V3: 1. Add shutdown handler (similar to ufshcd)
>     2. Commit message fix
> V4: Use select RPMB in Kconfg to ensure valid configuration.
> V5: Revamp the code using the sequence command.
> 
>  drivers/char/rpmb/Kconfig    |  10 +
>  drivers/char/rpmb/Makefile   |   1 +
>  drivers/char/rpmb/rpmb_sim.c | 668 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 679 insertions(+)
>  create mode 100644 drivers/char/rpmb/rpmb_sim.c
> 
> diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
> index 6794be9fcc5e..c21b3934249f 100644
> --- a/drivers/char/rpmb/Kconfig
> +++ b/drivers/char/rpmb/Kconfig
> @@ -13,3 +13,13 @@ config RPMB_INTF_DEV
>  	help
>  	  Say yes here if you want to access RPMB from user space
>  	  via character device interface /dev/rpmb%d
> +
> +
> +config RPMB_SIM
> +	tristate "RPMB partition device simulator"
> +	default n
> +	select RPMB
> +	select CRYPTO_SHA256
> +	select CRYPTO_HMAC
> +	help
> +	  RPMB partition simulator used for testing the RPMB subsystem
> diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
> index b5dc087b1299..81f924fd9a87 100644
> --- a/drivers/char/rpmb/Makefile
> +++ b/drivers/char/rpmb/Makefile
> @@ -1,5 +1,6 @@
>  obj-$(CONFIG_RPMB) += rpmb.o
>  rpmb-objs += core.o
>  rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
> +obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
>  
>  ccflags-y += -D__CHECK_ENDIAN__
> diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
> new file mode 100644
> index 000000000000..e33f6809ae2c
> --- /dev/null
> +++ b/drivers/char/rpmb/rpmb_sim.c
> @@ -0,0 +1,668 @@
> +/******************************************************************************
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright(c) 2016 Intel Corporation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * The full GNU General Public License is included in this distribution
> + * in the file called LICENSE.GPL.
> + *
> + * Contact Information:
> + *	Intel Corporation.
> + *	linux-mei@linux.intel.com
> + *	http://www.intel.com
> + *
> + * BSD LICENSE
> + *
> + * Copyright(c) 2016 Intel Corporation. All rights reserved.
> + * All rights reserved.
> + *
> + * 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 Intel Corporation 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 <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/device.h>
> +#include <crypto/hash.h>
> +#include <linux/scatterlist.h>
> +#include <linux/sizes.h>
> +
> +#include <linux/rpmb.h>
> +
> +static const char id[] = "RPMB:SIM";
> +#define CAPACITY_UNIT SZ_128K
> +#define CAPACITY_MIN  SZ_128K
> +#define CAPACITY_MAX  SZ_16M
> +#define BLK_UNIT      SZ_256
> +
> +static unsigned int max_wr_blks = 1;
> +module_param(max_wr_blks, uint, 0644);
> +MODULE_PARM_DESC(max_wr_blks, "max blocks that can be written in a single command (default: 1)");
> +
> +static unsigned int daunits = 1;
> +module_param(daunits, uint, 0644);
> +MODULE_PARM_DESC(daunits, "number of data area units of 128K (default: 1)");
> +
> +struct blk {
> +	u8 data[BLK_UNIT];
> +};
> +
> +/**
> + * struct rpmb_sim_dev
> + *
> + * @dev:  back pointer to the platform device
> + * @rdev: rpmb device
> + * @auth_key: Authentication key register which is used to authenticate
> + *            accesses when MAC is calculated;
> + * @auth_key_set: true if auth key was set
> + * @write_counter: Counter value for the total amount of successful
> + *             authenticated data write requests made by the host.
> + *             The initial value of this register after production is 00000000h.
> + *             The value will be incremented by one along with each successful
> + *             programming access. The value cannot be reset. After the counter
> + *             has reached the maximum value of FFFFFFFFh,
> + *             it will not be incremented anymore (overflow prevention)
> + * @hash_tfm:  hmac(sha256) tfm
> + *
> + * @res_frames: frame that holds the result of the last write operation
> + * @out_frames: next read operation result frames
> + * @out_frames_cnt: number of the output frames
> + *
> + * @capacity: size of the partition in bytes multiple of 128K
> + * @blkcnt:   block count
> + * @da:       data area in blocks
> + */
> +struct rpmb_sim_dev {
> +	struct device *dev;
> +	struct rpmb_dev *rdev;
> +	u8 auth_key[32];
> +	bool auth_key_set;
> +	u32 write_counter;
> +	struct crypto_shash *hash_tfm;
> +
> +	struct rpmb_frame res_frames[1];
> +	struct rpmb_frame *out_frames;
> +	unsigned int out_frames_cnt;
> +
> +	size_t capacity;
> +	size_t blkcnt;
> +	struct blk *da;
> +};
> +
> +static __be16 op_result(struct rpmb_sim_dev *rsdev, u16 result)
> +{
> +	if (!rsdev->auth_key_set)
> +		return cpu_to_be16(RPMB_ERR_NO_KEY);
> +
> +	if (rsdev->write_counter == 0xFFFFFFFF)
> +		result |=  RPMB_ERR_COUNTER_EXPIRED;
> +
> +	return cpu_to_be16(result);
> +}
> +
> +static __be16 req_to_resp(u16 req)
> +{
> +	return cpu_to_be16(RPMB_REQ2RESP(req));
> +}
> +
> +static int rpmb_sim_calc_hmac(struct rpmb_sim_dev *rsdev,
> +			      struct rpmb_frame *frames,
> +			      unsigned int blks, u8 *mac)
> +{
> +	SHASH_DESC_ON_STACK(desc, rsdev->hash_tfm);
> +	int i;
> +	int ret;
> +
> +	desc->tfm = rsdev->hash_tfm;
> +	desc->flags = 0;
> +
> +	ret = crypto_shash_init(desc);
> +	if (ret)
> +		goto out;
> +
> +	for (i = 0; i < blks; i++) {
> +		ret = crypto_shash_update(desc, frames[i].data, hmac_data_len);
> +		if (ret)
> +			goto out;
> +	}
> +	ret = crypto_shash_final(desc, mac);
> +out:
> +	if (ret)
> +		dev_err(rsdev->dev, "digest error = %d", ret);
> +
> +	return ret;
> +}
> +
> +static int rpmb_op_not_programmed(struct rpmb_sim_dev *rsdev, u16 req)
> +{
> +	struct rpmb_frame *res_frame = rsdev->res_frames;
> +
> +	res_frame->req_resp = req_to_resp(req);
> +	res_frame->result = op_result(rsdev, RPMB_ERR_NO_KEY);
> +
> +	dev_err(rsdev->dev, "not programmed\n");
> +
> +	return 0;
> +}
> +
> +static int rpmb_op_program_key(struct rpmb_sim_dev *rsdev,
> +			       struct rpmb_frame *in_frame, u32 cnt)
> +{
> +	struct rpmb_frame *res_frame = rsdev->res_frames;
> +	u16 req;
> +	int ret;
> +	u16 err = RPMB_ERR_OK;
> +
> +	req = be16_to_cpu(in_frame[0].req_resp);
> +
> +	if (req != RPMB_PROGRAM_KEY)
> +		return -EINVAL;
> +
> +	if (cnt != 1)
> +		return -EINVAL;
> +
> +	if (rsdev->auth_key_set) {
> +		dev_err(rsdev->dev, "key allread set\n");
> +		err = RPMB_ERR_WRITE;
> +		goto out;
> +	}
> +
> +	ret = crypto_shash_setkey(rsdev->hash_tfm, in_frame[0].key_mac, 32);
> +	if (ret) {
> +		dev_err(rsdev->dev, "set key failed = %d\n", ret);
> +		err = RPMB_ERR_GENERAL;
> +		goto out;
> +	}
> +
> +	dev_dbg(rsdev->dev, "digest size %u\n",
> +		crypto_shash_digestsize(rsdev->hash_tfm));
> +
> +	memcpy(rsdev->auth_key, in_frame[0].key_mac, 32);
> +	rsdev->auth_key_set = true;
> +out:
> +
> +	memset(res_frame, 0, sizeof(struct rpmb_frame));
> +	res_frame->req_resp = req_to_resp(req);
> +	res_frame->result = op_result(rsdev, err);
> +
> +	return 0;
> +}
> +
> +static int rpmb_op_get_wr_counter(struct rpmb_sim_dev *rsdev,
> +				  struct rpmb_frame *in_frame, u32 cnt)
> +{
> +	struct rpmb_frame *frame;
> +	int ret = 0;
> +	u16 req;
> +	u16 err;
> +
> +	req = be16_to_cpu(in_frame[0].req_resp);
> +	if (req != RPMB_GET_WRITE_COUNTER)
> +		return -EINVAL;
> +
> +	if (cnt != 1)
> +		return -EINVAL;
> +
> +	frame = kcalloc(1, sizeof(struct rpmb_frame), GFP_KERNEL);
> +	if (!frame) {
> +		err = RPMB_ERR_READ;
> +		ret = -ENOMEM;
> +		rsdev->out_frames = rsdev->res_frames;
> +		rsdev->out_frames_cnt = cnt;
> +		goto out;
> +	}
> +
> +	rsdev->out_frames = frame;
> +	rsdev->out_frames_cnt = cnt;
> +
> +	frame->req_resp = req_to_resp(req);
> +	frame->write_counter = cpu_to_be32(rsdev->write_counter);
> +	memcpy(frame->nonce, in_frame[0].nonce, 16);
> +
> +	err = RPMB_ERR_OK;
> +	if (rpmb_sim_calc_hmac(rsdev, frame, cnt, frame->key_mac))
> +		err = RPMB_ERR_READ;
> +
> +out:
> +	rsdev->out_frames[0].req_resp = req_to_resp(req);
> +	rsdev->out_frames[0].result = op_result(rsdev, err);
> +
> +	return ret;
> +}
> +
> +static int rpmb_op_write_data(struct rpmb_sim_dev *rsdev,
> +			      struct rpmb_frame *in_frame, u32 cnt)
> +{
> +	struct rpmb_frame *res_frame = rsdev->res_frames;
> +	u8 mac[32];
> +	u16 req, err, addr, blks;
> +	unsigned int i;
> +	int ret = 0;
> +
> +	req = be16_to_cpu(in_frame[0].req_resp);
> +	if (req != RPMB_WRITE_DATA)
> +		return -EINVAL;
> +
> +	if (rsdev->write_counter == 0xFFFFFFFF) {
> +		err = RPMB_ERR_WRITE;
> +		goto out;
> +	}
> +
> +	blks = be16_to_cpu(in_frame[0].block_count);
> +	if (blks == 0 || blks > cnt) {
> +		ret = -EINVAL;
> +		err = RPMB_ERR_GENERAL;
> +		goto out;
> +	}
> +
> +	if (blks > max_wr_blks) {
> +		err = RPMB_ERR_WRITE;
> +		goto out;
> +	}
> +
> +	addr = be16_to_cpu(in_frame[0].addr);
> +	if (addr >= rsdev->blkcnt) {
> +		err = RPMB_ERR_ADDRESS;
> +		goto out;
> +	}
> +
> +	if (rpmb_sim_calc_hmac(rsdev, in_frame, blks, mac)) {
> +		err = RPMB_ERR_AUTH;
> +		goto out;
> +	}
> +
> +	/* mac is in the last frame */
> +	if (memcmp(mac, in_frame[blks - 1].key_mac, sizeof(mac)) != 0) {
> +		err = RPMB_ERR_AUTH;
> +		goto out;
> +	}
> +
> +	if (be32_to_cpu(in_frame[0].write_counter) != rsdev->write_counter) {
> +		err = RPMB_ERR_COUNTER;
> +		goto out;
> +	}
> +
> +	if (addr + blks > rsdev->blkcnt) {
> +		err = RPMB_ERR_WRITE;
> +		goto out;
> +	}
> +
> +	err = RPMB_ERR_OK;
> +	for (i = 0; i < blks; i++)
> +		memcpy(rsdev->da[addr + i].data, in_frame[i].data, BLK_UNIT);
> +
> +	rsdev->write_counter++;
> +
> +out:
> +	memset(res_frame, 0, sizeof(struct rpmb_frame));
> +	if (err == RPMB_ERR_OK) {
> +		res_frame->write_counter = cpu_to_be32(rsdev->write_counter);
> +		memcpy(res_frame->key_mac, mac, sizeof(mac));
> +	}
> +	res_frame->req_resp = req_to_resp(req);
> +	res_frame->result = op_result(rsdev, err);
> +
> +	return ret;
> +}
> +
> +static int rpmb_op_read_data(struct rpmb_sim_dev *rsdev,
> +			     struct rpmb_frame *in_frame, u32 cnt)
> +{
> +	struct rpmb_frame *res_frame = rsdev->res_frames;
> +	struct rpmb_frame *out_frame;
> +	u8 mac[32];
> +	u16 req, err, addr, blks;
> +	unsigned int i;
> +	int ret;
> +
> +	req = be16_to_cpu(in_frame[0].req_resp);
> +	if (req != RPMB_READ_DATA)
> +		return -EINVAL;
> +
> +	out_frame = kcalloc(cnt, sizeof(struct rpmb_frame), GFP_KERNEL);
> +	if (!out_frame) {
> +		ret = -ENOMEM;
> +		err = RPMB_ERR_READ;
> +		goto out;
> +	}
> +
> +	blks = be16_to_cpu(in_frame[0].block_count);
> +	if (blks == 0 || blks > cnt) {
> +		ret = -EINVAL;
> +		err = RPMB_ERR_READ;
> +		goto out;
> +	}
> +
> +	ret = 0;
> +	addr = be16_to_cpu(in_frame[0].addr);
> +	if (addr >= rsdev->blkcnt) {
> +		err = RPMB_ERR_ADDRESS;
> +		goto out;
> +	}
> +
> +	if (addr + blks > rsdev->blkcnt) {
> +		err = RPMB_ERR_READ;
> +		goto out;
> +	}
> +
> +	for (i = 0; i < blks; i++) {
> +		memcpy(out_frame[i].data, rsdev->da[addr + i].data, BLK_UNIT);
> +		memcpy(out_frame[i].nonce, in_frame[0].nonce, 16);
> +		out_frame[i].req_resp = req_to_resp(req);
> +		out_frame[i].addr = in_frame[0].addr;
> +		out_frame[i].block_count = cpu_to_be16(blks);
> +	}
> +
> +	if (rpmb_sim_calc_hmac(rsdev, out_frame, blks, mac)) {
> +		err = RPMB_ERR_AUTH;
> +		goto out;
> +	}
> +
> +	memcpy(out_frame[blks - 1].key_mac, mac, sizeof(mac));
> +
> +	err = RPMB_ERR_OK;
> +	out_frame[0].result = op_result(rsdev, err);
> +
> +	rsdev->out_frames = out_frame;
> +	rsdev->out_frames_cnt = cnt;
> +
> +out:
> +	memset(res_frame, 0, sizeof(struct rpmb_frame));
> +	res_frame->req_resp = req_to_resp(req);
> +	res_frame->result = op_result(rsdev, err);
> +	if (err != RPMB_ERR_OK) {
> +		kfree(out_frame);
> +		rsdev->out_frames = res_frame;
> +		rsdev->out_frames_cnt = 1;
> +	}
> +
> +	return ret;
> +}
> +
> +static int rpmb_op_result_read(struct rpmb_sim_dev *rsdev,
> +			       struct rpmb_frame *frames, u32 cnt)
> +{
> +	u16 req = be16_to_cpu(frames[0].req_resp);
> +	u16 blks = be16_to_cpu(frames[0].block_count);
> +
> +	if (req != RPMB_RESULT_READ)
> +		return -EINVAL;
> +
> +	if (blks != 0)
> +		return -EINVAL;
> +
> +	rsdev->out_frames = rsdev->res_frames;
> +	rsdev->out_frames_cnt = 1;
> +	return 0;
> +}
> +
> +static int rpmb_sim_write(struct rpmb_sim_dev *rsdev,
> +			  struct rpmb_frame *frames, u32 cnt)
> +{
> +	u16 req;
> +	int ret;
> +
> +	if (!frames || !cnt)
> +		return -EINVAL;
> +
> +	req = be16_to_cpu(frames[0].req_resp);
> +	if (!rsdev->auth_key_set && req != RPMB_PROGRAM_KEY)
> +		return rpmb_op_not_programmed(rsdev, req);
> +
> +	switch (req) {
> +	case RPMB_PROGRAM_KEY:
> +		dev_dbg(rsdev->dev, "rpmb: program key\n");
> +		ret = rpmb_op_program_key(rsdev, frames, cnt);
> +		break;
> +	case RPMB_WRITE_DATA:
> +		dev_dbg(rsdev->dev, "rpmb: write data\n");
> +		ret = rpmb_op_write_data(rsdev, frames, cnt);
> +		break;
> +	case RPMB_GET_WRITE_COUNTER:
> +		dev_dbg(rsdev->dev, "rpmb: get write counter\n");
> +		ret = rpmb_op_get_wr_counter(rsdev, frames, cnt);
> +		break;
> +	case RPMB_READ_DATA:
> +		dev_dbg(rsdev->dev, "rpmb: read data\n");
> +		ret = rpmb_op_read_data(rsdev, frames, cnt);
> +		break;
> +	case RPMB_RESULT_READ:
> +		dev_dbg(rsdev->dev, "rpmb: result read\n");
> +		ret = rpmb_op_result_read(rsdev, frames, cnt);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	dev_dbg(rsdev->dev, "rpmb: ret=%d\n", ret);
> +
> +	return ret;
> +}
> +
> +static int rpmb_sim_read(struct rpmb_sim_dev *rsdev,
> +			 struct rpmb_frame *frames, u32 cnt)
> +{
> +	int i;
> +
> +	if (!frames || !cnt)
> +		return -EINVAL;
> +
> +	if (!rsdev->out_frames || rsdev->out_frames_cnt == 0) {
> +		dev_err(rsdev->dev, "out_frames are not set\n");
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < min_t(u32, rsdev->out_frames_cnt, cnt); i++)
> +		memcpy(frames, rsdev->out_frames, sizeof(struct rpmb_frame));
> +
> +	if (rsdev->out_frames != rsdev->res_frames)
> +		kfree(rsdev->out_frames);
> +
> +	rsdev->out_frames = NULL;
> +	rsdev->out_frames_cnt = 0;
> +	dev_dbg(rsdev->dev, "rpmb: cnt=%d\n", cnt);
> +
> +	return 0;
> +}
> +
> +static int rpmb_sim_cmd_seq(struct device *dev,
> +			    struct rpmb_cmd *cmds, u32 ncmds)
> +{
> +	struct platform_device *pdev;
> +	struct rpmb_sim_dev *rsdev;
> +	int i;
> +	int ret;
> +	struct rpmb_cmd *cmd;
> +
> +	if (!dev)
> +		return -EINVAL;
> +
> +	pdev = to_platform_device(dev);
> +	rsdev = platform_get_drvdata(pdev);
> +
> +	if (!rsdev)
> +		return -EINVAL;
> +
> +	for (ret = 0, i = 0; i < ncmds && !ret; i++) {
> +		cmd = &cmds[i];
> +		if (cmd->flags & RPMB_F_WRITE)
> +			ret = rpmb_sim_write(rsdev, cmd->frames, cmd->nframes);
> +		else
> +			ret = rpmb_sim_read(rsdev, cmd->frames, cmd->nframes);
> +	}
> +	return ret;
> +}
> +
> +static struct rpmb_ops rpmb_sim_ops = {
> +	.cmd_seq = rpmb_sim_cmd_seq,
> +	.type = RPMB_TYPE_EMMC,
> +};
> +
> +static int rpmb_sim_hmac_256_alloc(struct rpmb_sim_dev *rsdev)
> +{
> +	struct crypto_shash *hash_tfm;
> +
> +	hash_tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
> +	if (IS_ERR(hash_tfm))
> +		return PTR_ERR(hash_tfm);
> +
> +	rsdev->hash_tfm = hash_tfm;
> +
> +	dev_dbg(rsdev->dev, "hamac(sha256) registered\n");
> +	return 0;
> +}
> +
> +static void rpmb_sim_hmac_256_free(struct rpmb_sim_dev *rsdev)
> +{
> +	if (rsdev->hash_tfm)
> +		crypto_free_shash(rsdev->hash_tfm);
> +
> +	rsdev->hash_tfm = NULL;
> +}
> +
> +static int rpmb_sim_probe(struct platform_device *pdev)
> +{
> +	struct rpmb_sim_dev *rsdev;
> +	int ret;
> +
> +	rsdev = kzalloc(sizeof(*rsdev), GFP_KERNEL);
> +	if (!rsdev)
> +		return -ENOMEM;
> +
> +	rsdev->dev = &pdev->dev;
> +
> +	ret = rpmb_sim_hmac_256_alloc(rsdev);
> +	if (ret)
> +		goto err;
> +
> +	rsdev->capacity = CAPACITY_UNIT * daunits;
> +	rsdev->blkcnt  = rsdev->capacity / BLK_UNIT;
> +	rsdev->da = kzalloc(rsdev->capacity, GFP_KERNEL);
> +	if (!rsdev->da) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	rpmb_sim_ops.dev_id_len = strlen(id);
> +	rpmb_sim_ops.dev_id = id;
> +	rpmb_sim_ops.reliable_wr_cnt = max_wr_blks;
> +
> +	rsdev->rdev = rpmb_dev_register(rsdev->dev, &rpmb_sim_ops);
> +	if (IS_ERR(rsdev->rdev)) {
> +		ret = PTR_ERR(rsdev->rdev);
> +		goto err;
> +	}
> +
> +	dev_info(&pdev->dev, "registered RPMB capacity = %zu of %zu blocks\n",
> +		 rsdev->capacity, rsdev->blkcnt);
> +
> +	platform_set_drvdata(pdev, rsdev);
> +
> +	return 0;
> +err:
> +	rpmb_sim_hmac_256_free(rsdev);
> +	if (rsdev)
> +		kfree(rsdev->da);
> +	kfree(rsdev);
> +	return ret;
> +}
> +
> +static int rpmb_sim_remove(struct platform_device *pdev)
> +{
> +	struct rpmb_sim_dev *rsdev;
> +
> +	rsdev = platform_get_drvdata(pdev);
> +
> +	rpmb_dev_unregister(rsdev->dev);
> +
> +	platform_set_drvdata(pdev, NULL);
> +
> +	rpmb_sim_hmac_256_free(rsdev);
> +
> +	kfree(rsdev->da);
> +	kfree(rsdev);
> +	return 0;
> +}
> +
> +static void rpmb_sim_shutdown(struct platform_device *pdev)
> +{
> +	rpmb_sim_remove(pdev);
> +}
> +
> +static struct platform_driver rpmb_sim_driver = {
> +	.driver = {
> +		.name  = "rpmb_sim",
> +	},
> +	.probe         = rpmb_sim_probe,
> +	.remove        = rpmb_sim_remove,
> +	.shutdown      = rpmb_sim_shutdown,
> +};
> +
> +static struct platform_device *rpmb_sim_pdev;

A platform device?  Ick, no please don't abuse that interface for this
type of thing.  Make it a real device if you have one, and put it in the
proper place.  If it's a "virtual" device, great, use that.  But don't
make something up like this please.

thanks,

greg k-h

  parent reply	other threads:[~2016-08-31 10:58 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-18 20:27 [PATCH v5 0/8] Replay Protected Memory Block (RPMB) subsystem Tomas Winkler
2016-07-18 20:27 ` [PATCH v5 1/8] rpmb: add " Tomas Winkler
2016-07-18 20:27 ` [PATCH v5 2/8] char: rpmb: add sysfs-class ABI documentation Tomas Winkler
2016-08-31 10:53   ` Greg Kroah-Hartman
2016-07-18 20:27 ` [PATCH v5 3/8] char: rpmb: add device attributes Tomas Winkler
2016-08-31 10:56   ` Greg Kroah-Hartman
2016-09-01 20:21     ` Winkler, Tomas
2016-07-18 20:27 ` [PATCH v5 4/8] char: rpmb: provide a user space interface Tomas Winkler
2016-07-18 22:15   ` Paul Gortmaker
2016-07-20  9:02     ` Winkler, Tomas
2016-07-20 14:21       ` Paul Gortmaker
2016-08-05 20:08   ` Pavel Machek
2016-08-07  9:44     ` Winkler, Tomas
2016-08-31 10:49       ` Greg Kroah-Hartman
2016-09-01 20:05         ` Winkler, Tomas
2016-09-01 20:46           ` Greg Kroah-Hartman
2016-09-04 11:35             ` Winkler, Tomas
2016-09-04 20:20               ` Pavel Machek
2016-09-04 20:56                 ` Winkler, Tomas
2016-07-18 20:27 ` [PATCH v5 5/8] char: rpmb: add RPMB simulation device Tomas Winkler
2016-08-31 10:57   ` Greg Kroah-Hartman
2016-08-31 10:58   ` Greg Kroah-Hartman [this message]
2016-09-01 20:25     ` Winkler, Tomas
2016-09-01 20:45       ` Greg Kroah-Hartman
2016-07-18 20:27 ` [PATCH v5 6/8] tools rpmb: add RPBM access tool Tomas Winkler
2016-07-18 20:27 ` [PATCH v5 7/8] mmc: block: register RPMB partition with the RPMB subsystem Tomas Winkler
2016-07-18 20:27 ` [PATCH v5 8/8] scsi: ufs: connect to " Tomas Winkler
2016-07-23  7:44 ` [PATCH v5 0/8] Replay Protected Memory Block (RPMB) subsystem Winkler, Tomas
2016-08-05 20:06 ` Pavel Machek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160831105845.GE10180@kroah.com \
    --to=gregkh@linuxfoundation.org \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=Joao.Pinto@synopsys.com \
    --cc=adrian.hunter@intel.com \
    --cc=arve@android.com \
    --cc=gmar@google.com \
    --cc=hch@lst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=tomas.winkler@intel.com \
    --cc=ulf.hansson@linaro.org \
    --cc=vinholikatti@gmail.com \
    --cc=ygardi@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.