Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: antoine.tenart@free-electrons.com (Antoine Tenart)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/7] crypto: inside-secure: add SafeXcel EIP197 crypto engine driver
Date: Tue, 18 Apr 2017 10:04:22 +0200	[thread overview]
Message-ID: <20170418080422.55k63czpmnuqn7ku@kwain> (raw)
In-Reply-To: <5a016e1e-1443-158a-5ced-58dcb4ad63cc@arm.com>

Hi Robin,

On Wed, Apr 12, 2017 at 02:54:13PM +0100, Robin Murphy wrote:
> 
> Bit of a drive-by, but since I have it in my head that crypto drivers
> are a hotspot for dodgy DMA usage (in part due to the hardware often
> being a bit esoteric with embedded RAMs and such), this caught my eye
> and I thought I'd give this a quick once-over to check for anything
> smelly. Unfortunately, I was not disappointed... ;)

:-)

> On 29/03/17 13:44, Antoine Tenart wrote:
> [...]
> > diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
> > new file mode 100644
> > index 000000000000..00f3f2c85d05
> > --- /dev/null
> > +++ b/drivers/crypto/inside-secure/safexcel.c
> [...]
> > +int safexcel_invalidate_cache(struct crypto_async_request *async,
> > +			      struct safexcel_context *ctx,
> > +			      struct safexcel_crypto_priv *priv,
> > +			      dma_addr_t ctxr_dma, int ring,
> > +			      struct safexcel_request *request)
> > +{
> > +	struct safexcel_command_desc *cdesc;
> > +	struct safexcel_result_desc *rdesc;
> > +	phys_addr_t ctxr_phys;
> > +	int ret = 0;
> > +
> > +	ctxr_phys = dma_to_phys(priv->dev, ctxr_dma);
> 
> No no no. This is a SWIOTLB-specific (or otherwise arch-private,
> depending on implementation) helper, not a DMA API function, and should
> not be called directly by drivers. There is no guarantee it will give
> the result you expect, or even compile, in all cases (if the kbuild
> robot hasn't already revealed via the COMPILE_TEST dependency).
> 
> That said, AFAICS ctxr_phys ends up in a descriptor which is given to
> the device, so trying to use a physical address is wrong and it should
> still be the DMA address anyway.

I see. The cryptographic engine should always use dma addresses. I'll
update the descriptors structure members from "phys" to "dma" as well.

> [...]
> > +static int safexcel_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct resource *res;
> > +	struct safexcel_crypto_priv *priv;
> > +	int i, ret;
> > +
> > +	priv = devm_kzalloc(dev, sizeof(struct safexcel_crypto_priv),
> > +			    GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	priv->dev = dev;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	priv->base = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(priv->base)) {
> > +		dev_err(dev, "failed to get resource\n");
> > +		return PTR_ERR(priv->base);
> > +	}
> > +
> > +	priv->clk = of_clk_get(dev->of_node, 0);
> > +	if (!IS_ERR(priv->clk)) {
> > +		ret = clk_prepare_enable(priv->clk);
> > +		if (ret) {
> > +			dev_err(dev, "unable to enable clk (%d)\n", ret);
> > +			return ret;
> > +		}
> > +	} else {
> > +		/* The clock isn't mandatory */
> > +		if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
> > +			return -EPROBE_DEFER;
> > +	}
> 
> You should call dma_set_mask_and_coherent() before any DMA API calls,
> both to confirm DMA really is going to work all, and also (since this IP
> apparently supports >32-bit addresses) to describe the full inherent
> addressing capability, not least to avoid wasting time/space with
> unnecessary bounce buffering otherwise.

OK, I'll add a call to this helper before using DMA API calls.

> > +
> > +err_pool:
> > +	dma_pool_destroy(priv->context_pool);
> 
> You used dmam_pool_create(), so not only is an explicit destroy
> unnecessary, but doing so with the non-managed version is actively
> harmful, since devres would end up double-freeing the pool after you return.

I saw this and fixed it in my local version.

> > +struct safexcel_token {
> > +	u32 packet_length:17;
> > +	u8 stat:2;
> > +	u16 instructions:9;
> > +	u8 opcode:4;
> > +} __packed;
> 
> Using bitfields in hardware descriptors seems pretty risky, since you've
> no real guarantee two compilers will lay them out the same way (or that
> either would be correct WRT what the hardware expects). I'd be more
> inclined to construct all these fields with explicit masking and shifting.

Hmm, I'm not sure to follow you here. If I use bitfields in a __packed
structure, we should be safe. Why would the compiler have a different
behaviour?

> > +static int safexcel_aes_send(struct crypto_async_request *async,
> > +			     int ring, struct safexcel_request *request,
> > +			     int *commands, int *results)
> > +{
> > +	struct ablkcipher_request *req = ablkcipher_request_cast(async);
> > +	struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
> > +	struct safexcel_crypto_priv *priv = ctx->priv;
> > +	struct safexcel_command_desc *cdesc;
> > +	struct safexcel_result_desc *rdesc;
> > +	struct scatterlist *sg;
> > +	phys_addr_t ctxr_phys;
> > +	int nr_src, nr_dst, n_cdesc = 0, n_rdesc = 0, queued = req->nbytes;
> > +	int i, ret = 0;
> > +
> > +	request->req = &req->base;
> > +
> > +	if (req->src == req->dst) {
> > +		nr_src = sg_nents_for_len(req->src, req->nbytes);
> > +		nr_dst = nr_src;
> > +
> > +		if (dma_map_sg(priv->dev, req->src, nr_src, DMA_BIDIRECTIONAL) <= 0)
> 
> Nit: you only need to check for zero/nonzero to determine failure
> (similarly below) - dma_map_sg() cannot return negative values.

OK.

> Bigger complaint: you should not ignore the successful return value and
> rely on it being equal to nr_src - please see the description of
> dma_map_sg() in Documenatation/DMA-API.txt

OK, I'll have a look at it and fix this.

> > +	/* command descriptors */
> > +	for_each_sg(req->src, sg, nr_src, i) {
> > +		phys_addr_t sg_phys = dma_to_phys(priv->dev, sg_dma_address(sg));
> > +		int len = sg_dma_len(sg);
> 
> If dma_map_sg() coalesced any entries into the same mapping such that
> count < nents, these could well give bogus values toward the end of the
> list once i >= count(if you're lucky, at least len might be 0).

OK, I'll fix this.

> > +	/* Add a command descriptor for the cached data, if any */
> > +	if (cache_len) {
> > +		ctx->base.cache_dma = dma_map_single(priv->dev, req->cache,
> 
> This is pretty dodgy, since req->cache is inside a live data structure,
> adjoining parts of which are updated whilst still mapped (the update of
> req->processed below). You just about get away without data corruption
> since we *probably* don't invalidate anything when unmapping
> DMA_TO_DEVICE, and the coherency hardware *probably* doesn't do anything
> crazy, but you've no real guarantee of that - any DMA buffer should
> really be separately kmalloced. "That's a nice dirty cache line you've
> got there, it'd be a shame if anything were to happen to it..."

OK, good to know.

> > +	rdr->base = dmam_alloc_coherent(priv->dev,
> > +					rdr->offset * EIP197_DEFAULT_RING_SIZE,
> > +					&rdr->base_dma, GFP_KERNEL);
> > +	if (!rdr->base) {
> > +		dmam_free_coherent(priv->dev,
> > +				   cdr->offset * EIP197_DEFAULT_RING_SIZE,
> > +				   cdr->base, cdr->base_dma);
> 
> Returning an error here will abort your probe routine, so devres will
> clean these up there and then - there's no need to do free anything
> explicitly. That's rather the point of using devm_*() to begin with.

Sure.

> > +	dmam_free_coherent(priv->dev,
> > +			   cdr->offset * EIP197_DEFAULT_RING_SIZE,
> > +			   cdr->base, cdr->base_dma);
> > +	dmam_free_coherent(priv->dev,
> > +			   rdr->offset * EIP197_DEFAULT_RING_SIZE,
> > +			   rdr->base, rdr->base_dma);
> > +}
> 
> Again, this is only called at device teardown, so the whole function is
> redundant.

OK, I'll remove these.

Thanks for the review!
Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170418/2a1b30cf/attachment-0001.sig>

  reply	other threads:[~2017-04-18  8:04 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-29 12:44 [PATCH 0/7] arm64: marvell: add cryptographic engine support for 7k/8k Antoine Tenart
2017-03-29 12:44 ` [PATCH 1/7] Documentation/bindings: Document the SafeXel cryptographic engine driver Antoine Tenart
2017-03-29 12:44 ` [PATCH 2/7] crypto: inside-secure: add SafeXcel EIP197 crypto " Antoine Tenart
2017-04-12 13:54   ` Robin Murphy
2017-04-18  8:04     ` Antoine Tenart [this message]
2017-03-29 12:44 ` [PATCH 3/7] MAINTAINERS: add a maintainer for the Inside Secure crypto driver Antoine Tenart
2017-03-29 12:44 ` [PATCH 4/7] arm64: marvell: dts: add crypto engine description for 7k/8k Antoine Tenart
2017-04-12  8:36   ` Gregory CLEMENT
2017-04-12  8:56   ` Thomas Petazzoni
2017-04-18  7:34     ` Antoine Tenart
2017-03-29 12:44 ` [PATCH 5/7] arm64: marvell: dts: enable the crypto engine on the Armada 7040 DB Antoine Tenart
2017-04-12  8:36   ` Gregory CLEMENT
2017-03-29 12:44 ` [PATCH 6/7] arm64: marvell: dts: enable the crypto engine on the Armada 8040 DB Antoine Tenart
2017-04-12  8:37   ` Gregory CLEMENT
2017-03-29 12:44 ` [PATCH 7/7] arm64: defconfig: enable the Safexcel crypto engine as a module Antoine Tenart
2017-04-12  8:38   ` Gregory CLEMENT
2017-04-10  9:39 ` [PATCH 0/7] arm64: marvell: add cryptographic engine support for 7k/8k Herbert Xu
2017-04-11 16:12   ` Gregory CLEMENT
2017-04-12  6:11     ` Herbert Xu

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=20170418080422.55k63czpmnuqn7ku@kwain \
    --to=antoine.tenart@free-electrons.com \
    --cc=linux-arm-kernel@lists.infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox