Linux cryptographic layer development
 help / color / mirror / Atom feed
* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Herbert Xu @ 2016-09-28 12:29 UTC (permalink / raw)
  To: Jan Stancek
  Cc: Marcelo Cerri, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <1597189480.51836.1475048451846.JavaMail.zimbra@redhat.com>

On Wed, Sep 28, 2016 at 03:40:51AM -0400, Jan Stancek wrote:
> 
> Thanks for clearing up how this works in padlock-sha, but
> we are not exactly in same situation with p8_ghash.
> 
> p8_ghash_init_tfm() already updates descsize. Problem in original report
> is that without custom export/import/statesize p8_ghash_alg.statesize
> gets initialized by shash_prepare_alg() to alg->descsize:

Right.

> so I think we need either:
> 1) make sure p8_ghash_alg.descsize is correct before we register shash,
>    this is what Marcelo's last patch is doing

This approach doesn't work because there is no guarantee that
you'll get the same fallback the next time you allocate a tfm.
So relying on the descsize being constant can only work if all
implementations of the fallback use the same desc struct.

> 2) provide custom export/import/statesize for p8_ghash_alg

This works for padlock-sha because every implementation of SHA
uses the same state data structure from sha.h.  If we can make
all implementations of ghash agree on the exported state then
we can use the same approach.

Otherwise we can go back to allocating just ghash-generic and
also move its data structure into an exported header file.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Marcelo Cerri @ 2016-09-28 12:28 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Jan Stancek, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160928024549.GB14034@gondor.apana.org.au>

[-- Attachment #1: Type: text/plain, Size: 1931 bytes --]

Hi Herbert,

On Wed, Sep 28, 2016 at 10:45:49AM +0800, Herbert Xu wrote:
> On Tue, Sep 27, 2016 at 04:46:44PM -0300, Marcelo Cerri wrote:
> >
> > Can you check if the problem occurs with this patch?
>
> In light of the fact that padlock-sha is the correct example
> to follow, you only need to add one line to the init_tfm fucntion
> to update the descsize based on that of the fallback.
>

Not sure if I'm missing something here but p8_ghash already does that:

 56 static int p8_ghash_init_tfm(struct crypto_tfm *tfm)
 57 {
 ...
 83         shash_tfm->descsize = sizeof(struct p8_ghash_desc_ctx)
 84             + crypto_shash_descsize(fallback);
 85
 86         return 0;
 87 }

I think the problem here is that crypto_ahash_statesize uses the
statesize value (that is initialized with the descsize value from
shash_alg) instead of using the value from the tfm that was updated.

For padlock_sha1, it uses the value from alg->statesize since it defines
import and export functions. It doesn't make much difference if it uses
the value from descsize or statesize here, what really matter is that
it uses the value defined in struct shash_alg and not from the tfm.

The big difference between p8_ghash and padlock_sha1 is that
padlock_sha1 defines alg->statesize as sizeof(struct sha1_state), which
is the descsize value used by sha1_generic. This probably works but
it's also wrong because the padlock_sha1 driver does not ensures that
sha1_generic is always used.

So, one solution is to hardcode ghash-generic as the fallback algorithm
and update the descsize direct in its shash_alg structure. There's only
one problem with that. ghash-generic desc type (struct ghash_desc_ctx)
is not available for vmx_crypto at compile type, the type is defined
directly in crypto/ghash-generic.c. That's the reason I added a function
to get the fallback desc size at runtime in the patch I wrote as a prove
of concept.

--
Regards,
Marcelo

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply

* [PATCH] crypto/caam/jr : Unmap region obtained by of_iomap
From: Arvind Yadav @ 2016-09-28 10:31 UTC (permalink / raw)
  To: herbert, davem
  Cc: alexandru.porosanu, fabio.estevam, horia.geanta, cata.vasile,
	linux-crypto, linux-kernel, Arvind Yadav

From: Arvind Yadav <arvind.yadav.cs@gmail.com>

Free memory mapping, if probe is not successful.

Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
 drivers/crypto/caam/jr.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index a81f551..9e7f281 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -513,6 +513,7 @@ static int caam_jr_probe(struct platform_device *pdev)
 	error = caam_jr_init(jrdev); /* now turn on hardware */
 	if (error) {
 		irq_dispose_mapping(jrpriv->irq);
+		iounmap(ctrl);
 		return error;
 	}
 
-- 
1.7.9.5

^ permalink raw reply related

* Re: [2/2] ath9k: disable RNG by default
From: Kalle Valo @ 2016-09-28 10:00 UTC (permalink / raw)
  To: miaoqing pan
  Cc: linux-wireless, ath9k-devel, linux-crypto, smueller, jason,
	pouyans, Miaoqing Pan
In-Reply-To: <1470726147-30095-2-git-send-email-miaoqing@codeaurora.org>

miaoqing pan <miaoqing@codeaurora.org> wrote:
> From: Miaoqing Pan <miaoqing@codeaurora.org>
> 
> ath9k RNG will dominates all the noise sources from the real HW
> RNG, disable it by default. But we strongly recommand to enable
> it if the system without HW RNG, especially on embedded systems.
> 
> Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
> Acked-by: Stephan Mueller <smueller@chronox.de>
> Acked-by: Stephan Mueller <smueller@chronox.de>
> Reviewed-by: Jason Cooper <jason@lakedaemon.net>

Patch applied to ath-next branch of ath.git, thanks.

739ccd76b40e ath9k: disable RNG by default

-- 
https://patchwork.kernel.org/patch/9270467/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Jan Stancek @ 2016-09-28  8:59 UTC (permalink / raw)
  To: Marcelo Cerri
  Cc: Herbert Xu, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160927194644.GB15729@gallifrey>

> Jan,
> 
> Can you check if the problem occurs with this patch?

No issues in over-night test with this patch.

> --- a/drivers/crypto/vmx/vmx.c
> +++ b/drivers/crypto/vmx/vmx.c
> @@ -28,6 +28,8 @@
>  #include <asm/cputable.h>
>  #include <crypto/internal/hash.h>
>  
> +int p8_ghash_fallback_descsize(void);
> +
>  extern struct shash_alg p8_ghash_alg;
>  extern struct crypto_alg p8_aes_alg;
>  extern struct crypto_alg p8_aes_cbc_alg;
> @@ -45,6 +47,7 @@ int __init p8_init(void)
>  {
>  	int ret = 0;
>  	struct crypto_alg **alg_it;
> +	int ghash_descsize;
>  
>  	for (alg_it = algs; *alg_it; alg_it++) {
>  		ret = crypto_register_alg(*alg_it);
> @@ -59,6 +62,12 @@ int __init p8_init(void)
>  	if (ret)
>  		return ret;
>  
> +	ghash_descsize = p8_ghash_fallback_descsize();
> +	if (ghash_descsize < 0) {
> +		printk(KERN_ERR "Cannot get descsize for p8_ghash fallback\n");
> +		return ghash_descsize;
> +	}
> +	p8_ghash_alg.descsize += ghash_descsize;
>  	ret = crypto_register_shash(&p8_ghash_alg);
>  	if (ret) {
>  		for (alg_it = algs; *alg_it; alg_it++)

I'd suggest to move this inside vmx/ghash.c to a new function, so all p8_ghash
related code is at single place. Then p8_init() would just call the new
function:
-    ret = crypto_register_shash(&p8_ghash_alg);
+    ret = register_p8_ghash();

Regards,
Jan

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Jan Stancek @ 2016-09-28  7:40 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Marcelo Cerri, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160928024549.GB14034@gondor.apana.org.au>





----- Original Message -----
> From: "Herbert Xu" <herbert@gondor.apana.org.au>
> To: "Marcelo Cerri" <marcelo.cerri@canonical.com>
> Cc: "Jan Stancek" <jstancek@redhat.com>, "rui y wang" <rui.y.wang@intel.com>, mhcerri@linux.vnet.ibm.com,
> leosilva@linux.vnet.ibm.com, pfsmorigo@linux.vnet.ibm.com, linux-crypto@vger.kernel.org,
> linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
> Sent: Wednesday, 28 September, 2016 4:45:49 AM
> Subject: Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
> 
> On Tue, Sep 27, 2016 at 04:46:44PM -0300, Marcelo Cerri wrote:
> > 
> > Can you check if the problem occurs with this patch?
> 
> In light of the fact that padlock-sha is the correct example
> to follow, you only need to add one line to the init_tfm fucntion
> to update the descsize based on that of the fallback.

Thanks for clearing up how this works in padlock-sha, but
we are not exactly in same situation with p8_ghash.

p8_ghash_init_tfm() already updates descsize. Problem in original report
is that without custom export/import/statesize p8_ghash_alg.statesize
gets initialized by shash_prepare_alg() to alg->descsize:

crash> p p8_ghash_alg.statesize
$1 = 56

testmgr allocates space for export based on crypto_shash_statesize(),
but shash_default_export() writes based on crypto_shash_descsize():
[    8.297902] state: c0000004b873aa80, statesize: 56
[    8.297932] shash_default_export memcpy c0000004b873aa80 c0000004b8607da0, len: 76

so I think we need either:
1) make sure p8_ghash_alg.descsize is correct before we register shash,
   this is what Marcelo's last patch is doing
2) provide custom export/import/statesize for p8_ghash_alg

Regards,
Jan

> 
> Thanks,
> --
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> 

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Herbert Xu @ 2016-09-28  2:45 UTC (permalink / raw)
  To: Marcelo Cerri
  Cc: Jan Stancek, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160927194644.GB15729@gallifrey>

On Tue, Sep 27, 2016 at 04:46:44PM -0300, Marcelo Cerri wrote:
> 
> Can you check if the problem occurs with this patch?

In light of the fact that padlock-sha is the correct example
to follow, you only need to add one line to the init_tfm fucntion
to update the descsize based on that of the fallback.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Herbert Xu @ 2016-09-28  2:44 UTC (permalink / raw)
  To: Jan Stancek
  Cc: Marcelo Cerri, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <346154437.225735.1474966863173.JavaMail.zimbra@redhat.com>

On Tue, Sep 27, 2016 at 05:01:03AM -0400, Jan Stancek wrote:
> 
> Also, does that mean that padlock_sha has similar problem?
> It does not seem to reserve any space for fallback __ctx and it calls
> init()/update()/export() with padlock_sha_desc's fallback:
> 
> struct padlock_sha_desc {
>         struct shash_desc fallback;
> };
> 
> static struct shash_alg sha1_alg = {
>         .descsize       =       sizeof(struct padlock_sha_desc),

Actually I was wrong when I said that the API couldn't handle
a dynamic fallback.  It can and padlock-sha does the right thing
by updating descsize in the cra_init function.

So this is what vmx should do too.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Marcelo Cerri @ 2016-09-27 19:46 UTC (permalink / raw)
  To: Jan Stancek
  Cc: Herbert Xu, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160927120414.GC21317@gallifrey>

[-- Attachment #1: Type: text/plain, Size: 3002 bytes --]

Jan, 

Can you check if the problem occurs with this patch?

---
 drivers/crypto/vmx/ghash.c | 28 +++++++++++++++++-----------
 drivers/crypto/vmx/vmx.c   |  9 +++++++++
 2 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/drivers/crypto/vmx/ghash.c b/drivers/crypto/vmx/ghash.c
index 6c999cb0..033aba1 100644
--- a/drivers/crypto/vmx/ghash.c
+++ b/drivers/crypto/vmx/ghash.c
@@ -36,6 +36,8 @@
 #define GHASH_DIGEST_SIZE (16)
 #define GHASH_KEY_LEN (16)
 
+#define GHASH_FALLBACK_ALG "ghash-generic"
+
 void gcm_init_p8(u128 htable[16], const u64 Xi[2]);
 void gcm_gmult_p8(u64 Xi[2], const u128 htable[16]);
 void gcm_ghash_p8(u64 Xi[2], const u128 htable[16],
@@ -53,18 +55,26 @@ struct p8_ghash_desc_ctx {
 	struct shash_desc fallback_desc;
 };
 
+int p8_ghash_fallback_descsize(void)
+{
+	int descsize;
+	struct crypto_shash *fallback;
+	fallback = crypto_alloc_shash(GHASH_FALLBACK_ALG, 0,
+				      CRYPTO_ALG_NEED_FALLBACK);
+	if (IS_ERR(fallback)) {
+		return PTR_ERR(fallback);
+	}
+	descsize = crypto_shash_descsize(fallback);
+	crypto_free_shash(fallback);
+	return descsize;
+}
+
 static int p8_ghash_init_tfm(struct crypto_tfm *tfm)
 {
-	const char *alg;
+	const char *alg = GHASH_FALLBACK_ALG;
 	struct crypto_shash *fallback;
-	struct crypto_shash *shash_tfm = __crypto_shash_cast(tfm);
 	struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	if (!(alg = crypto_tfm_alg_name(tfm))) {
-		printk(KERN_ERR "Failed to get algorithm name.\n");
-		return -ENOENT;
-	}
-
 	fallback = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
 	if (IS_ERR(fallback)) {
 		printk(KERN_ERR
@@ -79,10 +89,6 @@ static int p8_ghash_init_tfm(struct crypto_tfm *tfm)
 			       crypto_shash_get_flags((struct crypto_shash
 						       *) tfm));
 	ctx->fallback = fallback;
-
-	shash_tfm->descsize = sizeof(struct p8_ghash_desc_ctx)
-	    + crypto_shash_descsize(fallback);
-
 	return 0;
 }
 
diff --git a/drivers/crypto/vmx/vmx.c b/drivers/crypto/vmx/vmx.c
index 31a98dc..8a51149 100644
--- a/drivers/crypto/vmx/vmx.c
+++ b/drivers/crypto/vmx/vmx.c
@@ -28,6 +28,8 @@
 #include <asm/cputable.h>
 #include <crypto/internal/hash.h>
 
+int p8_ghash_fallback_descsize(void);
+
 extern struct shash_alg p8_ghash_alg;
 extern struct crypto_alg p8_aes_alg;
 extern struct crypto_alg p8_aes_cbc_alg;
@@ -45,6 +47,7 @@ int __init p8_init(void)
 {
 	int ret = 0;
 	struct crypto_alg **alg_it;
+	int ghash_descsize;
 
 	for (alg_it = algs; *alg_it; alg_it++) {
 		ret = crypto_register_alg(*alg_it);
@@ -59,6 +62,12 @@ int __init p8_init(void)
 	if (ret)
 		return ret;
 
+	ghash_descsize = p8_ghash_fallback_descsize();
+	if (ghash_descsize < 0) {
+		printk(KERN_ERR "Cannot get descsize for p8_ghash fallback\n");
+		return ghash_descsize;
+	}
+	p8_ghash_alg.descsize += ghash_descsize;
 	ret = crypto_register_shash(&p8_ghash_alg);
 	if (ret) {
 		for (alg_it = algs; *alg_it; alg_it++)
-- 
2.7.4


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply related

* Re: [BUG] crypto: atmel-aes - erro when compiling with VERBOSE_DEBUG enable
From: Cyrille Pitchen @ 2016-09-27 16:45 UTC (permalink / raw)
  To: levent demir, Herbert Xu; +Cc: linux-crypto
In-Reply-To: <1474548357.12981.19.camel@inria.fr>

Hi Levent,

there is a typo in the subject line: erroR.
Also it would be better to start the summary phrase of the subject line with a
verb:

crypto: atmel-aes: fix compiler error when VERBODE_DEBUG is defined

Le 22/09/2016 à 14:45, levent demir a écrit :
> Fix debug function call in atmel_aes_write
> 
> Signed-off-by: Levent DEMIR <levent.demir@inria.fr>
> ---
>  drivers/crypto/atmel-aes.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
> index e3d40a8..2b0f926 100644
> --- a/drivers/crypto/atmel-aes.c
> +++ b/drivers/crypto/atmel-aes.c
> @@ -317,7 +317,7 @@ static inline void atmel_aes_write(struct
> atmel_aes_dev *dd,
>  		char tmp[16];
>  
>  		dev_vdbg(dd->dev, "write 0x%08x into %s\n", value,
> -			 atmel_aes_reg_name(offset, tmp));
> +			atmel_aes_reg_name(offset, tmp, sizeof(tmp)));
It looks like a space has been removed.

>  	}
>  #endif /* VERBOSE_DEBUG */
>  
> 


Best regards,

Cyrille

^ permalink raw reply

* Re: [v2] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Stephan Mueller @ 2016-09-27 15:17 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Ted Tso, herbert, linux-kernel, linux-crypto, ath9k-devel,
	linux-wireless, ath9k-devel, Kalle Valo, Jason Cooper
In-Reply-To: <2ba03f89daee4f09a88a1238943eb49d@euamsexm01a.eu.qualcomm.com>

Am Dienstag, 27. September 2016, 16:44:16 CEST schrieb Kalle Valo:

Hi Kalle,

> Stephan Mueller <smueller@chronox.de> wrote:
> > The ATH9K driver implements an RNG which is completely bypassing the
> > standard Linux HW generator logic.
> > 
> > The RNG may or may not deliver entropy. Considering the conservative
> > approach in treating entropy with respect to non-auditable sources, this
> > patch changes the delivered entropy value to zero. The RNG still feeds
> > data into the input_pool but it is assumed to have no entropy.
> > 
> > When the ATH9K RNG changes to use the HW RNG framework, it may re-enable
> > the entropy estimation considering that a user can change that value at
> > boot and runtime.
> > 
> > Reviewed-by: Jason Cooper <jason@lakedaemon.net>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> 
> Based on the discussion I'm dropping this patch. But the discussion was
> hard to follow so please let me know if I misunderstood.

I guess the rejection is appropriate, but something needs to be done: 
add_hwgenerator_randomness should not be used in this scenario.
> 
> Patch set to Rejected.



Ciao
Stephan

^ permalink raw reply

* Re: [1/2] ath9k: change entropy formula for easier understanding
From: Kalle Valo @ 2016-09-27 14:53 UTC (permalink / raw)
  To: miaoqing pan
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	ath9k-devel-A+ZNKFmMK5xy9aJCnZT0Uw,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	smueller-T9tCv8IpfcWELgA04lAiVw, jason-NLaQJdtUoK4Be96aLqz0jA,
	pouyans-Rm6X0d1/PG5y9aJCnZT0Uw, Miaoqing Pan
In-Reply-To: <1470726147-30095-1-git-send-email-miaoqing-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

miaoqing pan <miaoqing-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> From: Miaoqing Pan <miaoqing-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> 
> The quality of ADC entropy is 10 bits of min-entropy for
> a 32-bit value, change '(((x) * 8 * 320) >> 10)' to
> '(((x) * 8 * 10) >> 5)' for easier understanding.
> 
> Signed-off-by: Miaoqing Pan <miaoqing-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

I need some help here, it this patch ok to take or should I drop it? The
discussion is available from the patchwork link below if someone needs to
refresh the memory.

-- 
https://patchwork.kernel.org/patch/9270463/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply

* Re: [v2] RANDOM: ATH9K RNG delivers zero bits of entropy
From: Kalle Valo @ 2016-09-27 14:44 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Ted Tso, herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	ath9k-devel-A+ZNKFmMK5xy9aJCnZT0Uw,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	ath9k-devel-xDcbHBWguxHbcTqmT+pZeQ, Kalle Valo, Jason Cooper
In-Reply-To: <1654172.XfclnXhRmn-jJGQKZiSfeo1haGO/jJMPxvVK+yQ3ZXh@public.gmane.org>

Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org> wrote:
> The ATH9K driver implements an RNG which is completely bypassing the
> standard Linux HW generator logic.
> 
> The RNG may or may not deliver entropy. Considering the conservative
> approach in treating entropy with respect to non-auditable sources, this
> patch changes the delivered entropy value to zero. The RNG still feeds
> data into the input_pool but it is assumed to have no entropy.
> 
> When the ATH9K RNG changes to use the HW RNG framework, it may re-enable
> the entropy estimation considering that a user can change that value at
> boot and runtime.
> 
> Reviewed-by: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
> Signed-off-by: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>

Based on the discussion I'm dropping this patch. But the discussion was
hard to follow so please let me know if I misunderstood.

Patch set to Rejected.

-- 
https://patchwork.kernel.org/patch/9266265/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Marcelo Cerri @ 2016-09-27 12:04 UTC (permalink / raw)
  To: Jan Stancek
  Cc: Herbert Xu, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <346154437.225735.1474966863173.JavaMail.zimbra@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1287 bytes --]

Hi,

On Tue, Sep 27, 2016 at 05:01:03AM -0400, Jan Stancek wrote:
> So, if we extended p8_ghash_desc_ctx to accommodate fallback_desc's ctx
> and then provided statesize/import/export, would that be acceptable?
> 
> struct p8_ghash_desc_ctx {
>         ...
>         struct shash_desc fallback_desc;
> +       char fallback_ctx[sizeof(struct ghash_desc_ctx)];
> 

I think so. That's the solution mentioned by Herbert. The only drawback
is that we will need to fix "ghash-generic" as the fallback
implementation in order to know beforehand its descsize.

However I would keep the p8_ghash_desc_ctx the way it is and I would
sum sizeof(struct ghash_desc_ctx) to the algorithm descsize instead.

Let me put a quick patch together to test this.

> 
> Also, does that mean that padlock_sha has similar problem?
> It does not seem to reserve any space for fallback __ctx and it calls
> init()/update()/export() with padlock_sha_desc's fallback:
> 
> struct padlock_sha_desc {
>         struct shash_desc fallback;
> };
> 
> static struct shash_alg sha1_alg = {
>         .descsize       =       sizeof(struct padlock_sha_desc),
> 

Yeah. It still seems to me that padlock-sha has the same problem. Maybe
we are missing something...

--
Regards,
Marcelo

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply

* Re: [PATCH] padata: remove recently added module usage from bool code
From: Sebastian Andrzej Siewior @ 2016-09-27  9:03 UTC (permalink / raw)
  To: Paul Gortmaker
  Cc: linux-kernel, Steffen Klassert, Thomas Gleixner, linux-crypto
In-Reply-To: <20160927011821.6635-1-paul.gortmaker@windriver.com>

On 2016-09-26 21:18:21 [-0400], Paul Gortmaker wrote:
> 
> ...and so it currently is not being built as a module by anyone.

that is correct.

Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Sebastian

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Jan Stancek @ 2016-09-27  9:01 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Marcelo Cerri, rui y wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160927030826.GB8579@gondor.apana.org.au>





----- Original Message -----
> From: "Herbert Xu" <herbert@gondor.apana.org.au>
> To: "Marcelo Cerri" <marcelo.cerri@canonical.com>
> Cc: "Jan Stancek" <jstancek@redhat.com>, "rui y wang" <rui.y.wang@intel.com>, mhcerri@linux.vnet.ibm.com,
> leosilva@linux.vnet.ibm.com, pfsmorigo@linux.vnet.ibm.com, linux-crypto@vger.kernel.org,
> linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
> Sent: Tuesday, 27 September, 2016 5:08:26 AM
> Subject: Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
> 
> On Mon, Sep 26, 2016 at 02:43:17PM -0300, Marcelo Cerri wrote:
> > 
> > Wouldn't be enough to provide a pair of import/export functions as the
> > padlock-sha driver does?
> 
> I don't think that will help as ultimately you need to call the
> export function on the fallback and that's what requires the extra
> memory.  In fact very operation involving the fallback will need
> that extra memory too.

So, if we extended p8_ghash_desc_ctx to accommodate fallback_desc's ctx
and then provided statesize/import/export, would that be acceptable?

struct p8_ghash_desc_ctx {
        ...
        struct shash_desc fallback_desc;
+       char fallback_ctx[sizeof(struct ghash_desc_ctx)];


Also, does that mean that padlock_sha has similar problem?
It does not seem to reserve any space for fallback __ctx and it calls
init()/update()/export() with padlock_sha_desc's fallback:

struct padlock_sha_desc {
        struct shash_desc fallback;
};

static struct shash_alg sha1_alg = {
        .descsize       =       sizeof(struct padlock_sha_desc),

Regards,
Jan

> 
> Cheers,
> --
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> 

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Herbert Xu @ 2016-09-27  3:08 UTC (permalink / raw)
  To: Marcelo Cerri
  Cc: Jan Stancek, rui.y.wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160926174317.GA21317@gallifrey>

On Mon, Sep 26, 2016 at 02:43:17PM -0300, Marcelo Cerri wrote:
> 
> Wouldn't be enough to provide a pair of import/export functions as the
> padlock-sha driver does?

I don't think that will help as ultimately you need to call the
export function on the fallback and that's what requires the extra
memory.  In fact very operation involving the fallback will need
that extra memory too.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH v7 4/9] crypto: acomp - add support for lzo via scomp
From: Herbert Xu @ 2016-09-27  3:07 UTC (permalink / raw)
  To: Giovanni Cabiddu; +Cc: linux-crypto, weigang.li
In-Reply-To: <20160926172704.GA24726@SILVIXA00369791-F22-1>

On Mon, Sep 26, 2016 at 06:27:04PM +0100, Giovanni Cabiddu wrote:
>
> I think the definition of the acomp interface already allows for this.
> If the destination scatterlist inside the request is NULL, the
> algorithm/driver can allocate pages of memory for the output buffers as
> well as the scatterlist. In this case, the destination length, if not zero,
> could be used to specify the maximum size to allocate.
> What do you think?

Sounds good to me.  We should also add a function to free the
resulting SG list along with the allocated pages.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] padata: remove recently added module usage from bool code
From: Paul Gortmaker @ 2016-09-27  1:18 UTC (permalink / raw)
  To: linux-kernel
  Cc: Paul Gortmaker, Steffen Klassert, Thomas Gleixner,
	Sebastian Andrzej Siewior, linux-crypto

In commit 30e92153b4e6 ("padata: Convert to hotplug state machine")
this file started using module.h and got module_init and module_exit
added to it.

However the Kconfig for it is:

   init/Kconfig:config PADATA
   init/Kconfig:   depends on SMP
   init/Kconfig:   bool

...and so it currently is not being built as a module by anyone.

Lets remove the modular code that is essentially orphaned, so that
when reading the driver there is no doubt it is builtin-only.

Since module_init translates to device_initcall in the non-modular
case, the init ordering remains unchanged with this commit.

Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: linux-crypto@vger.kernel.org
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 kernel/padata.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/kernel/padata.c b/kernel/padata.c
index 7848f0566403..355807e52b1e 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -30,7 +30,7 @@
 #include <linux/slab.h>
 #include <linux/sysfs.h>
 #include <linux/rcupdate.h>
-#include <linux/module.h>
+#include <linux/init.h>
 
 #define MAX_OBJ_NUM 1000
 
@@ -1043,11 +1043,6 @@ static __init int padata_driver_init(void)
 	hp_online = ret;
 	return 0;
 }
-module_init(padata_driver_init);
+device_initcall(padata_driver_init);
 
-static __exit void padata_driver_exit(void)
-{
-	cpuhp_remove_multi_state(hp_online);
-}
-module_exit(padata_driver_exit);
 #endif
-- 
2.10.0

^ permalink raw reply related

* Re: [PATCH] crypto: sha1-powerpc: little-endian support
From: Paulo Flabiano Smorigo @ 2016-09-27  0:46 UTC (permalink / raw)
  To: Marcelo Cerri
  Cc: Herbert Xu, David S. Miller, linux-crypto, linuxppc-dev,
	linux-kernel, Benjamin Herrenschmidt, Paul Mackerras,
	Michael Ellerman, George Wilson, Claudio Carvalho,
	Paulo Flabiano Smorigo, joy.latten
In-Reply-To: <1474659116-4689-1-git-send-email-marcelo.cerri@canonical.com>

Fri, Sep 23, 2016 at 04:31:56PM -0300, Marcelo Cerri wrote:
> The driver does not handle endianness properly when loading the input
> data.

Indeed. I tested in both endianesses and it's working fine. Thanks!

Herbert, can we go ahead with this fix?

> 
> Signed-off-by: Marcelo Cerri <marcelo.cerri@canonical.com>
> ---
>  arch/powerpc/crypto/sha1-powerpc-asm.S | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/crypto/sha1-powerpc-asm.S b/arch/powerpc/crypto/sha1-powerpc-asm.S
> index 125e165..82ddc9b 100644
> --- a/arch/powerpc/crypto/sha1-powerpc-asm.S
> +++ b/arch/powerpc/crypto/sha1-powerpc-asm.S
> @@ -7,6 +7,15 @@
>  #include <asm/ppc_asm.h>
>  #include <asm/asm-offsets.h>
> 
> +#ifdef __BIG_ENDIAN__
> +#define LWZ(rt, d, ra)	\
> +	lwz	rt,d(ra)
> +#else
> +#define LWZ(rt, d, ra)	\
> +	li	rt,d;	\
> +	lwbrx	rt,rt,ra
> +#endif
> +
>  /*
>   * We roll the registers for T, A, B, C, D, E around on each
>   * iteration; T on iteration t is A on iteration t+1, and so on.
> @@ -23,7 +32,7 @@
>  #define W(t)	(((t)%16)+16)
> 
>  #define LOADW(t)				\
> -	lwz	W(t),(t)*4(r4)
> +	LWZ(W(t),(t)*4,r4)
> 
>  #define STEPD0_LOAD(t)				\
>  	andc	r0,RD(t),RB(t);		\
> @@ -33,7 +42,7 @@
>  	add	r0,RE(t),r15;			\
>  	add	RT(t),RT(t),r6;		\
>  	add	r14,r0,W(t);			\
> -	lwz	W((t)+4),((t)+4)*4(r4);	\
> +	LWZ(W((t)+4),((t)+4)*4,r4);	\
>  	rotlwi	RB(t),RB(t),30;			\
>  	add	RT(t),RT(t),r14
> 
> -- 
> 2.7.4
> 

-- 
Paulo Flabiano Smorigo
IBM Linux Technology Center

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Jan Stancek @ 2016-09-26 17:50 UTC (permalink / raw)
  To: Marcelo Cerri
  Cc: rui y wang, herbert, mhcerri, leosilva, pfsmorigo, linux-crypto,
	linuxppc-dev, linux-kernel
In-Reply-To: <20160926141510.GC5031@gallifrey>




----- Original Message -----
> From: "Marcelo Cerri" <marcelo.cerri@canonical.com>
> To: "Jan Stancek" <jstancek@redhat.com>
> Cc: "rui y wang" <rui.y.wang@intel.com>, herbert@gondor.apana.org.au, mhcerri@linux.vnet.ibm.com,
> leosilva@linux.vnet.ibm.com, pfsmorigo@linux.vnet.ibm.com, linux-crypto@vger.kernel.org,
> linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
> Sent: Monday, 26 September, 2016 4:15:10 PM
> Subject: Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
> 
> Hi Jan,
> 
> Just out of curiosity, have you tried to use "76" on both values to
> check if the problem still happens?

I did, I haven't seen any panics with such patch:

@@ -211,7 +212,7 @@ struct shash_alg p8_ghash_alg = {
        .update = p8_ghash_update,
        .final = p8_ghash_final,
        .setkey = p8_ghash_setkey,
-       .descsize = sizeof(struct p8_ghash_desc_ctx),
+       .descsize = sizeof(struct p8_ghash_desc_ctx) + 20,
        .base = {
                 .cra_name = "ghash",
                 .cra_driver_name = "p8_ghash",

^ permalink raw reply

* Re: [bug] crypto/vmx/p8_ghash memory corruption in 4.8-rc7
From: Marcelo Cerri @ 2016-09-26 17:43 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Jan Stancek, rui.y.wang, mhcerri, leosilva, pfsmorigo,
	linux-crypto, linuxppc-dev, linux-kernel
In-Reply-To: <20160926145934.GA5520@gondor.apana.org.au>

[-- Attachment #1: Type: text/plain, Size: 1430 bytes --]

Herbert,

Wouldn't be enough to provide a pair of import/export functions as the
padlock-sha driver does?

-- 
Regards,
Marcelo

On Mon, Sep 26, 2016 at 10:59:34PM +0800, Herbert Xu wrote:
> On Fri, Sep 23, 2016 at 08:22:27PM -0400, Jan Stancek wrote:
> >
> > This seems to directly correspond with:
> >   p8_ghash_alg.descsize = sizeof(struct p8_ghash_desc_ctx) == 56
> >   shash_tfm->descsize = sizeof(struct p8_ghash_desc_ctx) + crypto_shash_descsize(fallback) == 56 + 20
> > where 20 is presumably coming from "ghash_alg.descsize".
> > 
> > My gut feeling was that these 2 should match, but I'd love to hear
> > what crypto people think.
> 
> Indeed.  The vmx driver is broken.  It is allocating a fallback
> but is not providing any space for the state of the fallback.
> 
> Unfortunately our interface doesn't really provide a way to provide
> the state size dynamically.  So what I'd suggest is to fix the
> fallback to the generic ghash implementation and export its state
> size like we do for md5/sha.
> 
> Cheers,
> -- 
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply

* Re: sha1_mb broken
From: Stephan Mueller @ 2016-09-26 17:32 UTC (permalink / raw)
  To: Megha Dey; +Cc: linux-crypto
In-Reply-To: <1939675.7gNnqUbNs6@positron.chronox.de>

Am Freitag, 26. August 2016, 03:15:06 CEST schrieb Stephan Mueller:

Hi Megha,

> Hi,
> 
> I tried to execute tests with sha1_mb.

Have you had a chance to look into this one?
> 
> The execution simply stalls when invoking a digest operation -- i.e. the
> digest operation does not finish. After some time after invoking the hashing
> operation, the following log appears (note, the kccavs_* functions are my
> test code; that test code works perfectly well with all other hash
> implementations):
> 
> [  140.426026] INFO: rcu_sched detected stalls on CPUs/tasks:
> [  140.426719] 	2-...: (1 GPs behind) idle=9c3/140000000000000/0
> softirq=2680/2707 fqs=14762
> [  140.427024] 	(detected by 0, t=60002 jiffies, g=655, c=654, q=35)
> [  140.427024] Task dump for CPU 2:
> [  140.427024] cavs_driver     R  running task        0   945    862
> 0x00000008
> [  140.427024]  ffffffff9b78d965 ffffa527b8bfa640 ffffa527bb505940
> ffffa52775c20c50
> [  140.427024]  ffffa527bc300000 ffffa527b93d2a80 ffffa527bb857e00
> ffffa527bc2ffd78
> [  140.427024]  ffffa527b93d2ac8 ffffa527bc2ffcc0 ffffffff9b78dfc8
> ffffa527bc2ffd70
> [  140.427024] Call Trace:
> [  140.427024]  [<ffffffff9b78d965>] ? __schedule+0x245/0x690
> [  140.427024]  [<ffffffff9b78dfc8>] ? preempt_schedule_common+0x18/0x30
> [  140.427024]  [<ffffffff9b791a68>] ? _raw_spin_lock_irq+0x28/0x30
> [  140.427024]  [<ffffffff9b78ed98>] ? wait_for_completion_interruptible
> +0x28/0x180
> [  140.427024]  [<ffffffffc028541c>] ? sha1_mb_async_digest+0x6c/0x70
> [sha1_mb]
> [  140.427024]  [<ffffffff9b3b1129>] ? crypto_ahash_op+0x29/0x70
> [  140.427024]  [<ffffffffc0270148>] ? kccavs_test_ahash+0x198/0x2b0
> [kcapi_cavs]
> [  140.427024]  [<ffffffffc026e20a>] ? kccavs_data_read+0xda/0x160
> [kcapi_cavs]
> [  140.427024]  [<ffffffff9b370964>] ? full_proxy_read+0x54/0x90
> [  140.427024]  [<ffffffff9b208088>] ? __vfs_read+0x28/0x110
> [  140.427024]  [<ffffffff9b38a2c0>] ? security_file_permission+0xa0/0xc0
> [  140.427024]  [<ffffffff9b20850e>] ? rw_verify_area+0x4e/0xb0
> [  140.427024]  [<ffffffff9b208606>] ? vfs_read+0x96/0x130
> [  140.427024]  [<ffffffff9b2099f6>] ? SyS_read+0x46/0xa0
> [  140.427024]  [<ffffffff9b791cb6>] ? entry_SYSCALL_64_fastpath+0x1e/0xa8
> 
> 
> 
> Ciao
> Stephan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Ciao
Stephan

^ permalink raw reply

* Re: [PATCH v7 4/9] crypto: acomp - add support for lzo via scomp
From: Giovanni Cabiddu @ 2016-09-26 17:27 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto, weigang.li
In-Reply-To: <20160923150518.GA20384@gondor.apana.org.au>

On Fri, Sep 23, 2016 at 11:05:18PM +0800, Herbert Xu wrote:
> When I said acomp layer I'm referring specifically to the algorithm
> or driver.  As to your last question it would be the caller's
> responsibility to free that memory.
>
> The use-case is our oldest user, IPcomp.  Most packets are 1500 bytes
> max but we have to allocate 64K of memory to cover the worst case.
> For an algorithm that can deal with SG lists it can easily allocate
> pages of memory as it goes and place them in an SG list.
It is clear now. Thanks.

> Sure if you already have memory allocated then we don't want to
> force you to allocate it again in the algorithm/driver.  But our
> interface should allow the memory to be allocated in the driver.
I think the definition of the acomp interface already allows for this.
If the destination scatterlist inside the request is NULL, the
algorithm/driver can allocate pages of memory for the output buffers as
well as the scatterlist. In this case, the destination length, if not zero,
could be used to specify the maximum size to allocate.
What do you think?

--
Giovanni

^ permalink raw reply

* [PATCH v5 7/7] crypto: AES CBC multi-buffer tcrypt
From: Megha Dey @ 2016-09-26 17:27 UTC (permalink / raw)
  To: herbert, davem; +Cc: linux-crypto, tim.c.chen, megha.dey, Megha Dey
In-Reply-To: <1474910859-11713-1-git-send-email-megha.dey@linux.intel.com>

From: Tim Chen <tim.c.chen@linux.intel.com>

The tcrypt test framework for CBC multi-buffer testing is
laid out in this patch. Tcrypt has been extended to validate
the functionality and performance of AES CBC multi-buffer support.

A new test(mode=600) has been added to test the speed of the multibuffer
case, as multi-buffer encrypt will wait for additional encrypt requests
that never arrive to kick off computation. So we always incur the extra
delay before flush timer expires to trigger the computation in the (mode=500)
test. We create the new tests that will send out these additional requests
that can be aggregated and computed in parallel for true throughput speed test
of the multi-buffer encrypt test case.case.

The enhanced CBC tests create multiple transforms and exercise
the multi-buffer implementation. Crafted requests are sent at once
to the multiple transforms created and the returned responses
are compared with expected results. The test vectors are so chosen
as to exercise the scatter-gather list to the maximum allowable limit
within the framework.

Originally-by: Chandramouli Narayanan <mouli_7982@yahoo.com>
Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
---
 crypto/tcrypt.c  | 257 ++++++++++++++++++-
 crypto/testmgr.c | 759 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 crypto/testmgr.h |  64 ++++-
 3 files changed, 1054 insertions(+), 26 deletions(-)

diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index ae22f05..671f5bf 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -36,6 +36,7 @@
 #include <linux/jiffies.h>
 #include <linux/timex.h>
 #include <linux/interrupt.h>
+#include <linux/crypto.h>
 #include "tcrypt.h"
 
 /*
@@ -82,7 +83,7 @@ struct tcrypt_result {
 	int err;
 };
 
-static void tcrypt_complete(struct crypto_async_request *req, int err)
+void tcrypt_complete(struct crypto_async_request *req, int err)
 {
 	struct tcrypt_result *res = req->data;
 
@@ -181,6 +182,11 @@ static u32 aead_sizes[] = { 16, 64, 256, 512, 1024, 2048, 4096, 8192, 0 };
 
 #define XBUFSIZE 8
 #define MAX_IVLEN 32
+#define MB_WIDTH 8
+struct scatterlist mb_sg[MB_WIDTH][XBUFSIZE];
+struct skcipher_request *mb_req[MB_WIDTH];
+struct tcrypt_result mb_tresult[MB_WIDTH];
+char *mb_xbuf[MB_WIDTH][XBUFSIZE];
 
 static int testmgr_alloc_buf(char *buf[XBUFSIZE])
 {
@@ -778,6 +784,46 @@ static inline int do_one_acipher_op(struct skcipher_request *req, int ret)
 	return ret;
 }
 
+
+/*
+ * Perform a maximum of MB_WIDTH operations.
+ * Await the results and measure performance.
+ */
+cycles_t mb_start, mb_end;
+static int mb_err[MB_WIDTH];
+
+static inline int do_multi_acipher_op(
+	struct skcipher_request *req[MB_WIDTH], int enc)
+{
+	int i, ret, comp_ret = 0;
+	bool is_async;
+
+	for (i = 0; i < MB_WIDTH; ++i) {
+		ret = enc == ENCRYPT ? crypto_skcipher_encrypt(req[i])
+					: crypto_skcipher_decrypt(req[i]);
+		mb_err[i] = ret;
+		if (ret == -EINPROGRESS || ret == -EBUSY)
+			continue; /* on with next req */
+		/* any other error, bail out */
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < MB_WIDTH; ++i) {
+		struct tcrypt_result *tr = req[i]->base.data;
+
+		is_async = mb_err[i] == -EINPROGRESS || mb_err[i] == -EBUSY;
+		if (is_async) {
+			wait_for_completion(&tr->completion);
+			reinit_completion(&tr->completion);
+		}
+		comp_ret = tr->err;
+		if (comp_ret)
+			pr_info("multi_acipher_op error\n");
+	}
+
+	return comp_ret;
+}
+
 static int test_acipher_jiffies(struct skcipher_request *req, int enc,
 				int blen, int secs)
 {
@@ -925,6 +971,7 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs,
 			if (ret) {
 				pr_err("setkey() failed flags=%x\n",
 					crypto_skcipher_get_flags(tfm));
+
 				goto out_free_req;
 			}
 
@@ -978,6 +1025,203 @@ out:
 	crypto_free_skcipher(tfm);
 }
 
+static int test_mb_acipher_jiffies(
+	struct skcipher_request *req[MB_WIDTH], int enc, int blen, int secs)
+{
+	unsigned long start, end;
+	int bcount;
+	int ret;
+
+	/* initiate a maximum of MB_WIDTH operations and measure performance */
+	for (start = jiffies, end = start + secs * HZ, bcount = 0;
+		time_before(jiffies, end); bcount += MB_WIDTH) {
+		ret = do_multi_acipher_op(req, enc);
+		if (ret)
+		return ret;
+	}
+
+	pr_cont("%d operations in %d seconds (%ld bytes)\n",
+		bcount, secs, (long)bcount * blen);
+	return 0;
+}
+
+#define ITR 8
+static int test_mb_acipher_cycles(
+	struct skcipher_request *req[MB_WIDTH], int enc, int blen)
+{
+	cycles_t cycles = 0;
+	int ret = 0;
+	int i;
+
+	/* Warm-up run. */
+	for (i = 0; i < 4; i++) {
+		ret = do_multi_acipher_op(req, enc);
+
+		if (ret)
+			goto out;
+	}
+	/*
+	 * Initiate a maximum of MB_WIDTH operations per loop
+	 * Measure performance over MB_WIDTH iterations
+	 * Let do_multi_acipher_op count the cycles
+	 */
+	for (i = 0; i < ITR; i++) {
+		mb_start = get_cycles();
+		ret = do_multi_acipher_op(req, enc);
+
+		mb_end = get_cycles();
+		cycles += mb_end - mb_start;
+		if (ret)
+			goto out;
+	}
+
+out:
+	if (ret == 0)
+		pr_cont("1 operation in %llu cycles (%d bytes)\n",
+			(cycles + 4) / (ITR*MB_WIDTH), blen);
+
+	return ret;
+}
+
+static void test_mb_acipher_speed(const char *algo, int enc, unsigned int secs,
+				struct cipher_speed_template *template,
+				unsigned int tcount, u8 *keysize)
+{
+	unsigned int ret, i, j, k, iv_len, r;
+	const char *key;
+	char iv[128];
+	struct crypto_skcipher *tfm;
+	const char *e, *driver;
+	u32 *b_size;
+
+	pr_info("test_mb_acipher_speed: test algo %s\n", algo);
+	if (enc == ENCRYPT)
+		e = "encryption";
+	else
+		e = "decryption";
+
+	tfm = crypto_alloc_skcipher(algo, 0, 0);
+
+	if (IS_ERR(tfm)) {
+		pr_err("failed to load transform for %s: %ld\n", algo,
+			PTR_ERR(tfm));
+		return;
+	}
+
+       /* FIXME: do we need to check this? */
+	driver = get_driver_name(crypto_skcipher, tfm);
+	pr_info("\ntesting speed of async %s (%s) %s\n", algo, driver, e);
+
+	/* set up multiple requests for the transform */
+	for (r = 0; r < MB_WIDTH; ++r) {
+		init_completion(&mb_tresult[r].completion);
+		mb_req[r] = skcipher_request_alloc(tfm, GFP_KERNEL);
+		if (!mb_req[r]) {
+			pr_err("tcrypt: skcipher: Failed to allocate request for %s\n",
+					algo);
+			goto out;
+		}
+
+		skcipher_request_set_callback(mb_req[r],
+				CRYPTO_TFM_REQ_MAY_BACKLOG,
+				tcrypt_complete, &mb_tresult[r]);
+	}
+
+	/* loop through different data sizes to encrypt/decrypt */
+	i = 0;
+	do {
+		b_size = block_sizes;
+
+		do {
+			if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
+				pr_err("template (%u) too big for tvmem (%lu)\n",
+				*keysize + *b_size, TVMEMSIZE * PAGE_SIZE);
+				goto out_free_req;
+			}
+
+			pr_info("test %u (%d bit key, %d byte blocks): ", i,
+					*keysize * 8, *b_size);
+
+			memset(tvmem[0], 0xff, PAGE_SIZE);
+
+			/* set key, plain text and IV */
+			key = tvmem[0];
+			for (j = 0; j < tcount; j++) {
+				if (template[j].klen == *keysize) {
+					key = template[j].key;
+					break;
+				}
+			}
+
+			crypto_skcipher_clear_flags(tfm, ~0);
+
+			ret = crypto_skcipher_setkey(tfm, key, *keysize);
+			if (ret) {
+				pr_err("setkey() failed flags=%x keysize=%d\n",
+					crypto_skcipher_get_flags(tfm),
+					*keysize);
+				goto out_free_req;
+			}
+
+			/* set scatter-gather list of data */
+			for (r = 0; r < MB_WIDTH; ++r) {
+				sg_init_table(mb_sg[r], TVMEMSIZE);
+
+				k = *keysize + *b_size;
+				if (k > PAGE_SIZE) {
+					sg_set_buf(mb_sg[r],
+							tvmem[0] + *keysize,
+							PAGE_SIZE - *keysize);
+					k -= PAGE_SIZE;
+					j = 1;
+					while (k > PAGE_SIZE) {
+						sg_set_buf(&mb_sg[r][j],
+							tvmem[j], PAGE_SIZE);
+						memset(tvmem[j], 0xff,
+								PAGE_SIZE);
+						j++;
+						k -= PAGE_SIZE;
+					}
+					sg_set_buf(&mb_sg[r][j], tvmem[j], k);
+					memset(tvmem[j], 0xff, k);
+				} else {
+					sg_set_buf(mb_sg[r],
+						tvmem[0] + *keysize, *b_size);
+				}
+
+				iv_len = crypto_skcipher_ivsize(tfm);
+				if (iv_len)
+					memset(&iv, 0xff, iv_len);
+
+				skcipher_request_set_crypt(mb_req[r],
+						mb_sg[r], mb_sg[r],
+						*b_size, iv);
+			}
+			if (secs)
+				ret = test_mb_acipher_jiffies(mb_req, enc,
+						*b_size, secs);
+			else
+				ret = test_mb_acipher_cycles(mb_req, enc,
+						*b_size);
+
+			if (ret) {
+				pr_err("%s() failed flags=%x\n", e,
+					crypto_skcipher_get_flags(tfm));
+				break;
+			}
+			b_size++;
+			i++;
+		} while (*b_size);
+		keysize++;
+	} while (*keysize);
+
+out_free_req:
+	for (r = 0; r < MB_WIDTH; ++r)
+		skcipher_request_free(mb_req[r]);
+out:
+	crypto_free_skcipher(tfm);
+}
+
 static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
 			       struct cipher_speed_template *template,
 			       unsigned int tcount, u8 *keysize)
@@ -2035,6 +2279,17 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
 				   speed_template_8_32);
 		break;
 
+	case 600:
+		/* Measure performance of aes-cbc multibuffer support */
+		test_mb_acipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0,
+			speed_template_16_24_32);
+		test_mb_acipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
+			speed_template_16_24_32);
+		break;
+	case 601:
+		ret += tcrypt_test("cbc(aes)");
+		break;
+
 	case 1000:
 		test_available();
 		break;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 0b01c3d..a26b9b0 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1,3 +1,4 @@
+
 /*
  * Algorithm testing framework and tests.
  *
@@ -146,6 +147,23 @@ struct alg_test_desc {
 
 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 
+#ifdef CONFIG_CRYPTO_AES_CBC_MB
+/*
+ * Indexes into the xbuf to simulate cross-page access for multibuffer tests.
+ */
+#define MB_IDX1                32
+#define MB_IDX2                32400
+#define MB_IDX3                4222
+#define MB_IDX4                8193
+#define MB_IDX5                22222
+#define MB_IDX6                17101
+#define MB_IDX7                27333
+#define MB_IDX8                13222
+static unsigned int MB_IDX[8] = {
+	MB_IDX1, MB_IDX2, MB_IDX3, MB_IDX4,
+	MB_IDX5, MB_IDX6, MB_IDX7, MB_IDX8 };
+#endif /* CONFIG_CRYPTO_AES_CBC_MB */
+
 static void hexdump(unsigned char *buf, unsigned int len)
 {
 	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
@@ -383,7 +401,7 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
 		ret = -EINVAL;
 		for (k = 0; k < template[i].np; k++) {
 			if (WARN_ON(offset_in_page(IDX[k]) +
-				    template[i].tap[k] > PAGE_SIZE))
+				   template[i].tap[k] > PAGE_SIZE))
 				goto out;
 			sg_set_buf(&sg[k],
 				   memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
@@ -1025,30 +1043,33 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
 			crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 
 		ret = crypto_cipher_setkey(tfm, template[i].key,
-					   template[i].klen);
+				template[i].klen);
 		if (template[i].fail == !ret) {
 			printk(KERN_ERR "alg: cipher: setkey failed "
-			       "on test %d for %s: flags=%x\n", j,
-			       algo, crypto_cipher_get_flags(tfm));
+					"on test %d for %s: flags=%x\n", j,
+					algo, crypto_cipher_get_flags(tfm));
 			goto out;
 		} else if (ret)
 			continue;
 
 		for (k = 0; k < template[i].ilen;
-		     k += crypto_cipher_blocksize(tfm)) {
+				k += crypto_cipher_blocksize(tfm)) {
 			if (enc)
 				crypto_cipher_encrypt_one(tfm, data + k,
-							  data + k);
+						data + k);
 			else
 				crypto_cipher_decrypt_one(tfm, data + k,
-							  data + k);
+						data + k);
 		}
 
 		q = data;
 		if (memcmp(q, template[i].result, template[i].rlen)) {
 			printk(KERN_ERR "alg: cipher: Test %d failed "
-			       "on %s for %s\n", j, e, algo);
+					"on %s for %s\n", j, e, algo);
 			hexdump(q, template[i].rlen);
+			printk(KERN_ERR "alg: cipher: Test %d expected on %s for %s\n",
+				j, e, algo);
+			hexdump(template[i].result, template[i].rlen);
 			ret = -EINVAL;
 			goto out;
 		}
@@ -1180,8 +1201,14 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
 			pr_err("alg: skcipher%s: Test %d failed (invalid result) on %s for %s\n",
 			       d, j, e, algo);
 			hexdump(q, template[i].rlen);
+			pr_err("alg: skcipher%s: Test %d expected %s for %s\n",
+				d, j, e, algo);
+			hexdump(template[i].result, template[i].rlen);
 			ret = -EINVAL;
 			goto out;
+		pr_err("alg: skcipher%s: Test %d expected %s for %s\n",
+				d, j, e, algo);
+			hexdump(template[i].result, template[i].rlen);
 		}
 
 		if (template[i].iv_out &&
@@ -1296,9 +1323,18 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
 			if (memcmp(q, template[i].result + temp,
 				   template[i].tap[k])) {
 				pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
-				       d, j, e, k, algo);
+					d, j, e, k, algo);
 				hexdump(q, template[i].tap[k]);
+				pr_err(
+	"alg: skcipher%s: Chunk test %d expected on %s at page %u for %s\n",
+					d, j, e, k, algo);
+				hexdump(template[i].result + temp,
+					template[i].tap[k]);
 				goto out;
