* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 4:40 UTC (permalink / raw)
To: Pavel Machek
Cc: James Bottomley, Alan Stern, David Howells, linux-kernel,
linux-security-module, linux-efi, linux-pm, linux-crypto,
opensuse-kernel, Rafael J. Wysocki, Matthew Garrett, Len Brown,
Josh Boyer, Vojtech Pavlik, Matt Fleming, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <20130926002730.GA26857@amd.pavel.ucw.cz>
於 四,2013-09-26 於 02:27 +0200,Pavel Machek 提到:
> On Wed 2013-09-25 15:16:54, James Bottomley wrote:
> > On Wed, 2013-09-25 at 17:25 -0400, Alan Stern wrote:
> > > On Wed, 25 Sep 2013, David Howells wrote:
> > >
> > > > I have pushed some keyrings patches that will likely affect this to:
> > > >
> > > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > > >
> > > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> > >
> > > This suggests a point that I raised at the Linux Plumbers conference:
> > >
> > > Why are asymmetric keys used for verifying the hibernation image? It
> > > seems that a symmetric key would work just as well. And it would be a
> > > lot quicker to generate, because it wouldn't need any high-precision
> > > integer computations.
> >
> > The reason is the desire to validate that the previous kernel created
> > something which it passed on to the current kernel (in this case, the
> > hibernation image) untampered with. To do that, something must be
> > passed to the prior kernel that can be validated but *not* recreated by
> > the current kernel.
>
> I don't get this. Why is it important that current kernel can't
> recreate the signature?
>
> Current kernel is not considered malicious (if it were, you have worse
> problems).
>
Current boot kernel should not malicious especially when UEFI secure
boot enabled.
> Pavel
>
> PS: And yes, it would be nice to have
> Documentation/power/swsusp-uefi.txt (or something) explaining the
> design.
>
Thanks for your suggestion, I will write the swsusp-uefi.txt to
explaining the design in next version.
Thanks a lot!
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 4:40 UTC (permalink / raw)
To: Pavel Machek
Cc: James Bottomley, Alan Stern, David Howells,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-efi-u79uwXL29TY76Z2rM5mHXA, linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
opensuse-kernel-stAJ6ESoqRxg9hUCZPvPmw, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Josh Boyer, Vojtech Pavlik,
Matt Fleming, Greg KH, JKosina-IBi9RG/b67k, Rusty Russell,
Herbert Xu, David S. Miller, H. Peter Anvin, Michal Marek,
Gary Lin, Vivek Goyal
In-Reply-To: <20130926002730.GA26857-tWAi6jLit6GreWDznjuHag@public.gmane.org>
於 四,2013-09-26 於 02:27 +0200,Pavel Machek 提到:
> On Wed 2013-09-25 15:16:54, James Bottomley wrote:
> > On Wed, 2013-09-25 at 17:25 -0400, Alan Stern wrote:
> > > On Wed, 25 Sep 2013, David Howells wrote:
> > >
> > > > I have pushed some keyrings patches that will likely affect this to:
> > > >
> > > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > > >
> > > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> > >
> > > This suggests a point that I raised at the Linux Plumbers conference:
> > >
> > > Why are asymmetric keys used for verifying the hibernation image? It
> > > seems that a symmetric key would work just as well. And it would be a
> > > lot quicker to generate, because it wouldn't need any high-precision
> > > integer computations.
> >
> > The reason is the desire to validate that the previous kernel created
> > something which it passed on to the current kernel (in this case, the
> > hibernation image) untampered with. To do that, something must be
> > passed to the prior kernel that can be validated but *not* recreated by
> > the current kernel.
>
> I don't get this. Why is it important that current kernel can't
> recreate the signature?
>
> Current kernel is not considered malicious (if it were, you have worse
> problems).
>
Current boot kernel should not malicious especially when UEFI secure
boot enabled.
> Pavel
>
> PS: And yes, it would be nice to have
> Documentation/power/swsusp-uefi.txt (or something) explaining the
> design.
>
Thanks for your suggestion, I will write the swsusp-uefi.txt to
explaining the design in next version.
Thanks a lot!
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 4:40 UTC (permalink / raw)
To: Pavel Machek
Cc: James Bottomley, Alan Stern, David Howells, linux-kernel,
linux-security-module, linux-efi, linux-pm, linux-crypto,
opensuse-kernel, Rafael J. Wysocki, Matthew Garrett, Len Brown,
Josh Boyer, Vojtech Pavlik, Matt Fleming, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <20130926002730.GA26857@amd.pavel.ucw.cz>
於 四,2013-09-26 於 02:27 +0200,Pavel Machek 提到:
> On Wed 2013-09-25 15:16:54, James Bottomley wrote:
> > On Wed, 2013-09-25 at 17:25 -0400, Alan Stern wrote:
> > > On Wed, 25 Sep 2013, David Howells wrote:
> > >
> > > > I have pushed some keyrings patches that will likely affect this to:
> > > >
> > > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > > >
> > > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> > >
> > > This suggests a point that I raised at the Linux Plumbers conference:
> > >
> > > Why are asymmetric keys used for verifying the hibernation image? It
> > > seems that a symmetric key would work just as well. And it would be a
> > > lot quicker to generate, because it wouldn't need any high-precision
> > > integer computations.
> >
> > The reason is the desire to validate that the previous kernel created
> > something which it passed on to the current kernel (in this case, the
> > hibernation image) untampered with. To do that, something must be
> > passed to the prior kernel that can be validated but *not* recreated by
> > the current kernel.
>
> I don't get this. Why is it important that current kernel can't
> recreate the signature?
>
> Current kernel is not considered malicious (if it were, you have worse
> problems).
>
Current boot kernel should not malicious especially when UEFI secure
boot enabled.
> Pavel
>
> PS: And yes, it would be nice to have
> Documentation/power/swsusp-uefi.txt (or something) explaining the
> design.
>
Thanks for your suggestion, I will write the swsusp-uefi.txt to
explaining the design in next version.
Thanks a lot!
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 4:40 UTC (permalink / raw)
To: Pavel Machek
Cc: James Bottomley, Alan Stern, David Howells, linux-kernel,
linux-security-module, linux-efi, linux-pm, linux-crypto,
opensuse-kernel, Rafael J. Wysocki, Matthew Garrett, Len Brown,
Josh Boyer, Vojtech Pavlik, Matt Fleming, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <20130926002730.GA26857@amd.pavel.ucw.cz>
於 四,2013-09-26 於 02:27 +0200,Pavel Machek 提到:
> On Wed 2013-09-25 15:16:54, James Bottomley wrote:
> > On Wed, 2013-09-25 at 17:25 -0400, Alan Stern wrote:
> > > On Wed, 25 Sep 2013, David Howells wrote:
> > >
> > > > I have pushed some keyrings patches that will likely affect this to:
> > > >
> > > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > > >
> > > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> > >
> > > This suggests a point that I raised at the Linux Plumbers conference:
> > >
> > > Why are asymmetric keys used for verifying the hibernation image? It
> > > seems that a symmetric key would work just as well. And it would be a
> > > lot quicker to generate, because it wouldn't need any high-precision
> > > integer computations.
> >
> > The reason is the desire to validate that the previous kernel created
> > something which it passed on to the current kernel (in this case, the
> > hibernation image) untampered with. To do that, something must be
> > passed to the prior kernel that can be validated but *not* recreated by
> > the current kernel.
>
> I don't get this. Why is it important that current kernel can't
> recreate the signature?
>
> Current kernel is not considered malicious (if it were, you have worse
> problems).
>
Current boot kernel should not malicious especially when UEFI secure
boot enabled.
> Pavel
>
> PS: And yes, it would be nice to have
> Documentation/power/swsusp-uefi.txt (or something) explaining the
> design.
>
Thanks for your suggestion, I will write the swsusp-uefi.txt to
explaining the design in next version.
Thanks a lot!
Joey Lee
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 4:40 UTC (permalink / raw)
To: Pavel Machek
Cc: James Bottomley, Alan Stern, David Howells, linux-kernel,
linux-security-module, linux-efi, linux-pm, linux-crypto,
opensuse-kernel, Rafael J. Wysocki, Matthew Garrett, Len Brown,
Josh Boyer, Vojtech Pavlik, Matt Fleming, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <20130926002730.GA26857@amd.pavel.ucw.cz>
於 四,2013-09-26 於 02:27 +0200,Pavel Machek 提到:
> On Wed 2013-09-25 15:16:54, James Bottomley wrote:
> > On Wed, 2013-09-25 at 17:25 -0400, Alan Stern wrote:
> > > On Wed, 25 Sep 2013, David Howells wrote:
> > >
> > > > I have pushed some keyrings patches that will likely affect this to:
> > > >
> > > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > > >
> > > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> > >
> > > This suggests a point that I raised at the Linux Plumbers conference:
> > >
> > > Why are asymmetric keys used for verifying the hibernation image? It
> > > seems that a symmetric key would work just as well. And it would be a
> > > lot quicker to generate, because it wouldn't need any high-precision
> > > integer computations.
> >
> > The reason is the desire to validate that the previous kernel created
> > something which it passed on to the current kernel (in this case, the
> > hibernation image) untampered with. To do that, something must be
> > passed to the prior kernel that can be validated but *not* recreated by
> > the current kernel.
>
> I don't get this. Why is it important that current kernel can't
> recreate the signature?
>
> Current kernel is not considered malicious (if it were, you have worse
> problems).
>
Current boot kernel should not malicious especially when UEFI secure
boot enabled.
> Pavel
>
> PS: And yes, it would be nice to have
> Documentation/power/swsusp-uefi.txt (or something) explaining the
> design.
>
Thanks for your suggestion, I will write the swsusp-uefi.txt to
explaining the design in next version.
Thanks a lot!
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: Jiri Kosina @ 2013-09-26 6:24 UTC (permalink / raw)
To: James Bottomley
Cc: Pavel Machek, Alan Stern, David Howells, Lee, Chun-Yi,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-efi-u79uwXL29TY76Z2rM5mHXA, linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
opensuse-kernel-stAJ6ESoqRxg9hUCZPvPmw, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Josh Boyer, Vojtech Pavlik,
Matt Fleming, Greg KH, Rusty Russell, Herbert Xu, David S. Miller,
H. Peter Anvin, Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <1380162771.18835.47.camel-sFMDBYUN5F8GjUHQrlYNx2Wm91YjaHnnhRte9Li2A+AAvxtiuMwx3w@public.gmane.org>
On Wed, 25 Sep 2013, James Bottomley wrote:
> > I don't get this. Why is it important that current kernel can't
> > recreate the signature?
>
> The thread model is an attack on the saved information (i.e. the suspend
> image) between it being saved by the old kernel and used by the new one.
> The important point isn't that the new kernel doesn't have access to
> K_{N-1} it's that no-one does: the key is destroyed as soon as the old
> kernel terminates however the verification public part P_{N-1} survives.
James,
could you please describe the exact scenario you think that the symmetric
keys aproach doesn't protect against, while the assymetric key aproach
does?
The crucial points, which I believe make the symmetric key aproach work
(and I feel quite embarassed by the fact that I haven't realized this
initially when coming up with the assymetric keys aproach) are:
- the kernel that is performing the actual resumption is trusted in the
secure boot model, i.e. you trust it to perform proper verification
- potentially malicious userspace (which is what we are protecting against
-- malicious root creating fake hibernation image and issuing reboot)
doesn't have access to the symmetric key
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH V4 02/15] asymmetric keys: implement EMSA_PKCS1-v1_5-ENCODE in rsa
From: joeyli @ 2013-09-26 7:08 UTC (permalink / raw)
To: Phil Carmody
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-efi-u79uwXL29TY76Z2rM5mHXA, linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
opensuse-kernel-stAJ6ESoqRxg9hUCZPvPmw, David Howells,
Rafael J. Wysocki, Matthew Garrett
In-Reply-To: <20130923164931.GD6772-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Hi Phil,
First! Thanks for your time to review my patch!
於 一,2013-09-23 於 19:49 +0300,Phil Carmody 提到:
> On Sun, Sep 15, 2013 at 08:56:48AM +0800, Lee, Chun-Yi wrote:
> > Implement EMSA_PKCS1-v1_5-ENCODE [RFC3447 sec 9.2] in rsa.c. It's the
> > first step of signature generation operation (RSASSA-PKCS1-v1_5-SIGN).
> >
> > This patch is temporary set emLen to pks->k, and temporary set EM to
> > pks->S for debugging. We will replace the above values to real signature
> > after implement RSASP1.
> >
> > The naming of EMSA_PKCS1_v1_5_ENCODE and the variables used in this function
> > accord PKCS#1 spec but not follow kernel naming convention, it useful when look
> > at them with spec.
> >
> > Reference: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1v2/pkcs1ietffinal.txt
> > Reference: http://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf
> >
> > V2:
>
> You're now at V4.
The V4 is for whole patchset, I didn't do any modify in this patch in
this version.
The version define maybe confuse between separate and whole patchset, I
will avoid it.
>
> > - Clean up naming of variable: replace _EM by EM, replace EM by EM_tmp.
> > - Add comment to EMSA_PKCS1-v1_5-ENCODE function.
> >
> > Cc: Pavel Machek <pavel-+ZI9xUNit7I@public.gmane.org>
> > Reviewed-by: Jiri Kosina <jkosina-AlSwsSmVLrQ@public.gmane.org>
> > Signed-off-by: Lee, Chun-Yi <jlee-IBi9RG/b67k@public.gmane.org>
> > ---
> > crypto/asymmetric_keys/rsa.c | 163 +++++++++++++++++++++++++++++++++++++++++-
> > include/crypto/public_key.h | 2 +
> > 2 files changed, 164 insertions(+), 1 deletions(-)
> >
> > diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
> > index 47f3be4..352ba45 100644
> > --- a/crypto/asymmetric_keys/rsa.c
> > +++ b/crypto/asymmetric_keys/rsa.c
> > @@ -13,6 +13,7 @@
> > #include <linux/module.h>
> > #include <linux/kernel.h>
> > #include <linux/slab.h>
> > +#include <crypto/hash.h>
> > #include "public_key.h"
> > #include "private_key.h"
> >
> > @@ -152,6 +153,132 @@ static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X)
> > }
> >
> > /*
> > + * EMSA_PKCS1-v1_5-ENCODE [RFC3447 sec 9.2]
> > + * @M: message to be signed, an octet string
> > + * @emLen: intended length in octets of the encoded message
> > + * @hash_algo: hash function (option)
> > + * @hash: true means hash M, otherwise M is already a digest
> > + * @EM: encoded message, an octet string of length emLen
> > + *
> > + * This function is a implementation of the EMSA-PKCS1-v1_5 encoding operation
> > + * in RSA PKCS#1 spec. It used by the signautre generation operation of
> > + * RSASSA-PKCS1-v1_5 to encode message M to encoded message EM.
> > + *
> > + * The variables used in this function accord PKCS#1 spec but not follow kernel
> > + * naming convention, it useful when look at them with spec.
> > + */
> > +static int EMSA_PKCS1_v1_5_ENCODE(const u8 *M, size_t emLen,
> > + enum pkey_hash_algo hash_algo, const bool hash,
> > + u8 **EM, struct public_key_signature *pks)
> > +{
> > + u8 *digest;
> > + struct crypto_shash *tfm;
> > + struct shash_desc *desc;
> > + size_t digest_size, desc_size;
> > + size_t tLen;
> > + u8 *T, *PS, *EM_tmp;
> > + int i, ret;
> > +
> > + pr_info("EMSA_PKCS1_v1_5_ENCODE start\n");
> > +
> > + if (!RSA_ASN1_templates[hash_algo].data)
> > + ret = -ENOTSUPP;
>
> ...
>
> > + else
> > + pks->pkey_hash_algo = hash_algo;
> > +
> > + /* 1) Apply the hash function to the message M to produce a hash value H */
> > + tfm = crypto_alloc_shash(pkey_hash_algo[hash_algo], 0, 0);
> > + if (IS_ERR(tfm))
> > + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
> > +
> > + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
> > + digest_size = crypto_shash_digestsize(tfm);
> > +
> > + ret = -ENOMEM;
>
> The earlier "ret = -ENOTSUPP;" is either unused because you return at the IS_ERR,
> or unused because you overwrite it here. I'm a little disappointed that
> the compiler didn't recognise that something was assigned to a value that
> is never used.
>
> Phil
Yes, Dmitry also pointed out this issue, I should not go on the hash
process if the hash algorithm didn't support.
I will change fix this problem in next version.
Thanks a lot!
Joey Lee
--
To unsubscribe, e-mail: opensuse-kernel+unsubscribe-stAJ6ESoqRxg9hUCZPvPmw@public.gmane.org
To contact the owner, e-mail: opensuse-kernel+owner-stAJ6ESoqRxg9hUCZPvPmw@public.gmane.org
^ permalink raw reply
* Re: [PATCH 28/51] DMA-API: sound: fix dma mask handling in a lot of drivers
From: Takashi Iwai @ 2013-09-26 7:51 UTC (permalink / raw)
To: Russell King
Cc: alsa-devel, linux-doc, linux-mmc, linux-fbdev, linux-nvme,
Jaroslav Kysela, Peter Ujfalusi, linux-ide, Kukjin Kim, devel,
linux-samsung-soc, linux-scsi, e1000-devel, b43-dev, linux-media,
devicetree, Haojian Zhuang, Timur Tabi, Mark Brown, dri-devel,
Ben Dooks, linux-tegra, linux-omap, linux-arm-kernel,
Solarflare linux maintainers, Eric Miao, Sangbeom Kim
In-Reply-To: <E1VMm9m-0007ij-ER@rmk-PC.arm.linux.org.uk>
Hi,
sorry for the lat response, as I've been traveling in the last weeks.
At Thu, 19 Sep 2013 22:53:02 +0100,
Russell King wrote:
>
> This code sequence is unsafe in modules:
>
> static u64 mask = DMA_BIT_MASK(something);
> ...
> if (!dev->dma_mask)
> dev->dma_mask = &mask;
>
> as if a module is reloaded, the mask will be pointing at the original
> module's mask address, and this can lead to oopses. Moreover, they
> all follow this with:
>
> if (!dev->coherent_dma_mask)
> dev->coherent_dma_mask = mask;
>
> where 'mask' is the same value as the statically defined mask, and this
> bypasses the architecture's check on whether the DMA mask is possible.
>
> Fix these issues by using the new dma_coerce_coherent_and_mask()
> function.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Applied with Mark's ack now.
BTW, sound/soc/fsl/imx-pcm-fiq.c wasn't covered by this patch, so I
fixed it, too.
Thanks!
Takashi
> ---
> sound/arm/pxa2xx-pcm.c | 9 +++------
> sound/soc/atmel/atmel-pcm.c | 11 ++++-------
> sound/soc/blackfin/bf5xx-ac97-pcm.c | 11 ++++-------
> sound/soc/blackfin/bf5xx-i2s-pcm.c | 10 ++++------
> sound/soc/davinci/davinci-pcm.c | 9 +++------
> sound/soc/fsl/fsl_dma.c | 9 +++------
> sound/soc/fsl/mpc5200_dma.c | 10 ++++------
> sound/soc/jz4740/jz4740-pcm.c | 12 ++++--------
> sound/soc/kirkwood/kirkwood-dma.c | 9 +++------
> sound/soc/nuc900/nuc900-pcm.c | 9 ++++-----
> sound/soc/omap/omap-pcm.c | 11 ++++-------
> sound/soc/pxa/pxa2xx-pcm.c | 11 ++++-------
> sound/soc/s6000/s6000-pcm.c | 9 +++------
> sound/soc/samsung/dma.c | 11 ++++-------
> sound/soc/samsung/idma.c | 11 ++++-------
> 15 files changed, 55 insertions(+), 97 deletions(-)
>
> diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
> index 69a2455..fb3b76f 100644
> --- a/sound/arm/pxa2xx-pcm.c
> +++ b/sound/arm/pxa2xx-pcm.c
> @@ -83,8 +83,6 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = {
> .mmap = pxa2xx_pcm_mmap,
> };
>
> -static u64 pxa2xx_pcm_dmamask = 0xffffffff;
> -
> int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
> struct snd_pcm **rpcm)
> {
> @@ -100,10 +98,9 @@ int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
> pcm->private_data = client;
> pcm->private_free = pxa2xx_pcm_free_dma_buffers;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &pxa2xx_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = 0xffffffff;
> + ret = dma_coerce_mask_and_coherent_mask(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + goto out;
>
> if (play) {
> int stream = SNDRV_PCM_STREAM_PLAYBACK;
> diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
> index 3109db7..fbb87e3 100644
> --- a/sound/soc/atmel/atmel-pcm.c
> +++ b/sound/soc/atmel/atmel-pcm.c
> @@ -68,18 +68,15 @@ int atmel_pcm_mmap(struct snd_pcm_substream *substream,
> }
> EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
>
> -static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
> -
> int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &atmel_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
> diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
> index 53f8408..1d4c676 100644
> --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
> +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
> @@ -415,19 +415,16 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
> }
> }
>
> -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
>
> pr_debug("%s enter\n", __func__);
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &bf5xx_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
> index 9cb4a80..2a5b434 100644
> --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
> +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
> @@ -323,18 +323,16 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
> .silence = bf5xx_pcm_silence,
> };
>
> -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
> + int ret;
>
> pr_debug("%s enter\n", __func__);
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &bf5xx_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
> SNDRV_DMA_TYPE_DEV, card->dev, size, size);
> diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
> index 8460edc..84a63c6 100644
> --- a/sound/soc/davinci/davinci-pcm.c
> +++ b/sound/soc/davinci/davinci-pcm.c
> @@ -844,18 +844,15 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
> }
> }
>
> -static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &davinci_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = davinci_pcm_preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
> index 9cc5c1f..f73c7ef 100644
> --- a/sound/soc/fsl/fsl_dma.c
> +++ b/sound/soc/fsl/fsl_dma.c
> @@ -298,14 +298,11 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
> int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &fsl_dma_dmamask;
> -
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = fsl_dma_dmamask;
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(36));
> + if (ret)
> + return ret;
>
> /* Some codecs have separate DAIs for playback and capture, so we
> * should allocate a DMA buffer only for the streams that are valid.
> diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
> index 2a847ca..8fcf224 100644
> --- a/sound/soc/fsl/mpc5200_dma.c
> +++ b/sound/soc/fsl/mpc5200_dma.c
> @@ -299,7 +299,6 @@ static struct snd_pcm_ops psc_dma_ops = {
> .hw_params = psc_dma_hw_params,
> };
>
> -static u64 psc_dma_dmamask = DMA_BIT_MASK(32);
> static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> @@ -307,15 +306,14 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
> struct snd_pcm *pcm = rtd->pcm;
> struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
> size_t size = psc_dma_hardware.buffer_bytes_max;
> - int rc = 0;
> + int rc;
>
> dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
> card, dai, pcm);
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &psc_dma_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + rc = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (rc)
> + return rc;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
> diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
> index 7100592..1d7ef28 100644
> --- a/sound/soc/jz4740/jz4740-pcm.c
> +++ b/sound/soc/jz4740/jz4740-pcm.c
> @@ -297,19 +297,15 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
> }
> }
>
> -static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> -
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &jz4740_pcm_dmamask;
> + int ret;
>
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = jz4740_pcm_preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
> index b238434..3814bb0 100644
> --- a/sound/soc/kirkwood/kirkwood-dma.c
> +++ b/sound/soc/kirkwood/kirkwood-dma.c
> @@ -59,8 +59,6 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
> .fifo_size = 0,
> };
>
> -static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
> -
> static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
> {
> struct kirkwood_dma_data *priv = dev_id;
> @@ -292,10 +290,9 @@ static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
> struct snd_pcm *pcm = rtd->pcm;
> int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &kirkwood_dma_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = kirkwood_dma_preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
> index c894ff0..f588ee4 100644
> --- a/sound/soc/nuc900/nuc900-pcm.c
> +++ b/sound/soc/nuc900/nuc900-pcm.c
> @@ -314,16 +314,15 @@ static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm)
> snd_pcm_lib_preallocate_free_for_all(pcm);
> }
>
> -static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
> static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> + int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &nuc900_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
> card->dev, 4 * 1024, (4 * 1024) - 1);
> diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
> index a11405d..b8fa986 100644
> --- a/sound/soc/omap/omap-pcm.c
> +++ b/sound/soc/omap/omap-pcm.c
> @@ -156,8 +156,6 @@ static struct snd_pcm_ops omap_pcm_ops = {
> .mmap = omap_pcm_mmap,
> };
>
> -static u64 omap_pcm_dmamask = DMA_BIT_MASK(64);
> -
> static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
> int stream)
> {
> @@ -202,12 +200,11 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &omap_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = omap_pcm_preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
> index 806da27..d58b09f 100644
> --- a/sound/soc/pxa/pxa2xx-pcm.c
> +++ b/sound/soc/pxa/pxa2xx-pcm.c
> @@ -87,18 +87,15 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = {
> .mmap = pxa2xx_pcm_mmap,
> };
>
> -static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &pxa2xx_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
> index d0740a7..283620a 100644
> --- a/sound/soc/s6000/s6000-pcm.c
> +++ b/sound/soc/s6000/s6000-pcm.c
> @@ -444,8 +444,6 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
> snd_pcm_lib_preallocate_free_for_all(pcm);
> }
>
> -static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
> {
> struct snd_card *card = runtime->card->snd_card;
> @@ -456,10 +454,9 @@ static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
> params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
> pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &s6000_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + res = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (res)
> + return res;
>
> if (params->dma_in) {
> s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
> diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
> index 9338d11..fe2748b 100644
> --- a/sound/soc/samsung/dma.c
> +++ b/sound/soc/samsung/dma.c
> @@ -406,20 +406,17 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm)
> }
> }
>
> -static u64 dma_mask = DMA_BIT_MASK(32);
> -
> static int dma_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
>
> pr_debug("Entered %s\n", __func__);
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &dma_mask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = preallocate_dma_buffer(pcm,
> diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
> index ce1e1e1..e4f318f 100644
> --- a/sound/soc/samsung/idma.c
> +++ b/sound/soc/samsung/idma.c
> @@ -383,18 +383,15 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
> return 0;
> }
>
> -static u64 idma_mask = DMA_BIT_MASK(32);
> -
> static int idma_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &idma_mask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = preallocate_idma_buffer(pcm,
> --
> 1.7.4.4
>
^ permalink raw reply
* Re: [PATCH 28/51] DMA-API: sound: fix dma mask handling in a lot of drivers
From: Russell King - ARM Linux @ 2013-09-26 7:54 UTC (permalink / raw)
To: Takashi Iwai
Cc: alsa-devel, linux-doc, linux-mmc, linux-fbdev, linux-nvme,
Jaroslav Kysela, Peter Ujfalusi, linux-ide, Kukjin Kim, devel,
linux-samsung-soc, linux-scsi, e1000-devel, b43-dev, linux-media,
devicetree, Haojian Zhuang, Timur Tabi, Mark Brown, dri-devel,
Ben Dooks, linux-tegra, linux-omap, linux-arm-kernel,
Solarflare linux maintainers, Eric Miao, Sangbeom Kim
In-Reply-To: <s5h1u4cf2bo.wl%tiwai@suse.de>
On Thu, Sep 26, 2013 at 09:51:23AM +0200, Takashi Iwai wrote:
> Hi,
>
> sorry for the lat response, as I've been traveling in the last weeks.
>
> At Thu, 19 Sep 2013 22:53:02 +0100,
> Russell King wrote:
> >
> > This code sequence is unsafe in modules:
> >
> > static u64 mask = DMA_BIT_MASK(something);
> > ...
> > if (!dev->dma_mask)
> > dev->dma_mask = &mask;
> >
> > as if a module is reloaded, the mask will be pointing at the original
> > module's mask address, and this can lead to oopses. Moreover, they
> > all follow this with:
> >
> > if (!dev->coherent_dma_mask)
> > dev->coherent_dma_mask = mask;
> >
> > where 'mask' is the same value as the statically defined mask, and this
> > bypasses the architecture's check on whether the DMA mask is possible.
> >
> > Fix these issues by using the new dma_coerce_coherent_and_mask()
> > function.
> >
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>
> Applied with Mark's ack now.
Which is a very stupid thing to do because you won't have
dma_coerce_coherent_and_mask() in your tree, so all these drivers
will fail to build for you.
^ permalink raw reply
* Re: [PATCH V4 13/15] Hibernate: introduced SNAPSHOT_SIG_HASH config for select hash algorithm
From: Pavel Machek @ 2013-09-26 8:21 UTC (permalink / raw)
To: joeyli
Cc: linux-kernel, linux-security-module, linux-efi, linux-pm,
linux-crypto, opensuse-kernel, David Howells, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Josh Boyer, Vojtech Pavlik,
Matt Fleming, James Bottomley, Greg KH, JKosina, Rusty Russell,
Herbert Xu, David S. Miller, H. Peter Anvin, Michal Marek,
Gary Lin, Vivek Goyal
In-Reply-To: <1380159819.32302.24.camel@linux-s257.site>
Hi!
> > On Sun 2013-09-15 08:56:59, Lee, Chun-Yi wrote:
> > > This patch introduced SNAPSHOT_SIG_HASH config for user to select which
> > > hash algorithm will be used during signature generation of snapshot.
> >
> > This series is big enough already... and who is going to test it?
>
> The hash config not just for testing, it's relate to the performance and
> secure between different hash algorithms.
I'm not saying it is for testing. I'm saying that selection makes
testing harder.
> There have person raised in LPC say he don't like SHA algorithm.
Well, I don't like the config option.
> > There's no need to make hash configurable. Just select one that works.
>
> SHA1 has good performance, and SHA512 has better security, which one you
> like it?
Use SHA1. It is completely adequate for what you are trying to do.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* crypto: crypto_memneq - add equality testing of memory regions w/o timing leaks
From: James Yonan @ 2013-09-26 8:20 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, James Yonan, Daniel Borkmann, Florian Weimer
When comparing MAC hashes, AEAD authentication tags, or other hash
values in the context of authentication or integrity checking, it
is important not to leak timing information to a potential attacker,
i.e. when communication happens over a network.
Bytewise memory comparisons (such as memcmp) are usually optimized so
that they return a nonzero value as soon as a mismatch is found. E.g,
on x86_64/i5 for 512 bytes this can be ~50 cyc for a full mismatch
and up to ~850 cyc for a full match (cold). This early-return behavior
can leak timing information as a side channel, allowing an attacker to
iteratively guess the correct result.
This patch adds a new method crypto_memneq ("memory not equal to each
other") to the crypto API that compares memory areas of the same length
in roughly "constant time" (cache misses could change the timing, but
since they don't reveal information about the content of the strings
being compared, they are effectively benign). Iow, best and worst case
behaviour take the same amount of time to complete (in contrast to
memcmp).
Note that crypto_memneq (unlike memcmp) can only be used to test for
equality or inequality, NOT for lexicographical order. This, however,
is not an issue for its use-cases within the crypto API.
We tried to locate all of the places in the crypto API where memcmp was
being used for authentication or integrity checking, and convert them
over to crypto_memneq.
crypto_memneq is declared noinline, placed in its own source file,
and compiled with optimizations that might increase code size disabled
("Os") because a smart compiler (or LTO) might notice that the return
value is always compared against zero/nonzero, and might then
reintroduce the same early-return optimization that we are trying to
avoid.
Using #pragma or __attribute__ optimization annotations of the code
for disabling optimization was avoided as it seems to be considered
broken or unmaintained for long time in GCC [1]. Therefore, we work
around that by specifying the compile flag for memneq.o directly in
the Makefile. We found that this seems to be most appropriate.
As we use ("Os"), this patch also provides a loop-free "fast-path" for
frequently used 16 byte digests. Similarly to kernel library string
functions, leave an option for future even further optimized architecture
specific assembler implementations.
This was a joint work of James Yonan and Daniel Borkmann. Also thanks
for feedback from Florian Weimer on this and earlier proposals [2].
[1] http://gcc.gnu.org/ml/gcc/2012-07/msg00211.html
[2] https://lkml.org/lkml/2013/2/10/131
Signed-off-by: James Yonan <james@openvpn.net>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
---
crypto/Makefile | 7 ++-
crypto/asymmetric_keys/rsa.c | 5 +-
crypto/authenc.c | 6 +-
crypto/authencesn.c | 8 +--
crypto/ccm.c | 4 +-
crypto/gcm.c | 2 +-
crypto/memneq.c | 138 +++++++++++++++++++++++++++++++++++++++++++
include/crypto/algapi.h | 18 +++++-
8 files changed, 174 insertions(+), 14 deletions(-)
create mode 100644 crypto/memneq.c
diff --git a/crypto/Makefile b/crypto/Makefile
index 2d5ed08..b88cdf0 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -2,8 +2,13 @@
# Cryptographic API
#
+# memneq MUST be built with -Os or -O0 to prevent early-return optimizations
+# that will defeat memneq's actual purpose to prevent timing attacks.
+CFLAGS_REMOVE_memneq.o := -O1 -O2 -O3
+CFLAGS_memneq.o := -Os
+
obj-$(CONFIG_CRYPTO) += crypto.o
-crypto-y := api.o cipher.o compress.o
+crypto-y := api.o cipher.o compress.o memneq.o
obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
index 4a6a069..1912b9b 100644
--- a/crypto/asymmetric_keys/rsa.c
+++ b/crypto/asymmetric_keys/rsa.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <crypto/algapi.h>
#include "public_key.h"
MODULE_LICENSE("GPL");
@@ -189,12 +190,12 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
}
}
- if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) {
+ if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
return -EBADMSG;
}
- if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) {
+ if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
return -EKEYREJECTED;
}
diff --git a/crypto/authenc.c b/crypto/authenc.c
index ffce19d..2b3f4ab 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -188,7 +188,7 @@ static void authenc_verify_ahash_update_done(struct crypto_async_request *areq,
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+ err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
if (err)
goto out;
@@ -227,7 +227,7 @@ static void authenc_verify_ahash_done(struct crypto_async_request *areq,
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+ err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
if (err)
goto out;
@@ -462,7 +462,7 @@ static int crypto_authenc_verify(struct aead_request *req,
ihash = ohash + authsize;
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
+ return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
}
static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index ab53762..c569d58 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -247,7 +247,7 @@ static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *ar
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+ err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
if (err)
goto out;
@@ -296,7 +296,7 @@ static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *a
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+ err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
if (err)
goto out;
@@ -336,7 +336,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+ err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
if (err)
goto out;
@@ -568,7 +568,7 @@ static int crypto_authenc_esn_verify(struct aead_request *req)
ihash = ohash + authsize;
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
authsize, 0);
- return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
+ return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
}
static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 499c917..3e05499 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -363,7 +363,7 @@ static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
if (!err) {
err = crypto_ccm_auth(req, req->dst, cryptlen);
- if (!err && memcmp(pctx->auth_tag, pctx->odata, authsize))
+ if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
err = -EBADMSG;
}
aead_request_complete(req, err);
@@ -422,7 +422,7 @@ static int crypto_ccm_decrypt(struct aead_request *req)
return err;
/* verify */
- if (memcmp(authtag, odata, authsize))
+ if (crypto_memneq(authtag, odata, authsize))
return -EBADMSG;
return err;
diff --git a/crypto/gcm.c b/crypto/gcm.c
index 43e1fb0..b4f0179 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -582,7 +582,7 @@ static int crypto_gcm_verify(struct aead_request *req,
crypto_xor(auth_tag, iauth_tag, 16);
scatterwalk_map_and_copy(iauth_tag, req->src, cryptlen, authsize, 0);
- return memcmp(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
+ return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
}
static void gcm_decrypt_done(struct crypto_async_request *areq, int err)
diff --git a/crypto/memneq.c b/crypto/memneq.c
new file mode 100644
index 0000000..cd01622
--- /dev/null
+++ b/crypto/memneq.c
@@ -0,0 +1,138 @@
+/*
+ * Constant-time equality testing of memory regions.
+ *
+ * Authors:
+ *
+ * James Yonan <james@openvpn.net>
+ * Daniel Borkmann <dborkman@redhat.com>
+ *
+ * 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) 2013 OpenVPN Technologies, Inc. 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 OpenVPN Technologies, Inc. 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 of OpenVPN Technologies 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 <crypto/algapi.h>
+
+#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ
+
+/* Generic path for arbitrary size */
+static inline unsigned long
+__crypto_memneq_generic(const void *a, const void *b, size_t size)
+{
+ unsigned long neq = 0;
+
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ while (size >= sizeof(unsigned long)) {
+ neq |= *(unsigned long *)a ^ *(unsigned long *)b;
+ a += sizeof(unsigned long);
+ b += sizeof(unsigned long);
+ size -= sizeof(unsigned long);
+ }
+#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+ while (size > 0) {
+ neq |= *(unsigned char *)a ^ *(unsigned char *)b;
+ a += 1;
+ b += 1;
+ size -= 1;
+ }
+ return neq;
+}
+
+/* Loop-free fast-path for frequently used 16-byte size */
+static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
+{
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (sizeof(unsigned long) == 8)
+ return ((*(unsigned long *)(a) ^ *(unsigned long *)(b))
+ | (*(unsigned long *)(a+8) ^ *(unsigned long *)(b+8)));
+ else if (sizeof(unsigned int) == 4)
+ return ((*(unsigned int *)(a) ^ *(unsigned int *)(b))
+ | (*(unsigned int *)(a+4) ^ *(unsigned int *)(b+4))
+ | (*(unsigned int *)(a+8) ^ *(unsigned int *)(b+8))
+ | (*(unsigned int *)(a+12) ^ *(unsigned int *)(b+12)));
+ else
+#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+ return ((*(unsigned char *)(a) ^ *(unsigned char *)(b))
+ | (*(unsigned char *)(a+1) ^ *(unsigned char *)(b+1))
+ | (*(unsigned char *)(a+2) ^ *(unsigned char *)(b+2))
+ | (*(unsigned char *)(a+3) ^ *(unsigned char *)(b+3))
+ | (*(unsigned char *)(a+4) ^ *(unsigned char *)(b+4))
+ | (*(unsigned char *)(a+5) ^ *(unsigned char *)(b+5))
+ | (*(unsigned char *)(a+6) ^ *(unsigned char *)(b+6))
+ | (*(unsigned char *)(a+7) ^ *(unsigned char *)(b+7))
+ | (*(unsigned char *)(a+8) ^ *(unsigned char *)(b+8))
+ | (*(unsigned char *)(a+9) ^ *(unsigned char *)(b+9))
+ | (*(unsigned char *)(a+10) ^ *(unsigned char *)(b+10))
+ | (*(unsigned char *)(a+11) ^ *(unsigned char *)(b+11))
+ | (*(unsigned char *)(a+12) ^ *(unsigned char *)(b+12))
+ | (*(unsigned char *)(a+13) ^ *(unsigned char *)(b+13))
+ | (*(unsigned char *)(a+14) ^ *(unsigned char *)(b+14))
+ | (*(unsigned char *)(a+15) ^ *(unsigned char *)(b+15)));
+}
+
+/* Compare two areas of memory without leaking timing information,
+ * and with special optimizations for common sizes. Users should
+ * not call this function directly, but should instead use
+ * crypto_memneq defined in crypto/algapi.h.
+ */
+noinline unsigned long __crypto_memneq(const void *a, const void *b,
+ size_t size)
+{
+ switch (size) {
+ case 16:
+ return __crypto_memneq_16(a, b);
+ default:
+ return __crypto_memneq_generic(a, b, size);
+ }
+}
+EXPORT_SYMBOL(__crypto_memneq);
+
+#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 418d270..e73c19e 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -386,5 +386,21 @@ static inline int crypto_requires_sync(u32 type, u32 mask)
return (type ^ CRYPTO_ALG_ASYNC) & mask & CRYPTO_ALG_ASYNC;
}
-#endif /* _CRYPTO_ALGAPI_H */
+noinline unsigned long __crypto_memneq(const void *a, const void *b, size_t size);
+
+/**
+ * crypto_memneq - Compare two areas of memory without leaking
+ * timing information.
+ *
+ * @a: One area of memory
+ * @b: Another area of memory
+ * @size: The size of the area.
+ *
+ * Returns 0 when data is equal, 1 otherwise.
+ */
+static inline int crypto_memneq(const void *a, const void *b, size_t size)
+{
+ return __crypto_memneq(a, b, size) != 0UL ? 1 : 0;
+}
+#endif /* _CRYPTO_ALGAPI_H */
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH 28/51] DMA-API: sound: fix dma mask handling in a lot of drivers
From: Takashi Iwai @ 2013-09-26 8:25 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: alsa-devel, linux-doc, linux-mmc, linux-fbdev, linux-nvme,
Jaroslav Kysela, Peter Ujfalusi, linux-ide, Kukjin Kim, devel,
linux-samsung-soc, linux-scsi, e1000-devel, b43-dev, linux-media,
devicetree, Haojian Zhuang, Timur Tabi, Mark Brown, dri-devel,
Ben Dooks, linux-tegra, linux-omap, linux-arm-kernel,
Solarflare linux maintainers, Eric Miao, Sangbeom Kim
In-Reply-To: <20130926075425.GX25647@n2100.arm.linux.org.uk>
At Thu, 26 Sep 2013 08:54:25 +0100,
Russell King - ARM Linux wrote:
>
> On Thu, Sep 26, 2013 at 09:51:23AM +0200, Takashi Iwai wrote:
> > Hi,
> >
> > sorry for the lat response, as I've been traveling in the last weeks.
> >
> > At Thu, 19 Sep 2013 22:53:02 +0100,
> > Russell King wrote:
> > >
> > > This code sequence is unsafe in modules:
> > >
> > > static u64 mask = DMA_BIT_MASK(something);
> > > ...
> > > if (!dev->dma_mask)
> > > dev->dma_mask = &mask;
> > >
> > > as if a module is reloaded, the mask will be pointing at the original
> > > module's mask address, and this can lead to oopses. Moreover, they
> > > all follow this with:
> > >
> > > if (!dev->coherent_dma_mask)
> > > dev->coherent_dma_mask = mask;
> > >
> > > where 'mask' is the same value as the statically defined mask, and this
> > > bypasses the architecture's check on whether the DMA mask is possible.
> > >
> > > Fix these issues by using the new dma_coerce_coherent_and_mask()
> > > function.
> > >
> > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> >
> > Applied with Mark's ack now.
>
> Which is a very stupid thing to do because you won't have
> dma_coerce_coherent_and_mask() in your tree, so all these drivers
> will fail to build for you.
Ah, silly me, I missed the very first thing. Reverted it now...
FWIW, below is the missing piece. Please apply it in your side if
necessary.
Takashi
---
sound/soc/fsl/imx-pcm-fiq.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 34043c5..fd5f2fb 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -272,18 +272,16 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
return 0;
}
-static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
-
static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
- int ret = 0;
+ int ret;
+
+ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &imx_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = imx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
--
1.8.4
^ permalink raw reply related
* Re: [PATCH 28/51] DMA-API: sound: fix dma mask handling in a lot of drivers
From: Takashi Iwai @ 2013-09-26 8:29 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: alsa-devel, linux-doc, linux-mmc, linux-fbdev, linux-nvme,
Jaroslav Kysela, Peter Ujfalusi, linux-ide, Kukjin Kim, devel,
linux-samsung-soc, linux-scsi, e1000-devel, b43-dev, linux-media,
devicetree, Haojian Zhuang, Timur Tabi, Mark Brown, dri-devel,
Ben Dooks, linux-tegra, linux-omap, linux-arm-kernel,
Solarflare linux maintainers, Eric Miao, Sangbeom Kim
In-Reply-To: <s5hob7gdm6u.wl%tiwai@suse.de>
At Thu, 26 Sep 2013 10:25:13 +0200,
Takashi Iwai wrote:
>
> At Thu, 26 Sep 2013 08:54:25 +0100,
> Russell King - ARM Linux wrote:
> >
> > On Thu, Sep 26, 2013 at 09:51:23AM +0200, Takashi Iwai wrote:
> > > Hi,
> > >
> > > sorry for the lat response, as I've been traveling in the last weeks.
> > >
> > > At Thu, 19 Sep 2013 22:53:02 +0100,
> > > Russell King wrote:
> > > >
> > > > This code sequence is unsafe in modules:
> > > >
> > > > static u64 mask = DMA_BIT_MASK(something);
> > > > ...
> > > > if (!dev->dma_mask)
> > > > dev->dma_mask = &mask;
> > > >
> > > > as if a module is reloaded, the mask will be pointing at the original
> > > > module's mask address, and this can lead to oopses. Moreover, they
> > > > all follow this with:
> > > >
> > > > if (!dev->coherent_dma_mask)
> > > > dev->coherent_dma_mask = mask;
> > > >
> > > > where 'mask' is the same value as the statically defined mask, and this
> > > > bypasses the architecture's check on whether the DMA mask is possible.
> > > >
> > > > Fix these issues by using the new dma_coerce_coherent_and_mask()
> > > > function.
> > > >
> > > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > >
> > > Applied with Mark's ack now.
> >
> > Which is a very stupid thing to do because you won't have
> > dma_coerce_coherent_and_mask() in your tree, so all these drivers
> > will fail to build for you.
>
> Ah, silly me, I missed the very first thing. Reverted it now...
>
> FWIW, below is the missing piece. Please apply it in your side if
> necessary.
Oh, and feel free to add my ack, if any:
Acked-by: Takashi Iwai <tiwai@suse.de>
thanks,
Takashi
>
>
> Takashi
>
> ---
> sound/soc/fsl/imx-pcm-fiq.c | 12 +++++-------
> 1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
> index 34043c5..fd5f2fb 100644
> --- a/sound/soc/fsl/imx-pcm-fiq.c
> +++ b/sound/soc/fsl/imx-pcm-fiq.c
> @@ -272,18 +272,16 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
> return 0;
> }
>
> -static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
> -
> static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
> {
> struct snd_card *card = rtd->card->snd_card;
> struct snd_pcm *pcm = rtd->pcm;
> - int ret = 0;
> + int ret;
> +
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> - if (!card->dev->dma_mask)
> - card->dev->dma_mask = &imx_pcm_dmamask;
> - if (!card->dev->coherent_dma_mask)
> - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
> ret = imx_pcm_preallocate_dma_buffer(pcm,
> SNDRV_PCM_STREAM_PLAYBACK);
> --
> 1.8.4
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 10:43 UTC (permalink / raw)
To: Alan Stern
Cc: David Howells, linux-kernel, linux-security-module, linux-efi,
linux-pm, linux-crypto, opensuse-kernel, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Pavel Machek, Josh Boyer,
Vojtech Pavlik, Matt Fleming, James Bottomley, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <1380161957.32302.42.camel@linux-s257.site>
於 四,2013-09-26 於 10:19 +0800,joeyli 提到:
> 於 三,2013-09-25 於 17:25 -0400,Alan Stern 提到:
> > On Wed, 25 Sep 2013, David Howells wrote:
> >
> > > I have pushed some keyrings patches that will likely affect this to:
> > >
> > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > >
> > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> >
> > This suggests a point that I raised at the Linux Plumbers conference:
> >
> > Why are asymmetric keys used for verifying the hibernation image? It
> > seems that a symmetric key would work just as well. And it would be a
> > lot quicker to generate, because it wouldn't need any high-precision
> > integer computations.
> >
> > Alan Stern
> >
> >
>
> Per my understood, it's like add salt to snapshot when generate
> signature, then remove the salt when store the snapshot to swap. (or
> pass snapshot to userland).
>
> Let me explain the symmetric key solution base on my understand:
>
> + EFI stub kernel generate a hash value from a random seed, then store
> it to EFi boot varaible. It should protected by UEFI secure boot
> environment.
>
> + When hibernate launched:
> - Kernel create the snapshot image of memory. It's included the
> random hash value(salt) that generated in EFI stub stage.
> - Then kernel hash the snapshot image, put the hash to snapshot
> header, just like current asymmetric keys solution.
> - Kernel erase the salt in snapshot image before it go to swap or
> pass to userspace tool.
>
> + When hibernate resume:
> - Kernel or userspace tool load the snapshot(without salt) from swap
> to temporary memory space.
> - Kernel fill the salt back to snapshot image in memory, hash it.
> - Kernel compare the hash with the hash that put in snapshot header.
> - Verification done! The follow-up action as current solution.
>
> Please current me if I missed anything.
>
>
> Thanks a lot!
> Joey Lee
>
For the symmetric key solution, I will try HMAC (Hash Message
Authentication Code). It's already used in networking, hope the
performance is not too bad to a big image.
Thanks
Joey Lee
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 10:43 UTC (permalink / raw)
To: Alan Stern
Cc: David Howells, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-efi-u79uwXL29TY76Z2rM5mHXA, linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
opensuse-kernel-stAJ6ESoqRxg9hUCZPvPmw, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Pavel Machek, Josh Boyer,
Vojtech Pavlik, Matt Fleming, James Bottomley, Greg KH,
JKosina-IBi9RG/b67k, Rusty Russell, Herbert Xu, David S. Miller,
H. Peter Anvin, Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <1380161957.32302.42.camel-ONCj+Eqt86TasUa73XJKwA@public.gmane.org>
於 四,2013-09-26 於 10:19 +0800,joeyli 提到:
> 於 三,2013-09-25 於 17:25 -0400,Alan Stern 提到:
> > On Wed, 25 Sep 2013, David Howells wrote:
> >
> > > I have pushed some keyrings patches that will likely affect this to:
> > >
> > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > >
> > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> >
> > This suggests a point that I raised at the Linux Plumbers conference:
> >
> > Why are asymmetric keys used for verifying the hibernation image? It
> > seems that a symmetric key would work just as well. And it would be a
> > lot quicker to generate, because it wouldn't need any high-precision
> > integer computations.
> >
> > Alan Stern
> >
> >
>
> Per my understood, it's like add salt to snapshot when generate
> signature, then remove the salt when store the snapshot to swap. (or
> pass snapshot to userland).
>
> Let me explain the symmetric key solution base on my understand:
>
> + EFI stub kernel generate a hash value from a random seed, then store
> it to EFi boot varaible. It should protected by UEFI secure boot
> environment.
>
> + When hibernate launched:
> - Kernel create the snapshot image of memory. It's included the
> random hash value(salt) that generated in EFI stub stage.
> - Then kernel hash the snapshot image, put the hash to snapshot
> header, just like current asymmetric keys solution.
> - Kernel erase the salt in snapshot image before it go to swap or
> pass to userspace tool.
>
> + When hibernate resume:
> - Kernel or userspace tool load the snapshot(without salt) from swap
> to temporary memory space.
> - Kernel fill the salt back to snapshot image in memory, hash it.
> - Kernel compare the hash with the hash that put in snapshot header.
> - Verification done! The follow-up action as current solution.
>
> Please current me if I missed anything.
>
>
> Thanks a lot!
> Joey Lee
>
For the symmetric key solution, I will try HMAC (Hash Message
Authentication Code). It's already used in networking, hope the
performance is not too bad to a big image.
Thanks
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 10:43 UTC (permalink / raw)
To: Alan Stern
Cc: David Howells, linux-kernel, linux-security-module, linux-efi,
linux-pm, linux-crypto, opensuse-kernel, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Pavel Machek, Josh Boyer,
Vojtech Pavlik, Matt Fleming, James Bottomley, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <1380161957.32302.42.camel@linux-s257.site>
於 四,2013-09-26 於 10:19 +0800,joeyli 提到:
> 於 三,2013-09-25 於 17:25 -0400,Alan Stern 提到:
> > On Wed, 25 Sep 2013, David Howells wrote:
> >
> > > I have pushed some keyrings patches that will likely affect this to:
> > >
> > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > >
> > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> >
> > This suggests a point that I raised at the Linux Plumbers conference:
> >
> > Why are asymmetric keys used for verifying the hibernation image? It
> > seems that a symmetric key would work just as well. And it would be a
> > lot quicker to generate, because it wouldn't need any high-precision
> > integer computations.
> >
> > Alan Stern
> >
> >
>
> Per my understood, it's like add salt to snapshot when generate
> signature, then remove the salt when store the snapshot to swap. (or
> pass snapshot to userland).
>
> Let me explain the symmetric key solution base on my understand:
>
> + EFI stub kernel generate a hash value from a random seed, then store
> it to EFi boot varaible. It should protected by UEFI secure boot
> environment.
>
> + When hibernate launched:
> - Kernel create the snapshot image of memory. It's included the
> random hash value(salt) that generated in EFI stub stage.
> - Then kernel hash the snapshot image, put the hash to snapshot
> header, just like current asymmetric keys solution.
> - Kernel erase the salt in snapshot image before it go to swap or
> pass to userspace tool.
>
> + When hibernate resume:
> - Kernel or userspace tool load the snapshot(without salt) from swap
> to temporary memory space.
> - Kernel fill the salt back to snapshot image in memory, hash it.
> - Kernel compare the hash with the hash that put in snapshot header.
> - Verification done! The follow-up action as current solution.
>
> Please current me if I missed anything.
>
>
> Thanks a lot!
> Joey Lee
>
For the symmetric key solution, I will try HMAC (Hash Message
Authentication Code). It's already used in networking, hope the
performance is not too bad to a big image.
Thanks
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 10:43 UTC (permalink / raw)
To: Alan Stern
Cc: David Howells, linux-kernel, linux-security-module, linux-efi,
linux-pm, linux-crypto, opensuse-kernel, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Pavel Machek, Josh Boyer,
Vojtech Pavlik, Matt Fleming, James Bottomley, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <1380161957.32302.42.camel@linux-s257.site>
於 四,2013-09-26 於 10:19 +0800,joeyli 提到:
> 於 三,2013-09-25 於 17:25 -0400,Alan Stern 提到:
> > On Wed, 25 Sep 2013, David Howells wrote:
> >
> > > I have pushed some keyrings patches that will likely affect this to:
> > >
> > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > >
> > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> >
> > This suggests a point that I raised at the Linux Plumbers conference:
> >
> > Why are asymmetric keys used for verifying the hibernation image? It
> > seems that a symmetric key would work just as well. And it would be a
> > lot quicker to generate, because it wouldn't need any high-precision
> > integer computations.
> >
> > Alan Stern
> >
> >
>
> Per my understood, it's like add salt to snapshot when generate
> signature, then remove the salt when store the snapshot to swap. (or
> pass snapshot to userland).
>
> Let me explain the symmetric key solution base on my understand:
>
> + EFI stub kernel generate a hash value from a random seed, then store
> it to EFi boot varaible. It should protected by UEFI secure boot
> environment.
>
> + When hibernate launched:
> - Kernel create the snapshot image of memory. It's included the
> random hash value(salt) that generated in EFI stub stage.
> - Then kernel hash the snapshot image, put the hash to snapshot
> header, just like current asymmetric keys solution.
> - Kernel erase the salt in snapshot image before it go to swap or
> pass to userspace tool.
>
> + When hibernate resume:
> - Kernel or userspace tool load the snapshot(without salt) from swap
> to temporary memory space.
> - Kernel fill the salt back to snapshot image in memory, hash it.
> - Kernel compare the hash with the hash that put in snapshot header.
> - Verification done! The follow-up action as current solution.
>
> Please current me if I missed anything.
>
>
> Thanks a lot!
> Joey Lee
>
For the symmetric key solution, I will try HMAC (Hash Message
Authentication Code). It's already used in networking, hope the
performance is not too bad to a big image.
Thanks
Joey Lee
^ permalink raw reply
* Re: [RFC V4 PATCH 00/15] Signature verification of hibernate snapshot
From: joeyli @ 2013-09-26 10:43 UTC (permalink / raw)
To: Alan Stern
Cc: David Howells, linux-kernel, linux-security-module, linux-efi,
linux-pm, linux-crypto, opensuse-kernel, Rafael J. Wysocki,
Matthew Garrett, Len Brown, Pavel Machek, Josh Boyer,
Vojtech Pavlik, Matt Fleming, James Bottomley, Greg KH, JKosina,
Rusty Russell, Herbert Xu, David S. Miller, H. Peter Anvin,
Michal Marek, Gary Lin, Vivek Goyal
In-Reply-To: <1380161957.32302.42.camel@linux-s257.site>
於 四,2013-09-26 於 10:19 +0800,joeyli 提到:
> 於 三,2013-09-25 於 17:25 -0400,Alan Stern 提到:
> > On Wed, 25 Sep 2013, David Howells wrote:
> >
> > > I have pushed some keyrings patches that will likely affect this to:
> > >
> > > http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-devel
> > >
> > > I intend to ask James to pull these into his next branch. If he's happy to do
> > > so, I can look at pulling at least your asymmetric keys patch on top of them.
> >
> > This suggests a point that I raised at the Linux Plumbers conference:
> >
> > Why are asymmetric keys used for verifying the hibernation image? It
> > seems that a symmetric key would work just as well. And it would be a
> > lot quicker to generate, because it wouldn't need any high-precision
> > integer computations.
> >
> > Alan Stern
> >
> >
>
> Per my understood, it's like add salt to snapshot when generate
> signature, then remove the salt when store the snapshot to swap. (or
> pass snapshot to userland).
>
> Let me explain the symmetric key solution base on my understand:
>
> + EFI stub kernel generate a hash value from a random seed, then store
> it to EFi boot varaible. It should protected by UEFI secure boot
> environment.
>
> + When hibernate launched:
> - Kernel create the snapshot image of memory. It's included the
> random hash value(salt) that generated in EFI stub stage.
> - Then kernel hash the snapshot image, put the hash to snapshot
> header, just like current asymmetric keys solution.
> - Kernel erase the salt in snapshot image before it go to swap or
> pass to userspace tool.
>
> + When hibernate resume:
> - Kernel or userspace tool load the snapshot(without salt) from swap
> to temporary memory space.
> - Kernel fill the salt back to snapshot image in memory, hash it.
> - Kernel compare the hash with the hash that put in snapshot header.
> - Verification done! The follow-up action as current solution.
>
> Please current me if I missed anything.
>
>
> Thanks a lot!
> Joey Lee
>
For the symmetric key solution, I will try HMAC (Hash Message
Authentication Code). It's already used in networking, hope the
performance is not too bad to a big image.
Thanks
Joey Lee
^ permalink raw reply
* IV generation in geode-aes
From: Sohail @ 2013-09-19 12:04 UTC (permalink / raw)
To: linux-crypto
Hi all,
I could'nt understand the mechanism of IV generation in geode-aes. Can
someone explain it in easy to understand manner?
Thanks a lot.
^ permalink raw reply
* Re: [PATCH 39/51] DMA-API: others: use dma_set_coherent_mask()
From: Archit Taneja @ 2013-09-26 10:51 UTC (permalink / raw)
To: Russell King, alsa-devel, b43-dev, devel, devicetree, dri-devel,
e1000-devel, linux-arm-kernel, linux-crypto, linux-doc,
linux-fbdev, linux-ide, linux-media, linux-mmc, linux-nvme,
linux-omap, linuxppc-dev, linux-samsung-soc, linux-scsi,
linux-tegra, linux-usb, linux-wireless, netdev,
Solarflare linux maintainers, uclinux-dist-devel
Cc: Kukjin Kim, Joonyoung Shim, David Airlie, Seung-Woo Kim,
Rob Clark, Inki Dae, Kyungmin Park, Valkeinen, Tomi, Tejun Heo
In-Reply-To: <E1VMnNq-0007s4-HN@rmk-PC.arm.linux.org.uk>
Hi,
On Friday 20 September 2013 04:41 AM, Russell King wrote:
> The correct way for a driver to specify the coherent DMA mask is
> not to directly access the field in the struct device, but to use
> dma_set_coherent_mask(). Only arch and bus code should access this
> member directly.
>
> Convert all direct write accesses to using the correct API.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
> drivers/ata/pata_ixp4xx_cf.c | 5 ++++-
> drivers/gpu/drm/exynos/exynos_drm_drv.c | 6 +++++-
> drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 5 +++--
> 3 files changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
> index 1ec53f8..ddf470c 100644
> --- a/drivers/ata/pata_ixp4xx_cf.c
> +++ b/drivers/ata/pata_ixp4xx_cf.c
> @@ -144,6 +144,7 @@ static int ixp4xx_pata_probe(struct platform_device *pdev)
> struct ata_host *host;
> struct ata_port *ap;
> struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev);
> + int ret;
>
> cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> @@ -157,7 +158,9 @@ static int ixp4xx_pata_probe(struct platform_device *pdev)
> return -ENOMEM;
>
> /* acquire resources and fill host */
> - pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
> data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index bb82ef7..81192d0 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -286,7 +286,11 @@ static struct drm_driver exynos_drm_driver = {
>
> static int exynos_drm_platform_probe(struct platform_device *pdev)
> {
> - pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + int ret;
> +
> + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
>
> return drm_platform_init(&exynos_drm_driver, pdev);
> }
> diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
> index acf6678..701c4c1 100644
> --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
> +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
> @@ -664,8 +664,9 @@ static int omap_dmm_probe(struct platform_device *dev)
> }
>
> /* set dma mask for device */
> - /* NOTE: this is a workaround for the hwmod not initializing properly */
> - dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + ret = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
> + if (ret)
> + goto fail;
Tested with omapdrm on omap4 panda es board.
Thanks,
Archit
^ permalink raw reply
* [PATCH 1/3] crypto: Fully restore ahash request before completing
From: Marek Vasut @ 2013-09-26 11:18 UTC (permalink / raw)
To: linux-crypto; +Cc: linux-arm-kernel, Marek Vasut, Herbert Xu, David S. Miller
When finishing the ahash request, the ahash_op_unaligned_done() will
call complete() on the request. Yet, this will not call the correct
complete callback. The correct complete callback was previously stored
in the requests' private data, as seen in ahash_op_unaligned(). This
patch restores the correct complete callback and .data field of the
request before calling complete() on it.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David S. Miller <davem@davemloft.net>
---
crypto/ahash.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 793a27f..a92dc38 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -213,7 +213,10 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
ahash_op_unaligned_finish(areq, err);
- complete(data, err);
+ areq->base.complete = complete;
+ areq->base.data = data;
+
+ complete(&areq->base, err);
}
static int ahash_op_unaligned(struct ahash_request *req,
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 3/3] ARM: mxs: dts: Enable DCP for MXS
From: Marek Vasut @ 2013-09-26 11:18 UTC (permalink / raw)
To: linux-crypto
Cc: linux-arm-kernel, Marek Vasut, Herbert Xu, David S. Miller,
Fabio Estevam, Shawn Guo
In-Reply-To: <1380194306-5243-1-git-send-email-marex@denx.de>
Enable the DCP by default on both i.MX23 and i.MX28.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David S. Miller <davem@davemloft.net>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
To: linux-crypto@vger.kernel.org
---
arch/arm/boot/dts/imx23.dtsi | 4 +++-
arch/arm/boot/dts/imx28.dtsi | 5 +++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 87faa6e..0630a9a 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -337,8 +337,10 @@
};
dcp@80028000 {
+ compatible = "fsl,mxs-dcp";
reg = <0x80028000 0x2000>;
- status = "disabled";
+ interrupts = <53 54>;
+ status = "okay";
};
pxp@8002a000 {
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 918d419..8b5ad60 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -782,9 +782,10 @@
};
dcp: dcp@80028000 {
+ compatible = "fsl,mxs-dcp";
reg = <0x80028000 0x2000>;
- interrupts = <52 53 54>;
- compatible = "fsl-dcp";
+ interrupts = <53 54>;
+ status = "okay";
};
pxp: pxp@8002a000 {
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 2/3] ARM: mxs: crypto: Add Freescale MXS DCP driver
From: Marek Vasut @ 2013-09-26 11:18 UTC (permalink / raw)
To: linux-crypto; +Cc: linux-arm-kernel, Marek Vasut, Herbert Xu, David S. Miller
In-Reply-To: <1380194306-5243-1-git-send-email-marex@denx.de>
Add support for the MXS DCP block. The driver currently supports
SHA-1/SHA-256 hashing and AES-128 CBC/ECB modes. The non-standard
CRC32 is not yet supported.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David S. Miller <davem@davemloft.net>
---
drivers/crypto/Kconfig | 17 +
drivers/crypto/Makefile | 1 +
drivers/crypto/mxs-dcp.c | 1082 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1100 insertions(+)
create mode 100644 drivers/crypto/mxs-dcp.c
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index f4fd837..4aa6686 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -399,4 +399,21 @@ config CRYPTO_DEV_ATMEL_SHA
To compile this driver as a module, choose M here: the module
will be called atmel-sha.
+config CRYPTO_DEV_MXS_DCP
+ tristate "Support for Freescale MXS DCP"
+ depends on ARCH_MXS
+ select CRYPTO_SHA1
+ select CRYPTO_SHA256
+ select CRYPTO_CBC
+ select CRYPTO_ECB
+ select CRYPTO_AES
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_ALGAPI
+ help
+ The Freescale i.MX23/i.MX28 has SHA1/SHA256 and AES128 CBC/ECB
+ co-processor on the die.
+
+ To compile this driver as a module, choose M here: the module
+ will be called atmel-sha.
+
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index b4946dd..56cce04 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o
+obj-$(CONFIG_CRYPTO_DEV_MXS_DCP) += mxs-dcp.o
diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
new file mode 100644
index 0000000..c2b35c7
--- /dev/null
+++ b/drivers/crypto/mxs-dcp.c
@@ -0,0 +1,1082 @@
+/*
+ * Freescale i.MX23/i.MX28 Data Co-Processor driver
+ *
+ * Copyright (C) 2013 Marek Vasut <marex@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/crypto.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/stmp_device.h>
+
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include <crypto/internal/hash.h>
+
+#define DCP_MAX_CHANS 4
+#define DCP_BUF_SZ PAGE_SIZE
+
+/* DCP DMA descriptor. */
+struct dcp_dma_desc {
+ uint32_t next_cmd_addr;
+ uint32_t control0;
+ uint32_t control1;
+ uint32_t source;
+ uint32_t destination;
+ uint32_t size;
+ uint32_t payload;
+ uint32_t status;
+};
+
+/* Coherent aligned block for bounce buffering. */
+struct dcp_coherent_block {
+ uint8_t aes_in_buf[DCP_BUF_SZ];
+ uint8_t aes_out_buf[DCP_BUF_SZ];
+ uint8_t sha_in_buf[DCP_BUF_SZ];
+
+ uint8_t aes_key[2 * AES_KEYSIZE_128];
+ uint8_t sha_digest[SHA256_DIGEST_SIZE];
+
+ struct dcp_dma_desc desc[DCP_MAX_CHANS];
+};
+
+struct dcp {
+ struct device *dev;
+ void __iomem *base;
+
+ uint32_t caps;
+
+ struct dcp_coherent_block *coh;
+ dma_addr_t coh_phys;
+
+ struct completion completion[DCP_MAX_CHANS];
+ struct mutex mutex[DCP_MAX_CHANS];
+ struct task_struct *thread[DCP_MAX_CHANS];
+ struct crypto_queue queue[DCP_MAX_CHANS];
+};
+
+enum dcp_chan {
+ DCP_CHAN_HASH_SHA = 0,
+ DCP_CHAN_CRYPTO = 2,
+};
+
+struct dcp_async_ctx {
+ /* Common context */
+ enum dcp_chan chan;
+ uint32_t fill;
+
+ /* SHA Hash-specific context */
+ struct mutex mutex;
+ uint32_t alg;
+ unsigned int hot:1;
+
+ /* Crypto-specific context */
+ unsigned int enc:1;
+ unsigned int ecb:1;
+ struct crypto_ablkcipher *fallback;
+ unsigned int key_len;
+ uint8_t key[AES_KEYSIZE_128];
+};
+
+struct dcp_sha_req_ctx {
+ unsigned int init:1;
+ unsigned int fini:1;
+};
+
+/*
+ * There can even be only one instance of the MXS DCP due to the
+ * design of Linux Crypto API.
+ */
+static struct dcp *global_sdcp;
+DEFINE_MUTEX(global_mutex);
+
+/* DCP register layout. */
+#define MXS_DCP_CTRL 0x00
+#define MXS_DCP_CTRL_GATHER_RESIDUAL_WRITES (1 << 23)
+#define MXS_DCP_CTRL_ENABLE_CONTEXT_CACHING (1 << 22)
+
+#define MXS_DCP_STAT 0x10
+#define MXS_DCP_STAT_CLR 0x18
+#define MXS_DCP_STAT_IRQ_MASK 0xf
+
+#define MXS_DCP_CHANNELCTRL 0x20
+#define MXS_DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK 0xff
+
+#define MXS_DCP_CAPABILITY1 0x40
+#define MXS_DCP_CAPABILITY1_SHA256 (4 << 16)
+#define MXS_DCP_CAPABILITY1_SHA1 (1 << 16)
+#define MXS_DCP_CAPABILITY1_AES128 (1 << 0)
+
+#define MXS_DCP_CONTEXT 0x50
+
+#define MXS_DCP_CH_N_CMDPTR(n) (0x100 + ((n) * 0x40))
+
+#define MXS_DCP_CH_N_SEMA(n) (0x110 + ((n) * 0x40))
+
+#define MXS_DCP_CH_N_STAT(n) (0x120 + ((n) * 0x40))
+#define MXS_DCP_CH_N_STAT_CLR(n) (0x128 + ((n) * 0x40))
+
+/* DMA descriptor bits. */
+#define MXS_DCP_CONTROL0_HASH_TERM (1 << 13)
+#define MXS_DCP_CONTROL0_HASH_INIT (1 << 12)
+#define MXS_DCP_CONTROL0_PAYLOAD_KEY (1 << 11)
+#define MXS_DCP_CONTROL0_CIPHER_ENCRYPT (1 << 8)
+#define MXS_DCP_CONTROL0_CIPHER_INIT (1 << 9)
+#define MXS_DCP_CONTROL0_ENABLE_HASH (1 << 6)
+#define MXS_DCP_CONTROL0_ENABLE_CIPHER (1 << 5)
+#define MXS_DCP_CONTROL0_DECR_SEMAPHORE (1 << 1)
+#define MXS_DCP_CONTROL0_INTERRUPT (1 << 0)
+
+#define MXS_DCP_CONTROL1_HASH_SELECT_SHA256 (2 << 16)
+#define MXS_DCP_CONTROL1_HASH_SELECT_SHA1 (0 << 16)
+#define MXS_DCP_CONTROL1_CIPHER_MODE_CBC (1 << 4)
+#define MXS_DCP_CONTROL1_CIPHER_MODE_ECB (0 << 4)
+#define MXS_DCP_CONTROL1_CIPHER_SELECT_AES128 (0 << 0)
+
+static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
+{
+ struct dcp *sdcp = global_sdcp;
+ const int chan = actx->chan;
+ uint32_t stat;
+ int ret;
+ dma_addr_t desc_phys = sdcp->coh_phys +
+ offsetof(struct dcp_coherent_block, desc[actx->chan]);
+
+ INIT_COMPLETION(sdcp->completion[chan]);
+
+ /* Clear status register. */
+ writel(0xffffffff, sdcp->base + MXS_DCP_CH_N_STAT_CLR(chan));
+
+ /* Load the DMA descriptor. */
+ writel(desc_phys, sdcp->base + MXS_DCP_CH_N_CMDPTR(chan));
+
+ /* Increment the semaphore to start the DMA transfer. */
+ writel(1, sdcp->base + MXS_DCP_CH_N_SEMA(chan));
+
+ ret = wait_for_completion_timeout(&sdcp->completion[chan],
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ dev_err(sdcp->dev, "Channel %i timeout (DCP_STAT=0x%08x)\n",
+ chan, readl(sdcp->base + MXS_DCP_STAT));
+ return -ETIMEDOUT;
+ }
+
+ stat = readl(sdcp->base + MXS_DCP_CH_N_STAT(chan));
+ if (stat & 0xff) {
+ dev_err(sdcp->dev, "Channel %i error (CH_STAT=0x%08x)\n",
+ chan, stat);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Encryption (AES128)
+ */
+static void mxs_dcp_assemble_desc_aes(struct dcp_async_ctx *actx, int init)
+{
+ struct dcp *sdcp = global_sdcp;
+ struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
+
+ dma_addr_t key_phys = sdcp->coh_phys +
+ offsetof(struct dcp_coherent_block, aes_key);
+ dma_addr_t src_phys = sdcp->coh_phys +
+ offsetof(struct dcp_coherent_block, aes_in_buf);
+ dma_addr_t dst_phys = sdcp->coh_phys +
+ offsetof(struct dcp_coherent_block, aes_out_buf);
+
+ /* Fill in the DMA descriptor. */
+ desc->control0 = MXS_DCP_CONTROL0_DECR_SEMAPHORE |
+ MXS_DCP_CONTROL0_INTERRUPT |
+ MXS_DCP_CONTROL0_ENABLE_CIPHER;
+
+ /* Payload contains the key. */
+ desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY;
+
+ if (actx->enc)
+ desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT;
+ if (init)
+ desc->control0 |= MXS_DCP_CONTROL0_CIPHER_INIT;
+
+ desc->control1 = MXS_DCP_CONTROL1_CIPHER_SELECT_AES128;
+
+ if (actx->ecb)
+ desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_ECB;
+ else
+ desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_CBC;
+
+ desc->next_cmd_addr = 0;
+ desc->source = src_phys;
+ desc->destination = dst_phys;
+ desc->size = actx->fill;
+ desc->payload = key_phys;
+ desc->status = 0;
+}
+
+static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
+{
+ struct dcp *sdcp = global_sdcp;
+
+ struct ablkcipher_request *req = ablkcipher_request_cast(arq);
+ struct dcp_async_ctx *actx = crypto_tfm_ctx(arq->tfm);
+
+ struct scatterlist *dst = req->dst;
+ struct scatterlist *src = req->src;
+ const int nents = sg_nents(req->src);
+
+ const int out_off = DCP_BUF_SZ;
+ uint8_t *in_buf = sdcp->coh->aes_in_buf;
+ uint8_t *out_buf = sdcp->coh->aes_out_buf;
+
+ uint8_t *out_tmp, *src_buf, *dst_buf = NULL;
+ uint32_t dst_off = 0;
+
+ uint8_t *key = sdcp->coh->aes_key;
+
+ int ret = 0;
+ int split = 0;
+ unsigned int i, len, clen, rem = 0;
+ int init = 0;
+
+ actx->fill = 0;
+
+ /* Copy the key from the temporary location. */
+ memcpy(key, actx->key, actx->key_len);
+
+ if (!actx->ecb) {
+ /* Copy the CBC IV just past the key. */
+ memcpy(key + AES_KEYSIZE_128, req->info, AES_KEYSIZE_128);
+ /* CBC needs the INIT set. */
+ init = 1;
+ } else {
+ memset(key + AES_KEYSIZE_128, 0, AES_KEYSIZE_128);
+ }
+
+ for_each_sg(req->src, src, nents, i) {
+ src_buf = sg_virt(src);
+ len = sg_dma_len(src);
+
+ do {
+ if (actx->fill + len > out_off)
+ clen = out_off - actx->fill;
+ else
+ clen = len;
+
+ memcpy(in_buf + actx->fill, src_buf, clen);
+ len -= clen;
+ src_buf += clen;
+ actx->fill += clen;
+
+ /*
+ * If we filled the buffer or this is the last SG,
+ * submit the buffer.
+ */
+ if (actx->fill == out_off || sg_is_last(src)) {
+ mxs_dcp_assemble_desc_aes(actx, init);
+ ret = mxs_dcp_start_dma(actx);
+ if (ret)
+ return ret;
+ init = 0;
+
+ out_tmp = out_buf;
+ while (dst && actx->fill) {
+ if (!split) {
+ dst_buf = sg_virt(dst);
+ dst_off = 0;
+ }
+ rem = min(sg_dma_len(dst) - dst_off,
+ actx->fill);
+
+ memcpy(dst_buf + dst_off, out_tmp, rem);
+ out_tmp += rem;
+ dst_off += rem;
+ actx->fill -= rem;
+
+ if (dst_off == sg_dma_len(dst)) {
+ dst = sg_next(dst);
+ split = 0;
+ } else {
+ split = 1;
+ }
+ }
+ }
+ } while (len);
+ }
+
+ return ret;
+}
+
+static int dcp_chan_thread_aes(void *data)
+{
+ struct dcp *sdcp = global_sdcp;
+ const int chan = DCP_CHAN_CRYPTO;
+
+ struct crypto_async_request *backlog;
+ struct crypto_async_request *arq;
+
+ int ret;
+
+ do {
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ mutex_lock(&sdcp->mutex[chan]);
+ backlog = crypto_get_backlog(&sdcp->queue[chan]);
+ arq = crypto_dequeue_request(&sdcp->queue[chan]);
+ mutex_unlock(&sdcp->mutex[chan]);
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+
+ if (arq) {
+ ret = mxs_dcp_aes_block_crypt(arq);
+ arq->complete(arq, ret);
+ continue;
+ }
+
+ schedule();
+ } while (!kthread_should_stop());
+
+ return 0;
+}
+
+static int mxs_dcp_block_fallback(struct ablkcipher_request *req, int enc)
+{
+ struct crypto_tfm *tfm =
+ crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+ struct dcp_async_ctx *ctx = crypto_ablkcipher_ctx(
+ crypto_ablkcipher_reqtfm(req));
+ int ret;
+
+ ablkcipher_request_set_tfm(req, ctx->fallback);
+
+ if (enc)
+ ret = crypto_ablkcipher_encrypt(req);
+ else
+ ret = crypto_ablkcipher_decrypt(req);
+
+ ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+
+ return ret;
+}
+
+static int mxs_dcp_aes_enqueue(struct ablkcipher_request *req, int enc, int ecb)
+{
+ struct dcp *sdcp = global_sdcp;
+ struct crypto_async_request *arq = &req->base;
+ struct dcp_async_ctx *actx = crypto_tfm_ctx(arq->tfm);
+ int ret;
+
+ if (unlikely(actx->key_len != AES_KEYSIZE_128))
+ return mxs_dcp_block_fallback(req, enc);
+
+ actx->enc = enc;
+ actx->ecb = ecb;
+ actx->chan = DCP_CHAN_CRYPTO;
+
+ mutex_lock(&sdcp->mutex[actx->chan]);
+ ret = crypto_enqueue_request(&sdcp->queue[actx->chan], &req->base);
+ mutex_unlock(&sdcp->mutex[actx->chan]);
+
+ wake_up_process(sdcp->thread[actx->chan]);
+
+ return -EINPROGRESS;
+}
+
+static int mxs_dcp_aes_ecb_decrypt(struct ablkcipher_request *req)
+{
+ return mxs_dcp_aes_enqueue(req, 0, 1);
+}
+
+static int mxs_dcp_aes_ecb_encrypt(struct ablkcipher_request *req)
+{
+ return mxs_dcp_aes_enqueue(req, 1, 1);
+}
+
+static int mxs_dcp_aes_cbc_decrypt(struct ablkcipher_request *req)
+{
+ return mxs_dcp_aes_enqueue(req, 0, 0);
+}
+
+static int mxs_dcp_aes_cbc_encrypt(struct ablkcipher_request *req)
+{
+ return mxs_dcp_aes_enqueue(req, 1, 0);
+}
+
+static int mxs_dcp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+ unsigned int len)
+{
+ struct dcp_async_ctx *actx = crypto_ablkcipher_ctx(tfm);
+ unsigned int ret;
+
+ /*
+ * AES 128 is supposed by the hardware, store key into temporary
+ * buffer and exit. We must use the temporary buffer here, since
+ * there can still be an operation in progress.
+ */
+ actx->key_len = len;
+ if (len == AES_KEYSIZE_128) {
+ memcpy(actx->key, key, len);
+ return 0;
+ }
+
+ /* Check if the key size is supported by kernel at all. */
+ if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
+ tfm->base.crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ /*
+ * If the requested AES key size is not supported by the hardware,
+ * but is supported by in-kernel software implementation, we use
+ * software fallback.
+ */
+ actx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ actx->fallback->base.crt_flags |=
+ tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK;
+
+ ret = crypto_ablkcipher_setkey(actx->fallback, key, len);
+ if (!ret)
+ return 0;
+
+ tfm->base.crt_flags &= ~CRYPTO_TFM_RES_MASK;
+ tfm->base.crt_flags |=
+ actx->fallback->base.crt_flags & CRYPTO_TFM_RES_MASK;
+
+ return ret;
+}
+
+static int mxs_dcp_aes_fallback_init(struct crypto_tfm *tfm)
+{
+ const char *name = tfm->__crt_alg->cra_name;
+ const uint32_t flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK;
+ struct dcp_async_ctx *actx = crypto_tfm_ctx(tfm);
+ struct crypto_ablkcipher *blk;
+
+ blk = crypto_alloc_ablkcipher(name, 0, flags);
+ if (IS_ERR(blk))
+ return PTR_ERR(blk);
+
+ actx->fallback = blk;
+ tfm->crt_ablkcipher.reqsize = sizeof(struct dcp_async_ctx);
+ return 0;
+}
+
+static void mxs_dcp_aes_fallback_exit(struct crypto_tfm *tfm)
+{
+ struct dcp_async_ctx *actx = crypto_tfm_ctx(tfm);
+
+ crypto_free_ablkcipher(actx->fallback);
+ actx->fallback = NULL;
+}
+
+/*
+ * Hashing (SHA1/SHA256)
+ */
+static void mxs_dcp_assemble_desc_sha(struct ahash_request *req)
+{
+ struct dcp *sdcp = global_sdcp;
+
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
+ struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
+
+ struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
+ dma_addr_t digest_phys = sdcp->coh_phys +
+ offsetof(struct dcp_coherent_block, sha_digest);
+ dma_addr_t buf_phys = sdcp->coh_phys +
+ offsetof(struct dcp_coherent_block, sha_in_buf);
+
+ /* Fill in the DMA descriptor. */
+ desc->control0 = MXS_DCP_CONTROL0_DECR_SEMAPHORE |
+ MXS_DCP_CONTROL0_INTERRUPT |
+ MXS_DCP_CONTROL0_ENABLE_HASH;
+ if (rctx->init)
+ desc->control0 |= MXS_DCP_CONTROL0_HASH_INIT;
+
+ desc->control1 = actx->alg;
+ desc->next_cmd_addr = 0;
+ desc->source = buf_phys;
+ desc->destination = 0;
+ desc->size = actx->fill;
+ desc->payload = 0;
+ desc->status = 0;
+
+ /* Set HASH_TERM bit for last transfer block. */
+ if (rctx->fini) {
+ desc->control0 |= MXS_DCP_CONTROL0_HASH_TERM;
+ desc->payload = digest_phys;
+ }
+}
+
+static int dcp_sha_req_to_buf(struct crypto_async_request *arq)
+{
+ struct dcp *sdcp = global_sdcp;
+
+ struct ahash_request *req = ahash_request_cast(arq);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
+ struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
+ struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
+ const int nents = sg_nents(req->src);
+
+ uint8_t *digest = sdcp->coh->sha_digest;
+ uint8_t *in_buf = sdcp->coh->sha_in_buf;
+
+ uint8_t *src_buf;
+
+ struct scatterlist *src;
+
+ unsigned int i, len, clen;
+ int ret;
+
+ int fin = rctx->fini;
+ if (fin)
+ rctx->fini = 0;
+
+ for_each_sg(req->src, src, nents, i) {
+ src_buf = sg_virt(src);
+ len = sg_dma_len(src);
+
+ do {
+ if (actx->fill + len > DCP_BUF_SZ)
+ clen = DCP_BUF_SZ - actx->fill;
+ else
+ clen = len;
+
+ memcpy(in_buf + actx->fill, src_buf, clen);
+ len -= clen;
+ src_buf += clen;
+ actx->fill += clen;
+
+ /*
+ * If we filled the buffer and still have some
+ * more data, submit the buffer.
+ */
+ if (len && actx->fill == DCP_BUF_SZ) {
+ mxs_dcp_assemble_desc_sha(req);
+ ret = mxs_dcp_start_dma(actx);
+ if (ret)
+ return ret;
+ actx->fill = 0;
+ rctx->init = 0;
+ }
+ } while (len);
+ }
+
+ if (fin) {
+ rctx->fini = 1;
+
+ /* Submit whatever is left. */
+ mxs_dcp_assemble_desc_sha(req);
+ ret = mxs_dcp_start_dma(actx);
+ if (ret || !req->result)
+ return ret;
+
+ /* For some reason, the result is flipped. */
+ for (i = 0; i < halg->digestsize; i++)
+ req->result[i] = digest[halg->digestsize - i - 1];
+ }
+
+ return 0;
+}
+
+static int dcp_chan_thread_sha(void *data)
+{
+ struct dcp *sdcp = global_sdcp;
+ const int chan = DCP_CHAN_HASH_SHA;
+
+ struct crypto_async_request *backlog;
+ struct crypto_async_request *arq;
+
+ struct dcp_sha_req_ctx *rctx;
+
+ struct ahash_request *req;
+ int ret, fini;
+
+ do {
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ mutex_lock(&sdcp->mutex[chan]);
+ backlog = crypto_get_backlog(&sdcp->queue[chan]);
+ arq = crypto_dequeue_request(&sdcp->queue[chan]);
+ mutex_unlock(&sdcp->mutex[chan]);
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+
+ if (arq) {
+ req = ahash_request_cast(arq);
+ rctx = ahash_request_ctx(req);
+
+ ret = dcp_sha_req_to_buf(arq);
+ fini = rctx->fini;
+ arq->complete(arq, ret);
+ if (!fini)
+ continue;
+ }
+
+ schedule();
+ } while (!kthread_should_stop());
+
+ return 0;
+}
+
+static int dcp_sha_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
+
+ struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
+
+ /*
+ * Start hashing session. The code below only inits the
+ * hashing session context, nothing more.
+ */
+ memset(actx, 0, sizeof(*actx));
+
+ if (strcmp(halg->base.cra_name, "sha1") == 0)
+ actx->alg = MXS_DCP_CONTROL1_HASH_SELECT_SHA1;
+ else
+ actx->alg = MXS_DCP_CONTROL1_HASH_SELECT_SHA256;
+
+ actx->fill = 0;
+ actx->hot = 0;
+ actx->chan = DCP_CHAN_HASH_SHA;
+
+ mutex_init(&actx->mutex);
+
+ return 0;
+}
+
+static int dcp_sha_update(struct ahash_request *req)
+{
+ struct dcp *sdcp = global_sdcp;
+
+ struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
+
+ int ret;
+
+ /*
+ * Ignore requests that have no data in them and are not
+ * the trailing requests in the stream of requests.
+ */
+ if (!req->nbytes && !rctx->fini)
+ return 0;
+
+ mutex_lock(&actx->mutex);
+ if (!actx->hot) {
+ actx->hot = 1;
+ rctx->init = 1;
+ }
+
+ mutex_lock(&sdcp->mutex[actx->chan]);
+ ret = crypto_enqueue_request(&sdcp->queue[actx->chan], &req->base);
+ mutex_unlock(&sdcp->mutex[actx->chan]);
+
+ wake_up_process(sdcp->thread[actx->chan]);
+ mutex_unlock(&actx->mutex);
+
+ return -EINPROGRESS;
+}
+
+static int dcp_sha_final(struct ahash_request *req)
+{
+ struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
+
+ ahash_request_set_crypt(req, NULL, req->result, 0);
+
+ rctx->fini = 1;
+ return dcp_sha_update(req);
+}
+
+static int dcp_sha_finup(struct ahash_request *req)
+{
+ struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
+
+ rctx->fini = 1;
+ return dcp_sha_update(req);
+}
+
+static int dcp_sha_digest(struct ahash_request *req)
+{
+ int ret;
+
+ ret = dcp_sha_init(req);
+ if (ret)
+ return ret;
+
+ return dcp_sha_finup(req);
+}
+
+static int dcp_sha_cra_init(struct crypto_tfm *tfm)
+{
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct dcp_sha_req_ctx));
+ return 0;
+}
+
+static void dcp_sha_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+/* AES 128 ECB and AES 128 CBC */
+static struct crypto_alg dcp_aes_algs[] = {
+ [0] = {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-dcp",
+ .cra_priority = 400,
+ .cra_alignmask = 15,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_init = mxs_dcp_aes_fallback_init,
+ .cra_exit = mxs_dcp_aes_fallback_exit,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dcp_async_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = mxs_dcp_aes_setkey,
+ .encrypt = mxs_dcp_aes_ecb_encrypt,
+ .decrypt = mxs_dcp_aes_ecb_decrypt
+ }
+ }
+ },
+ [1] = {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-dcp",
+ .cra_priority = 400,
+ .cra_alignmask = 15,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_init = mxs_dcp_aes_fallback_init,
+ .cra_exit = mxs_dcp_aes_fallback_exit,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dcp_async_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = mxs_dcp_aes_setkey,
+ .encrypt = mxs_dcp_aes_cbc_encrypt,
+ .decrypt = mxs_dcp_aes_cbc_decrypt,
+ .ivsize = AES_BLOCK_SIZE,
+ }
+ }
+ },
+};
+
+/* SHA1 */
+static struct ahash_alg dcp_sha1_alg = {
+ .init = dcp_sha_init,
+ .update = dcp_sha_update,
+ .final = dcp_sha_final,
+ .finup = dcp_sha_finup,
+ .digest = dcp_sha_digest,
+ .halg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ .base = {
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1-dcp",
+ .cra_priority = 400,
+ .cra_alignmask = 63,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dcp_async_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_init = dcp_sha_cra_init,
+ .cra_exit = dcp_sha_cra_exit,
+ }
+ }
+};
+
+/* SHA256 */
+static struct ahash_alg dcp_sha256_alg = {
+ .init = dcp_sha_init,
+ .update = dcp_sha_update,
+ .final = dcp_sha_final,
+ .finup = dcp_sha_finup,
+ .digest = dcp_sha_digest,
+ .halg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .base = {
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256-dcp",
+ .cra_priority = 400,
+ .cra_alignmask = 63,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dcp_async_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_init = dcp_sha_cra_init,
+ .cra_exit = dcp_sha_cra_exit,
+ }
+ }
+};
+
+static irqreturn_t mxs_dcp_irq(int irq, void *context)
+{
+ struct dcp *sdcp = context;
+ uint32_t stat;
+ int i;
+
+ stat = readl(sdcp->base + MXS_DCP_STAT);
+ stat &= MXS_DCP_STAT_IRQ_MASK;
+ if (!stat)
+ return IRQ_NONE;
+
+ /* Clear the interrupts. */
+ writel(stat, sdcp->base + MXS_DCP_STAT_CLR);
+
+ /* Complete the DMA requests that finished. */
+ for (i = 0; i < DCP_MAX_CHANS; i++)
+ if (stat & (1 << i))
+ complete(&sdcp->completion[i]);
+
+ return IRQ_HANDLED;
+}
+
+static int mxs_dcp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dcp *sdcp = NULL;
+ int i, ret;
+
+ struct resource *iores;
+ int dcp_vmi_irq, dcp_irq;
+
+ mutex_lock(&global_mutex);
+ if (global_sdcp) {
+ dev_err(dev, "Only one DCP instance allowed!\n");
+ ret = -ENODEV;
+ goto err_mutex;
+ }
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dcp_vmi_irq = platform_get_irq(pdev, 0);
+ dcp_irq = platform_get_irq(pdev, 1);
+ if (!iores || dcp_vmi_irq < 0 || dcp_irq < 0) {
+ ret = -EINVAL;
+ goto err_mutex;
+ }
+
+ sdcp = devm_kzalloc(dev, sizeof(*sdcp), GFP_KERNEL);
+ if (!sdcp) {
+ ret = -ENOMEM;
+ goto err_mutex;
+ }
+
+ sdcp->dev = dev;
+ sdcp->base = devm_ioremap_resource(dev, iores);
+ if (IS_ERR(sdcp->base)) {
+ ret = PTR_ERR(sdcp->base);
+ goto err_mutex;
+ }
+
+ ret = devm_request_irq(dev, dcp_vmi_irq, mxs_dcp_irq, 0,
+ "dcp-vmi-irq", sdcp);
+ if (ret) {
+ dev_err(dev, "Failed to claim DCP VMI IRQ!\n");
+ goto err_mutex;
+ }
+
+ ret = devm_request_irq(dev, dcp_irq, mxs_dcp_irq, 0,
+ "dcp-irq", sdcp);
+ if (ret) {
+ dev_err(dev, "Failed to claim DCP IRQ!\n");
+ goto err_mutex;
+ }
+
+ /* Allocate coherent helper block. */
+ sdcp->coh = dma_alloc_coherent(dev, sizeof(struct dcp_coherent_block),
+ &sdcp->coh_phys, GFP_KERNEL);
+ if (!sdcp->coh) {
+ dev_err(dev, "Error allocating coherent block\n");
+ ret = -ENOMEM;
+ goto err_mutex;
+ }
+
+ /* Restart the DCP block. */
+ stmp_reset_block(sdcp->base);
+
+ /* Initialize control register. */
+ writel(MXS_DCP_CTRL_GATHER_RESIDUAL_WRITES |
+ MXS_DCP_CTRL_ENABLE_CONTEXT_CACHING | 0xf,
+ sdcp->base + MXS_DCP_CTRL);
+
+ /* Enable all DCP DMA channels. */
+ writel(MXS_DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK,
+ sdcp->base + MXS_DCP_CHANNELCTRL);
+
+ /*
+ * We do not enable context switching. Give the context buffer a
+ * pointer to an illegal address so if context switching is
+ * inadvertantly enabled, the DCP will return an error instead of
+ * trashing good memory. The DCP DMA cannot access ROM, so any ROM
+ * address will do.
+ */
+ writel(0xffff0000, sdcp->base + MXS_DCP_CONTEXT);
+ for (i = 0; i < DCP_MAX_CHANS; i++)
+ writel(0xffffffff, sdcp->base + MXS_DCP_CH_N_STAT_CLR(i));
+ writel(0xffffffff, sdcp->base + MXS_DCP_STAT_CLR);
+
+ global_sdcp = sdcp;
+
+ platform_set_drvdata(pdev, sdcp);
+
+ for (i = 0; i < DCP_MAX_CHANS; i++) {
+ mutex_init(&sdcp->mutex[i]);
+ init_completion(&sdcp->completion[i]);
+ crypto_init_queue(&sdcp->queue[i], 50);
+ }
+
+ /* Create the SHA and AES handler threads. */
+ sdcp->thread[DCP_CHAN_HASH_SHA] = kthread_create(dcp_chan_thread_sha,
+ NULL, "mxs_dcp_chan/sha");
+ if (IS_ERR(sdcp->thread[DCP_CHAN_HASH_SHA])) {
+ dev_err(dev, "Error starting SHA thread!\n");
+ ret = PTR_ERR(sdcp->thread[DCP_CHAN_HASH_SHA]);
+ goto err_free_coherent;
+ }
+
+ sdcp->thread[DCP_CHAN_CRYPTO] = kthread_create(dcp_chan_thread_aes,
+ NULL, "mxs_dcp_chan/aes");
+ if (IS_ERR(sdcp->thread[DCP_CHAN_CRYPTO])) {
+ dev_err(dev, "Error starting SHA thread!\n");
+ ret = PTR_ERR(sdcp->thread[DCP_CHAN_CRYPTO]);
+ goto err_destroy_sha_thread;
+ }
+
+ /* Register the various crypto algorithms. */
+ sdcp->caps = readl(sdcp->base + MXS_DCP_CAPABILITY1);
+
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_AES128) {
+ ret = crypto_register_algs(dcp_aes_algs,
+ ARRAY_SIZE(dcp_aes_algs));
+ if (ret) {
+ /* Failed to register algorithm. */
+ dev_err(dev, "Failed to register AES crypto!\n");
+ goto err_destroy_aes_thread;
+ }
+ }
+
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_SHA1) {
+ ret = crypto_register_ahash(&dcp_sha1_alg);
+ if (ret) {
+ dev_err(dev, "Failed to register %s hash!\n",
+ dcp_sha1_alg.halg.base.cra_name);
+ goto err_unregister_aes;
+ }
+ }
+
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_SHA256) {
+ ret = crypto_register_ahash(&dcp_sha256_alg);
+ if (ret) {
+ dev_err(dev, "Failed to register %s hash!\n",
+ dcp_sha256_alg.halg.base.cra_name);
+ goto err_unregister_sha1;
+ }
+ }
+
+ return 0;
+
+err_unregister_sha1:
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_SHA1)
+ crypto_unregister_ahash(&dcp_sha1_alg);
+
+err_unregister_aes:
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_AES128)
+ crypto_unregister_algs(dcp_aes_algs, ARRAY_SIZE(dcp_aes_algs));
+
+err_destroy_aes_thread:
+ kthread_stop(sdcp->thread[DCP_CHAN_CRYPTO]);
+
+err_destroy_sha_thread:
+ kthread_stop(sdcp->thread[DCP_CHAN_HASH_SHA]);
+
+err_free_coherent:
+ dma_free_coherent(sdcp->dev,
+ 4 * sizeof(struct dcp_coherent_block),
+ sdcp->coh, sdcp->coh_phys);
+err_mutex:
+ mutex_unlock(&global_mutex);
+ return ret;
+}
+
+static int mxs_dcp_remove(struct platform_device *pdev)
+{
+ struct dcp *sdcp;
+ int i;
+
+ sdcp = platform_get_drvdata(pdev);
+
+ kthread_stop(sdcp->thread[DCP_CHAN_HASH_SHA]);
+ kthread_stop(sdcp->thread[DCP_CHAN_CRYPTO]);
+
+ platform_set_drvdata(pdev, NULL);
+
+ dma_free_coherent(sdcp->dev, sizeof(struct dcp_coherent_block),
+ sdcp->coh, sdcp->coh_phys);
+
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_SHA256)
+ crypto_unregister_ahash(&dcp_sha256_alg);
+
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_SHA1)
+ crypto_unregister_ahash(&dcp_sha1_alg);
+
+ if (sdcp->caps & MXS_DCP_CAPABILITY1_AES128) {
+ for (i = ARRAY_SIZE(dcp_aes_algs); i >= 0; i--)
+ crypto_unregister_alg(&dcp_aes_algs[i]);
+ }
+
+ mutex_lock(&global_mutex);
+ global_sdcp = NULL;
+ mutex_unlock(&global_mutex);
+
+ return 0;
+}
+
+static const struct of_device_id mxs_dcp_dt_ids[] = {
+ {.compatible = "fsl,mxs-dcp", .data = NULL,},
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, mxs_dcp_dt_ids);
+
+static struct platform_driver mxs_dcp_driver = {
+ .probe = mxs_dcp_probe,
+ .remove = mxs_dcp_remove,
+ .driver = {
+ .name = "mxs-dcp",
+ .owner = THIS_MODULE,
+ .of_match_table = mxs_dcp_dt_ids,
+ },
+};
+
+module_platform_driver(mxs_dcp_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("Freescale MXS DCP Driver");
+MODULE_LICENSE("GPL");
--
1.8.4.rc3
^ permalink raw reply related
* Re: [PATCH 2/3] ARM: mxs: crypto: Add Freescale MXS DCP driver
From: Fabio Estevam @ 2013-09-26 11:27 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-crypto, Herbert Xu, linux-arm-kernel@lists.infradead.org,
David S. Miller, Shawn Guo
In-Reply-To: <1380194306-5243-2-git-send-email-marex@denx.de>
Hi Marek,
On Thu, Sep 26, 2013 at 8:18 AM, Marek Vasut <marex@denx.de> wrote:
> Add support for the MXS DCP block. The driver currently supports
> SHA-1/SHA-256 hashing and AES-128 CBC/ECB modes. The non-standard
> CRC32 is not yet supported.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: David S. Miller <davem@davemloft.net>
> ---
> drivers/crypto/Kconfig | 17 +
> drivers/crypto/Makefile | 1 +
> drivers/crypto/mxs-dcp.c | 1082 ++++++++++++++++++++++++++++++++++++++++++++++
What about the existing DCP driver at drivers/crypto/dcp.c ?
Why do we need to have two drivers for the same IP block? It looks
confusing to have both.
Regards,
Fabio Estevam
^ permalink raw reply
* Re: [PATCH 3/3] ARM: mxs: dts: Enable DCP for MXS
From: Lothar Waßmann @ 2013-09-26 11:36 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-crypto, Fabio Estevam, Herbert Xu, Shawn Guo,
David S. Miller, linux-arm-kernel
In-Reply-To: <1380194306-5243-3-git-send-email-marex@denx.de>
Hi,
Marek Vasut writes:
> Enable the DCP by default on both i.MX23 and i.MX28.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Fabio Estevam <fabio.estevam@freescale.com>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> To: linux-crypto@vger.kernel.org
> ---
> arch/arm/boot/dts/imx23.dtsi | 4 +++-
> arch/arm/boot/dts/imx28.dtsi | 5 +++--
> 2 files changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
> index 87faa6e..0630a9a 100644
> --- a/arch/arm/boot/dts/imx23.dtsi
> +++ b/arch/arm/boot/dts/imx23.dtsi
> @@ -337,8 +337,10 @@
> };
>
> dcp@80028000 {
> + compatible = "fsl,mxs-dcp";
> reg = <0x80028000 0x2000>;
> - status = "disabled";
> + interrupts = <53 54>;
> + status = "okay";
> };
AFAICT the policy seems to be that nodes, that are always enabled
don't get a 'status' property at all.
> pxp@8002a000 {
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index 918d419..8b5ad60 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -782,9 +782,10 @@
> };
>
> dcp: dcp@80028000 {
> + compatible = "fsl,mxs-dcp";
> reg = <0x80028000 0x2000>;
> - interrupts = <52 53 54>;
> - compatible = "fsl-dcp";
>
What about drivers/crypto/dcp.c that is currently using this property?
Lothar Waßmann
--
___________________________________________________________
Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996
www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox