lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d5cf77b4734f9d60c8d61a2a0a799180@walle.cc>
Date:   Fri, 05 Nov 2021 02:20:43 +0100
From:   Michael Walle <michael@...le.cc>
To:     Andrey Zhizhikin <andrey.zhizhikin@...ca-geosystems.com>
Cc:     horia.geanta@....com, pankaj.gupta@....com,
        herbert@...dor.apana.org.au, davem@...emloft.net,
        iuliana.prodan@....com, linux-crypto@...r.kernel.org,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH] crypto: caam - check jr permissions before probing

Hi Andrey,

Am 2021-11-04 17:21, schrieb Andrey Zhizhikin:
> Job Rings can be set to be exclusively used by TrustZone which makes 
> the
> access to those rings only possible from Secure World. This access
> separation is defined by setting bits in CAAM JRxDID_MS register. Once
> reserved to be owned by TrustZone, this Job Ring becomes unavailable 
> for
> the Kernel. This reservation is performed early in the boot process,
> even before the Kernel starts, which leads to unavailability of the HW
> at the probing stage. Moreover, the reservation can be done for any Job
> Ring and is not under control of the Kernel. The only condition that
> remains is: at least one Job Ring should be made available for the NS
> world.

Where is that written down?

> Current implementation lists Job Rings as child nodes of CAAM driver,
> and tries to perform probing on those regardless of whether JR HW is
> accessible or not.
> 
> This leads to the following error while probing:
> [    1.509894] caam 30900000.crypto: job rings = 3, qi = 0
> [    1.525201] caam_jr 30901000.jr: failed to flush job ring 0
> [    1.525214] caam_jr: probe of 30901000.jr failed with error -5
> 
> Implement a dynamic mechanism to identify which Job Ring is actually
> marked as owned by TrustZone, and fail the probing of those child nodes
> with -ENODEV.
> 
> Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@...ca-geosystems.com>
> ---
>  drivers/crypto/caam/ctrl.c   | 18 ++++++++++++------
>  drivers/crypto/caam/intern.h |  1 +
>  drivers/crypto/caam/jr.c     | 17 +++++++++++++++++
>  drivers/crypto/caam/regs.h   |  8 +++++---
>  4 files changed, 35 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
> index ca0361b2dbb0..c48506a02340 100644
> --- a/drivers/crypto/caam/ctrl.c
> +++ b/drivers/crypto/caam/ctrl.c
> @@ -805,12 +805,18 @@ static int caam_probe(struct platform_device 
> *pdev)
>  	for_each_available_child_of_node(nprop, np)
>  		if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") ||
>  		    of_device_is_compatible(np, "fsl,sec4.0-job-ring")) {
> -			ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *)
> -					     ((__force uint8_t *)ctrl +
> -					     (ring + JR_BLOCK_NUMBER) *
> -					      BLOCK_OFFSET
> -					     );
> -			ctrlpriv->total_jobrs++;
> +			/* Check if the JR is not owned exclusively by TZ */
> +			if (!((rd_reg32(&ctrl->jr_mid[ring].liodn_ms)) &
> +				(MSTRID_LOCK_TZ_OWN | MSTRID_LOCK_PRIM_TZ))) {

what is the PRIM_TZ bit? I don't see it in my reference manual
(which is for the LS1028A).

Can't we just do a
if (rd_reg32(&ctrl->jr_mid[ring].liodn_ms) &
     (MSTRID_LOCK_TZ_OWN | MSTRID_LOCK_PRIM_TZ))
	continue;

> +				ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *)
> +						     ((__force uint8_t *)ctrl +
> +						     (ring + JR_BLOCK_NUMBER) *
> +						      BLOCK_OFFSET
> +						     );

This isn't really used at all. Can we drop "jr" from
struct caam_drv_private altogether? See also below.

> +				/* Indicate that this JR is available for NS */
> +				ctrlpriv->jobr_ns_flags |= BIT(ring);
> +				ctrlpriv->total_jobrs++;

as well as this?

> +			}
>  			ring++;
>  		}
> 
> diff --git a/drivers/crypto/caam/intern.h 
> b/drivers/crypto/caam/intern.h
> index 7d45b21bd55a..2919af55dbfe 100644
> --- a/drivers/crypto/caam/intern.h
> +++ b/drivers/crypto/caam/intern.h
> @@ -91,6 +91,7 @@ struct caam_drv_private {
>  	 * or from register-based version detection code
>  	 */
>  	u8 total_jobrs;		/* Total Job Rings in device */
> +	u8 jobr_ns_flags;	/* Flags for each Job Ring if it is not owned by 
> TZ*/
>  	u8 qi_present;		/* Nonzero if QI present in device */
>  	u8 mc_en;		/* Nonzero if MC f/w is active */
>  	int secvio_irq;		/* Security violation interrupt number */
> diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
> index 7f2b1101f567..a260981e0843 100644
> --- a/drivers/crypto/caam/jr.c
> +++ b/drivers/crypto/caam/jr.c
> @@ -511,10 +511,27 @@ static int caam_jr_probe(struct platform_device 
> *pdev)
>  	struct device_node *nprop;
>  	struct caam_job_ring __iomem *ctrl;
>  	struct caam_drv_private_jr *jrpriv;
> +	struct caam_drv_private *caamctrlpriv;
>  	static int total_jobrs;

ugh.

>  	struct resource *r;
>  	int error;
> 
> +	/* Before we proceed with the JR device probing, verify
> +	 * that the job ring itself is available to Non-Secure world.
> +	 * If the JR is owned exclusively by TZ - we should not even
> +	 * process it further.
> +	 */
> +	caamctrlpriv = dev_get_drvdata(pdev->dev.parent);
> +	if (!(caamctrlpriv->jobr_ns_flags & BIT(total_jobrs))) {

Is anything preventing from total_jobrs getting big? Can't
we get rid of this static variable somehow? Before this commit,
it was just used for messages. Can we check the TZ bit here
instead of doing that bitflags dance?

nitpick: in caam there are no netdev comments. So multiline
comments look like:
/*
  * this is a comment.
  */

> +		/* This job ring is marked to be exclusively used by TZ,
> +		 * do not proceed with probing as the HW block is inaccessible.
> +		 * Increment total seen JR devices since it is used as the index
> +		 * into verification and fail probing for this node.
> +		 */
> +		total_jobrs++;
> +		return -ENODEV;
> +	}
> +
>  	jrdev = &pdev->dev;
>  	jrpriv = devm_kzalloc(jrdev, sizeof(*jrpriv), GFP_KERNEL);
>  	if (!jrpriv)
> diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
> index 3738625c0250..8ade617f9e65 100644
> --- a/drivers/crypto/caam/regs.h
> +++ b/drivers/crypto/caam/regs.h
> @@ -445,10 +445,12 @@ struct caam_perfmon {
>  };
> 
>  /* LIODN programming for DMA configuration */
> -#define MSTRID_LOCK_LIODN	0x80000000
> -#define MSTRID_LOCK_MAKETRUSTED	0x00010000	/* only for JR masterid */
> +#define MSTRID_LOCK_LIODN		BIT(31)
> +#define MSTRID_LOCK_MAKETRUSTED	BIT(16)	/* only for JR: masterid */
> +#define MSTRID_LOCK_TZ_OWN		BIT(15)	/* only for JR: owned by TZ */
> +#define MSTRID_LOCK_PRIM_TZ		BIT(4)	/* only for JR: Primary TZ */

can't find that one.

in general, does these marcros match with your reference
manual? Which one do you have?

for me the bits are named:
LICID[31], AMTD[16], TZ[15] and SDID[11:0]
also the register is called JRnICID.

I wonder if the LS1028A has a newer/older CAAM version.
according to the device tree (fsl-ls1028a.dtsi) the
sec is v5.0 (and also compatible with v4.0). If you
have a look at the RM it says 7.0 (at least the MAJ_VER
in SECVID_MS is 7 accoring to the manual; i haven't
checked on the hardware for now.

Horia, can you shed some light here.

> -#define MSTRID_LIODN_MASK	0x0fff
> +#define MSTRID_LIODN_MASK		GENMASK(11, 0)
>  struct masterid {
>  	u32 liodn_ms;	/* lock and make-trusted control bits */
>  	u32 liodn_ls;	/* LIODN for non-sequence and seq access */
> 
> base-commit: 8a796a1dfca2780321755033a74bca2bbe651680

-- 
-michael

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