+			} else {
+				pr_err(
+	"alg: skcipher%s: Chunk test %d succeeded on %s at page %u for %s klen %d\n",
+					d, j, e, k, algo, template[i].klen);
 			}
 
 			q += template[i].tap[k];
@@ -1558,29 +1594,718 @@ out:
 	return err;
 }
 
+#ifdef CONFIG_CRYPTO_AES_CBC_MB
+/*
+ * AES CBC multibuffer implementation can encrypt
+ * a maximum of 8 requests at once. Therefore, the
+ * MAX_REQ should be set >= 8 for better performance.
+ * The MAX_XFM allows multiple transforms created within
+ * the test framework.
+ *
+ * The multibuffer tests set up several requests and
+ * hand them off to the multibuffer driver. Error processing
+* does not simply bail out. The test code walks through all
+ * requests and awaits their completion. Indiscriminate premature
+ * bailout on error while other requests are in progress will cause
+ * trouble.
+ */
+
+#define MAX_REQ        16
+#define MAX_XFM        MAX_REQ
+static struct skcipher_request *mb_req[MAX_REQ][MAX_REQ];
+static struct scatterlist mb_sg[MAX_REQ][MAX_REQ][8];
+static struct scatterlist mb_sgout[MAX_REQ][MAX_REQ][8];
+static struct tcrypt_result mb_result[MAX_REQ][MAX_REQ];
+static char *mb_xbuf[MAX_REQ][MAX_REQ][XBUFSIZE];
+static char *mb_xoutbuf[MAX_REQ][MAX_REQ][XBUFSIZE];
+static int mb_err[MAX_REQ][MAX_REQ];
+static char ivec[MAX_REQ][MAX_REQ][MAX_IVLEN];
+/* random data for cbc multibuffer tests */
+static struct cipher_test_suite mb_cbc_cipher[] = {
+	{
+		{
+			.vecs = aes_cbc_enc_tv_template_rnddata_klenmix,
+			.count = AES_CBC_ENC_TV_TEMPLATE_RNDDATA_KEY16_VEC_COUNT
+		},
+		{
+			.vecs = aes_cbc_dec_tv_template_rnddata_klen16,
+			.count = AES_CBC_DEC_TV_TEMPLATE_RNDDATA_KEY16_VEC_COUNT
+		}
+	},
+};
+
+/*
+ * Test multibuffer version AES CBC crypto algorithm via multiple transforms.
+ * The test iterates through a set of MAX_REQ requests with identical key,
+ * but unique input and IV.
+ */
+
+/*
+ * Test multibuffer version AES CBC crypto algorithm via multiple transforms.
+ * The test iterates through the test vectors sending MAX_REQ requests with
+ * the same vector and IV.
+ */
+/* free buffers allocated for testing multibuffer cbc */
+
+static void free_mbxbuf(int tidx)
+{
+	int i;
+
+	for (i = 0; i < MAX_REQ; ++i) {
+		if (mb_xbuf[tidx][i])
+			testmgr_free_buf(mb_xbuf[tidx][i]);
+	}
+}
+
+/* free  MAX_REQ mb_xout buffers for a given transform */
+
+static void free_mbxoutbuf(int tidx)
+{
+	int i;
+
+	for (i = 0; i < MAX_REQ; ++i) {
+		if (mb_xoutbuf[tidx][i])
+			testmgr_free_buf(mb_xoutbuf[tidx][i]);
+	}
+}
+
+/* free MAX_REQ requests for a given transform */
+
+static void free_mbreq(int tidx)
+{
+	int i;
+
+	for (i = 0; i < MAX_REQ; ++i)
+		skcipher_request_free(mb_req[tidx][i]);
+}
+
+/* For a given transform, allocate buffers to test multibuffer cbc */
+
+static int allocbuf_mb(int tidx, struct crypto_skcipher *tfm,
+			const bool diff_dst, const char *algo)
+{
+	int r, n, err = 0;
+	char *ybuf[XBUFSIZE];
+
+	for (r = 0; r < MAX_REQ; ++r) {
+		if (testmgr_alloc_buf(ybuf))
+			goto out_nobuf;
+
+		for (n = 0; n < XBUFSIZE; ++n)
+			mb_xbuf[tidx][r][n] = ybuf[n];
+
+		if (diff_dst) {
+			if (testmgr_alloc_buf(ybuf))
+				goto out_nooutbuf;
+			for (n = 0; n < XBUFSIZE; ++n)
+				mb_xoutbuf[tidx][r][n] = ybuf[n];
+		}
+
+		init_completion(&mb_result[tidx][r].completion);
+
+		mb_req[tidx][r] = skcipher_request_alloc(
+				tfm,
+				GFP_KERNEL);
+		if (!mb_req[tidx][r]) {
+			err = -ENOMEM;
+			pr_err(
+				"alg: __test_skcipher: Failed to allocate request for %s\n",
+				algo);
+			goto out;
+		}
+		skcipher_request_set_callback(mb_req[tidx][r],
+			CRYPTO_TFM_REQ_MAY_BACKLOG,
+			tcrypt_complete, &mb_result[tidx][r]);
+	}
+	return 0;
+
+out:
+	free_mbreq(tidx);
+	if (diff_dst)
+		free_mbxoutbuf(tidx);
+
+out_nooutbuf:
+	free_mbxbuf(tidx);
+
+out_nobuf:
+	return err;
+}
+
+static void set_mb_input(unsigned int tidx, unsigned int vidx,
+			struct cipher_testvec *template,
+			const int align_offset, bool uniq_vec)
+{
+	void *data;
+	struct cipher_testvec *tvec;
+
+	tvec = &template[vidx] + tidx;
+	data = mb_xbuf[tidx][0][0];
+	data += align_offset;
+	memcpy(data, tvec->input, tvec->ilen);
+}
+
+static void send_mb_req(int tidx, unsigned int vidx, int enc,
+			const bool diff_dst, const int align_offset,
+			struct cipher_testvec *template, bool uniq_vec,
+			const char *algo)
+{
+	int ret;
+	void *data;
+	char *iv, *d, *e;
+	unsigned short ilen;
+	struct cipher_testvec *tvec;
+	char *thisiv;
+
+	tvec = &template[vidx] + tidx;
+	iv = tvec->iv;
+	ilen = tvec->ilen;
+	if (diff_dst)
+		d = "-ddst";
+	else
+		d = "";
+
+	if (enc == ENCRYPT)
+		e = "encryption";
+	else
+		e = "decryption";
+
+	memset(&mb_err[tidx][0], 0, MAX_REQ); /* no error to begin with */
+
+	data = mb_xbuf[tidx][0][0];
+	data += align_offset;
+	sg_init_one(&mb_sg[tidx][0][0], data, ilen);
+	if (diff_dst) {
+		data = mb_xoutbuf[tidx][0][0];
+		data += align_offset;
+		sg_init_one(&mb_sgout[tidx][0][0], data, ilen);
+	}
+
+	thisiv = ivec[tidx][0];
+	memcpy(thisiv, iv, MAX_IVLEN);
+	skcipher_request_set_crypt(
+			mb_req[tidx][0],
+			mb_sg[tidx][0],
+			(diff_dst) ? mb_sgout[tidx][0]
+			: mb_sg[tidx][0],
+			ilen, thisiv);
+	ret = enc ?
+		crypto_skcipher_encrypt(
+				mb_req[tidx][0])
+		:
+		crypto_skcipher_decrypt(
+				mb_req[tidx][0]);
+
+	if (ret == -EINPROGRESS || ret == -EBUSY || ret == 0) {
+		/* deal with return status properly */
+		mb_err[tidx][0] = ret;
+	} else if (ret) {
+		unsigned int id;
+
+		mb_err[tidx][0] = ret;
+		id = vidx;
+		/* error */
+		pr_err("skcipher%s: %s failed on test %d for %s: ret=%d\n",
+				d, e, id, algo, -ret);
+		pr_err("skcipher%s: req=%d failed\n",
+				d, tidx);
+	}
+}
+
+static void await_mb_result(int tidx)
+{
+	int ret;
+	struct tcrypt_result *tr = &mb_result[tidx][0];
+
+	if (mb_err[tidx][0]) {
+		if (mb_err[tidx][0] != -EINPROGRESS &&
+				mb_err[tidx][0] != -EBUSY) {
+			pr_err("skcipher error\n"); /* skip reqs that failed */
+			return;
+		}
+		/* wait on async completions */
+		wait_for_completion(&tr->completion);
+		ret = tr->err;
+		mb_err[tidx][0] = ret;
+		if (!ret) {
+			/* no error, on with next */
+			reinit_completion(&tr->completion);
+		} else {
+			pr_err("skcipher: xfm=%d completion error %d\n",
+					tidx, ret);
+		}
+	}
+	/* no wait on synchronous completions */
+}
+
+static void check_mb_result(int tidx, unsigned int vidx, int enc,
+			const bool diff_dst, const int align_offset,
+			struct cipher_testvec *template, bool uniq_vec,
+			const char *algo)
+{
+	void *data;
+	char *q, *d, *e;
+	struct cipher_testvec *tvec;
+
+	tvec = &template[vidx] + tidx;
+	if (diff_dst)
+		d = "-ddst";
+	else
+		d = "";
+
+	if (enc == ENCRYPT)
+		e = "encryption";
+	else
+		e = "decryption";
+
+
+	/* the request resulted in error, move on */
+	if (mb_err[tidx][0])
+		return;
+
+	if (diff_dst) {
+		data = mb_xoutbuf[tidx][0][0];
+		data += align_offset;
+	} else {
+		data = mb_xbuf[tidx][0][0];
+		data += align_offset;
+	}
+	q = data;
+	if (memcmp(q, tvec->result, tvec->rlen)) {
+		pr_err("skcipher%s: Test %d(%d) failed on %s for %s\n",
+				d, tidx, vidx, e, algo);
+		pr_err("skcipher: xfm=%d result mismatch\n",
+				tidx);
+		pr_err("Expected result for xfm=%d\n", tidx);
+		hexdump(tvec->result,
+				tvec->rlen);
+		pr_err("Encountered result for xfm=%d\n",
+				tidx);
+		hexdump(q, tvec->rlen);
+	} else {
+		pr_err("skcipher%s: Test %d(%d) succeeded on %s for %s\n",
+				d, tidx, vidx, e, algo);
+	}
+}
+
+static void check_mb_sg_result(int tidx, unsigned int vidx, int enc,
+			bool diff_dst, struct cipher_testvec *template,
+			bool uniq_vec, const char *algo)
+{
+	unsigned int k, n;
+	unsigned int temp;
+	char *q, *d, *e;
+	struct cipher_testvec *tvec;
+	unsigned int cor_pg, cor_bytes;
+	unsigned int id; /* test id */
+
+	tvec = &template[vidx] + tidx;
+	if (diff_dst)
+		d = "-ddst";
+	else
+		d = "";
+
+	if (enc == ENCRYPT)
+		e = "encryption";
+	else
+		e = "decryption";
+
+	temp = 0;
+	id = vidx;
+	if (mb_err[tidx][0])
+		return; /* on with other reqs */
+	for (k = 0; k < tvec->np; k++) {
+		unsigned int pg;
+
+		pg = MB_IDX[k] >> PAGE_SHIFT;
+		if (diff_dst)
+			q = mb_xoutbuf[tidx][0][pg] +
+				offset_in_page(MB_IDX[k]);
+		else
+			q = mb_xbuf[tidx][0][pg] +
+				offset_in_page(MB_IDX[k]);
+
+		cor_bytes = tvec->tap[k];
+		cor_pg = k;
+		if (memcmp(q, tvec->result + temp, tvec->tap[k])) {
+			pr_err(
+				"skcipher%s: chunk test %d failed/corruption %s @pg %u for %s:%u bytes:\n",
+					d, id, e, cor_pg, algo, cor_bytes);
+			hexdump(q, cor_bytes);
+			return;
+		}
+		pr_err(
+			"skcipher%s: chunk test %d succeeded %s @pg %u for %s:%u bytes:\n",
+				d, id, e, cor_pg, algo, cor_bytes);
+
+		q += tvec->tap[k];
+		for (n = 0; offset_in_page(q + n) && q[n]; n++)
+			;
+		if (n) {
+			cor_bytes = n;
+			cor_pg = k;
+			pr_err(
+				"skcipher%s: chunk test %d result corruption %s @pg %u for %s:%u bytes:\n",
+					d, id, e, cor_pg, algo, cor_bytes);
+			hexdump(q, cor_bytes);
+			break; /* on with next request */
+		}
+		temp += tvec->tap[k];
+	}
+}
+
+static void send_mb_sg_req(int tidx, unsigned int vidx, int enc,
+			   bool diff_dst, struct cipher_testvec *template,
+			   bool uniq_vec, const char *algo)
+{
+	unsigned int k, n;
+	unsigned int temp;
+	int ret;
+	char *q, *d, *e;
+	char *ybuf[XBUFSIZE];
+	struct cipher_testvec *tvec;
+	char *thisiv;
+
+	tvec = &template[vidx] + tidx;
+	if (diff_dst)
+		d = "-ddst";
+	else
+		d = "";
+
+	if (enc == ENCRYPT)
+		e = "encryption";
+	else
+		e = "decryption";
+
+	memset(&mb_err[tidx][0], 0, MAX_REQ);
+
+	temp = 0;
+	sg_init_table(&mb_sg[tidx][0][0], tvec->np);
+	if (diff_dst)
+		sg_init_table(&mb_sgout[tidx][0][0], tvec->np);
+
+	for (k = 0; k < tvec->np; ++k) {
+		unsigned int pg;
+
+		if (WARN_ON((offset_in_page(MB_IDX[k]) + tvec->tap[k]) >
+					PAGE_SIZE)) {
+			pr_err("skcipher%s: %s Invalid sg for %s\n",
+					d, e, algo);
+			pr_err("offset + tap(%d) > PAGE_SIZE(%lu)\n",
+					tvec->tap[k], PAGE_SIZE);
+			pr_err("req=%d k=%d tap(%d)\n",
+					tidx, k, tvec->tap[k]);
+			break;  /* skip this */
+		}
+
+		for (n = 0; n < XBUFSIZE; ++n)
+			ybuf[n] = mb_xbuf[tidx][0][n];
+		pg = MB_IDX[k] >> PAGE_SHIFT;
+		q = ybuf[pg] + offset_in_page(MB_IDX[k]);
+
+		memcpy(q, tvec->input + temp, tvec->tap[k]);
+
+		if ((offset_in_page(q) + tvec->tap[k]) < PAGE_SIZE)
+			q[tvec->tap[k]] = 0;
+
+		sg_set_buf(&mb_sg[tidx][0][k], q, tvec->tap[k]);
+		if (diff_dst) {
+			unsigned int segs;
+
+			segs = tvec->tap[k];
+			q = mb_xoutbuf[tidx][0][pg] +
+				offset_in_page(MB_IDX[k]);
+
+			sg_set_buf(&mb_sgout[tidx][0][k], q, segs);
+
+			memset(q, 0, tvec->tap[k]);
+			if ((offset_in_page(q) + tvec->tap[k]) <
+					PAGE_SIZE)
+				q[segs] = 0;
+		}
+
+		temp += tvec->tap[k];
+	}
+
+	thisiv = ivec[tidx][0];
+	memcpy(thisiv, tvec->iv, MAX_IVLEN);
+	skcipher_request_set_crypt(
+			mb_req[tidx][0],
+			&mb_sg[tidx][0][0],
+			(diff_dst) ? &mb_sgout[tidx][0][0]
+			: &mb_sg[tidx][0][0],
+			tvec->ilen,
+			thisiv);
+
+	ret = enc ? crypto_skcipher_encrypt(
+			mb_req[tidx][0])
+		: crypto_skcipher_decrypt(
+				mb_req[tidx][0]);
+
+	if (ret == -EBUSY || ret == -EINPROGRESS || ret == 0) {
+		/* deal with return status properly */
+		mb_err[tidx][0] = ret;
+		if (uniq_vec)
+			++tvec;
+	} else if (ret) {
+		mb_err[tidx][0] = ret;
+		pr_err("skcipher%s: xfm=%d failed for %s algo %s\n",
+				d, tidx, e, algo);
+	}
+}
+
+static int __test_mb_skcipher(struct crypto_skcipher *tfm[MAX_REQ],
+			      int enc, struct cipher_testvec *template,
+			      unsigned int tcount,
+			      const bool diff_dst, const int align_offset)
+{
+	const char *algo;
+	unsigned int i, j;
+	const char *e, *d;
+	int ret = -ENOMEM;
+	bool sent[MAX_REQ];
+
+	/* same algorithm, multiple xfms */
+	algo = crypto_tfm_alg_driver_name(
+			crypto_skcipher_tfm(tfm[0]));
+
+	memset(mb_xbuf, '\0', sizeof(mb_xbuf));
+	memset(mb_xoutbuf, '\0', sizeof(mb_xoutbuf));
+
+	for (i = 0; i < MAX_REQ; ++i) {
+		if (allocbuf_mb(i, tfm[i], diff_dst, algo))
+			goto out_nobuf;
+	}
+
+	if (diff_dst)
+		d = "-ddst";
+	else
+		d = "";
+
+	if (enc == ENCRYPT)
+		e = "encryption";
+	else
+		e = "decryption";
+
+	for (i = 0; i < MAX_REQ; ++i)
+		sent[i] = false;
+
+	/* multi xfm, and send multi requests for all xfms and await results */
+	j = 0;
+	for (i = 0; i < tcount; i++) {
+		if (template[i].np && !template[i].also_non_np)
+			continue;
+		/* ensure that the vector data is within page size */
+		if (template[i].ilen > PAGE_SIZE)
+			continue;
+
+		ret = -EINVAL;
+		if (WARN_ON(align_offset + template[i].ilen > PAGE_SIZE))
+			goto out;
+
+		/* set the data for multiple xfms */
+		set_mb_input(i, 0, template,
+				align_offset, false);
+
+		/*
+		 * Set the key for multiple xfms.
+		 * To proceed with test all xfms should be successful
+		 */
+
+		crypto_skcipher_clear_flags(tfm[i], ~0);
+		if (template[i].wk)
+			crypto_skcipher_set_flags(tfm[i],
+					CRYPTO_TFM_REQ_WEAK_KEY);
+
+		ret = crypto_skcipher_setkey(tfm[i], template[i].key,
+				template[i].klen);
+		if (!ret == template[i].fail) {
+			pr_err(
+					"alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
+					d, i, algo,
+					crypto_skcipher_get_flags(tfm[i]));
+			goto out;
+		} else if (ret)
+			break;
+		/* move on to next test if key could not be setup */
+		if (ret)
+			continue;
+
+		j++;
+
+		sent[i] = true;
+		send_mb_req(i, 0, enc, diff_dst, align_offset,
+				template, false, algo);
+
+	}
+	/* await results from multiple requests from multiple xfms */
+	for (i = 0; i < tcount; ++i) {
+		if (sent[i])
+			await_mb_result(i);
+	}
+
+	/* check results from multiple requests from multiple xfms */
+	for (i = 0; i < tcount; ++i) {
+		if (sent[i])
+			check_mb_result(i, 0, enc, diff_dst,
+					align_offset, template, false, algo);
+		sent[i] = false;
+	}
+
+	j = 0;
+	for (i = 0; i < tcount; i++) {
+		/* alignment tests are only done with continuous buffers */
+
+		if (align_offset != 0)
+			break;
+		if (!template[i].np)
+			continue;
+
+		j++;
+		/* set the key for multiple transforms */
+		crypto_skcipher_clear_flags(tfm[i], ~0);
+		if (template[i].wk)
+			crypto_skcipher_set_flags(
+					tfm[i],
+					CRYPTO_TFM_REQ_WEAK_KEY);
+
+		ret = crypto_skcipher_setkey(tfm[i], template[i].key,
+				template[i].klen);
+		if (!ret == template[i].fail) {
+			pr_err(
+					"skcipher%s: setkey failed on chunk test %d xfm=%d for %s: flags=%x\n",
+					d, j, i, algo,
+					crypto_skcipher_get_flags(tfm[i]));
+			goto out;
+		} else if (ret)
+			break;
+		if (ret)
+			continue; /* on to next test */
+
+		/* iterate the test over multiple requests & xfms */
+
+		sent[i] = true;
+		send_mb_sg_req(i, 0, enc, diff_dst,
+				template, false, algo);
+	}
+
+	/* wait for completion from all xfms */
+	for (i = 0; i < tcount; ++i) {
+		if (sent[i])
+			await_mb_result(i);
+	}
+
+	/* check results from all xfms */
+	for (i = 0; i < tcount; ++i) {
+		if (sent[i])
+			check_mb_sg_result(i, 0, enc, diff_dst,
+					template, false, algo);
+	}
+
+	ret = 0;
+out:
+	for (i = 0; i < MAX_REQ; ++i)
+		free_mbreq(i);
+
+	if (diff_dst) {
+		for (i = 0; i < MAX_REQ; ++i)
+			free_mbxoutbuf(i);
+	}
+	for (i = 0; i < MAX_REQ; ++i)
+		free_mbxbuf(i);
+
+out_nobuf:
+	return ret;
+}
+
+static int test_mb_skcipher(struct crypto_skcipher *tfm[MAX_XFM],
+			    int enc, struct cipher_testvec *template,
+			    unsigned int tcount)
+{
+	int ret;
+
+	/* test 'dst == src' case */
+	ret = __test_mb_skcipher(tfm, enc, template, tcount, false, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int alg_test_mb_skcipher(const struct alg_test_desc *desc,
+				const char *driver, u32 type, u32 mask)
+{
+	struct crypto_skcipher *tfm[MAX_REQ];
+	int err = 0;
+	int i;
+
+	/* create multiple transforms to test AES CBC */
+	for (i = 0; i < MAX_REQ; i++) {
+		tfm[i] = crypto_alloc_skcipher(driver,
+				type | CRYPTO_ALG_INTERNAL, mask);
+		if (IS_ERR(tfm[i])) {
+			printk(KERN_ERR "alg: skcipher: Failed to load transform for %s: %ld\n",
+					driver, PTR_ERR(tfm[i]));
+			return PTR_ERR(tfm[i]);
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mb_cbc_cipher); ++i) {
+		err = test_mb_skcipher(
+				tfm,
+				ENCRYPT,
+				mb_cbc_cipher[i].enc.vecs,
+				mb_cbc_cipher[i].enc.count
+				);
+		if (err)
+			goto out;
+
+		err = test_mb_skcipher(
+				tfm,
+				DECRYPT,
+				mb_cbc_cipher[i].dec.vecs,
+				mb_cbc_cipher[i].dec.count
+				);
+		if (err)
+			goto out;
+
+	}
+out:
+	for (i = 0; i < MAX_REQ; i++)
+		crypto_free_skcipher(tfm[i]);
+
+	return err;
+}
+#endif /* CONFIG_CRYPTO_AES_CBC_MB */
+
 static int alg_test_skcipher(const struct alg_test_desc *desc,
-			     const char *driver, u32 type, u32 mask)
+			const char *driver, u32 type, u32 mask)
 {
 	struct crypto_skcipher *tfm;
 	int err = 0;
 
+#ifdef CONFIG_CRYPTO_AES_CBC_MB
+	/* invoke the comprehensive cbc multibuffer tests */
+	if (desc->alg && (strcmp(desc->alg, "cbc(aes)") == 0))
+		return alg_test_mb_skcipher(desc, driver, type, mask);
+#endif
+
 	tfm = crypto_alloc_skcipher(driver, type | CRYPTO_ALG_INTERNAL, mask);
 	if (IS_ERR(tfm)) {
 		printk(KERN_ERR "alg: skcipher: Failed to load transform for "
-		       "%s: %ld\n", driver, PTR_ERR(tfm));
+				"%s: %ld\n", driver, PTR_ERR(tfm));
 		return PTR_ERR(tfm);
 	}
 
 	if (desc->suite.cipher.enc.vecs) {
 		err = test_skcipher(tfm, ENCRYPT, desc->suite.cipher.enc.vecs,
-				    desc->suite.cipher.enc.count);
+				desc->suite.cipher.enc.count);
 		if (err)
 			goto out;
 	}
 
 	if (desc->suite.cipher.dec.vecs)
 		err = test_skcipher(tfm, DECRYPT, desc->suite.cipher.dec.vecs,
-				    desc->suite.cipher.dec.count);
+				desc->suite.cipher.dec.count);
 
 out:
 	crypto_free_skcipher(tfm);
@@ -2110,6 +2835,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
+		.alg = "__driver-cbc-aes-aesni-mb",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "__driver-cbc-camellia-aesni",
 		.test = alg_test_null,
 	}, {
@@ -3615,6 +4344,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "mcryptd(__driver-cbc-aes-aesni-mb)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "md4",
 		.test = alg_test_hash,
 		.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index da99f89..ee6b223 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -34546,19 +34546,59 @@ static struct comp_testvec lz4hc_decomp_tv_template[] = {
 };
 
 #ifdef CONFIG_CRYPTO_AES_CBC_MB
-static struct cipher_testvec aes_cbc_enc_tv_template_rnddata_klen16[] = {
+static struct cipher_testvec aes_cbc_enc_tv_template_rnddata_klenmix[] = {
 {
-	.key =
-"\xd7\x0c\x4c\x6d\x11\x02\xb0\x31\x63\x9b\x82\x76\x9e\x03\x26\xdf",
-	.klen = 16,
-	.iv =
-"\xc1\x62\x66\x62\xb8\x65\x28\xfa\x5f\x36\xd3\x09\xb1\x2c\xa1\xa3",
-	.input =
-"\x4f\x6c\x63\xa5\xd0\x19\x08\x4e\xd4\x58\x33\xf6\x2b\xeb\x26\xb9",
-	.ilen = 16,
-	.result =
-"\xa0\x35\xb0\x33\xc0\x2e\xe5\xbb\xbc\xe6\x01\x9e\xf4\x67\x11\x14",
-	.rlen = 16,
+		.key	= "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
+			  "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+			  "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
+			  "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+		.klen	= 32,
+		.iv	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.ilen	= 64,
+		.result	= "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
+			  "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
+			  "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
+			  "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
+			  "\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
+			  "\xa5\x30\xe2\x63\x04\x23\x14\x61"
+			  "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
+			  "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+		.rlen	= 64,
+},
+{ /* From NIST SP800-38A */
+		.key	= "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
+			  "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+			  "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+		.klen	= 24,
+		.iv	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.ilen	= 64,
+		.result	= "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
+			  "\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
+			  "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
+			  "\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
+			  "\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
+			  "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
+			  "\x08\xb0\xe2\x79\x88\x59\x88\x81"
+			  "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+		.rlen	= 64,
 },
 {
 	.key =
-- 
1.9.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox