linux-crypto.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH] crypto: ccp - Assign DMA commands to the channel's CCP
       [not found] <20170310180341.21062.82465.stgit@taos>
@ 2017-03-13 19:35 ` Gary R Hook
  2017-03-14  7:17   ` Stephan Müller
  0 siblings, 1 reply; 7+ messages in thread
From: Gary R Hook @ 2017-03-13 19:35 UTC (permalink / raw)
  To: linux-crypto; +Cc: Stephan Müller

On 03/03/2017 7:15 AM, Stephan Mueller wrote:

> Am Donnerstag, 2. März 2017, 22:26:54 CET schrieb Gary R Hook:
>
> Hi Gary,

Thanks for your comments, Stephan.

>
> > A version 5 device provides the primitive commands
> > required for AES GCM. This patch adds support for
> > en/decryption.
> >
> > Signed-off-by: Gary R Hook <gary.hook@amd.com>
> > ---
> >  drivers/crypto/ccp/Makefile                |    1
> >  drivers/crypto/ccp/ccp-crypto-aes-galois.c |  257
> > ++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-main.c       |
> > 12 +
> >  drivers/crypto/ccp/ccp-crypto.h            |   14 ++
> >  drivers/crypto/ccp/ccp-dev-v5.c            |    2
> >  drivers/crypto/ccp/ccp-dev.h               |    1
> >  drivers/crypto/ccp/ccp-ops.c               |  252
> > +++++++++++++++++++++++++++ include/linux/ccp.h                        |
> > 9 +
> >  8 files changed, 548 insertions(+)
> >  create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c
> >
> > diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> > b/drivers/crypto/ccp/ccp-crypto-aes-galois.c new file mode 100644
> > index 0000000..8bc18c9
> > --- /dev/null
> > +++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> > @@ -0,0 +1,257 @@
> > +/*
> > + * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support
> > + *
> > + * Copyright (C) 2016 Advanced Micro Devices, Inc.
> > + *
> > + * Author: Gary R Hook <gary.hook@amd.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/sched.h>
> > +#include <linux/delay.h>
> > +#include <linux/scatterlist.h>
> > +#include <linux/crypto.h>
> > +#include <crypto/internal/aead.h>
> > +#include <crypto/algapi.h>
> > +#include <crypto/aes.h>
> > +#include <crypto/ctr.h>
> > +#include <crypto/scatterwalk.h>
> > +#include <linux/delay.h>
> > +
> > +#include "ccp-crypto.h"
> > +
> > +#define    AES_GCM_IVSIZE  12
> > +
> > +static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int
> > ret) +{
> > +   return ret;
> > +}
> > +
> > +static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
> > +                         unsigned int key_len)
> > +{
> > +   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> > +
> > +   switch (key_len) {
> > +   case AES_KEYSIZE_128:
> > +           ctx->u.aes.type = CCP_AES_TYPE_128;
> > +           break;
> > +   case AES_KEYSIZE_192:
> > +           ctx->u.aes.type = CCP_AES_TYPE_192;
> > +           break;
> > +   case AES_KEYSIZE_256:
> > +           ctx->u.aes.type = CCP_AES_TYPE_256;
> > +           break;
> > +   default:
> > +           crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
> > +           return -EINVAL;
> > +   }
> > +
> > +   ctx->u.aes.mode = CCP_AES_MODE_GCM;
> > +   ctx->u.aes.key_len = key_len;
> > +
> > +   memcpy(ctx->u.aes.key, key, key_len);
> > +   sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
> > +                              unsigned int authsize)
> > +{
> > +   return 0;
> > +}
> > +
> > +static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
> > +{
> > +   struct crypto_aead *tfm = crypto_aead_reqtfm(req);
> > +   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> > +   struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
> > +   struct scatterlist *iv_sg = NULL;
> > +   unsigned int iv_len = 0;
> > +   int i;
> > +   int ret = 0;
> > +
> > +   if (!ctx->u.aes.key_len)
> > +           return -EINVAL;
> > +
> > +   if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
> > +           return -EINVAL;
> > +
> > +   if (!req->iv)
> > +           return -EINVAL;
> > +
> > +   /*
> > +    * 5 parts:
> > +    *   plaintext/ciphertext input
> > +    *   AAD
> > +    *   key
> > +    *   IV
> > +    *   Destination+tag buffer
> > +    */
> > +
> > +   /* According to the way AES GCM has been implemented here,
> > +    * per RFC 4106 it seems, the provided IV is fixed at 12 bytes,
>
> When you have that restriction, should the cipher be called rfc4106(gcm(aes))?
>
> But then, the key is 4 bytes longer than a normal AES key as it contains the
> leading 32 bits of the IV.

I had my wires crossed due to an incomplete understanding of an AEAD cipher
in general, and GCM in particular. I'm hopeful that someone can help me
understand:

For the AES GCM encryption tests in testmgr.h, where there is an IV, 
they're all
12 bytes in length. As I understand AES GCM the IV can be anywhere from 
1 to 2^64
bits in length; the value of 96 makes for convenience and efficiency. 
But it's
neither a requirement nor restriction.

There are no tests (in testmgr.h) that use an IV length other than  0 or 96.
My comment about RFC4106 has to do with requiring an IV 0f 96 bits + a 
word that
is incremented for each block (making every nonce unique, per the 
requirement).
But let's ignore that, please.

It looks as if:

What seems to be missing is the ability to register a (GCM) transform 
that can
handle an IV of arbitrary (allowable) length. I have to specify the 
length (ivsize)
when I register an algorithm, and everything I see in the existing code 
appears
to expect a GCM ivsize to be 96 bits, period (or zero). This is what I 
meant when
I referenced RFC4106: I perceive restrictions not in my code, but n the 
way GCM seems
to be supported in the crypto AEAD framework. A complete GCM 
implementation would not
seem to have a restriction to a specific IV length (rather, a range of 
allowed
values).

Is my reading of the GCM description in error? Do we need/want the ability
to have a flexible IV length for GCM? What am I not understanding?

For reference, I'm working from the NIST doc:
http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf

>
> > +    * occupies the beginning of the IV array. Write a 32-bit
> > +    * integer after that (bytes 13-16) with a value of "1".
> > +    */
> > +   memcpy(rctx->iv, req->iv, AES_GCM_IVSIZE);
> > +   for (i = 0; i < 3; i++)
> > +           rctx->iv[i + AES_GCM_IVSIZE] = 0;
> > +   rctx->iv[AES_BLOCK_SIZE - 1] = 1;
> > +
> > +   /* Set up a scatterlist for the IV */
> > +   iv_sg = &rctx->iv_sg;
> > +   iv_len = AES_BLOCK_SIZE;
> > +   sg_init_one(iv_sg, rctx->iv, iv_len);
> > +
> > +   /* The AAD + plaintext are concatenated in the src buffer */
> > +   memset(&rctx->cmd, 0, sizeof(rctx->cmd));
> > +   INIT_LIST_HEAD(&rctx->cmd.entry);
> > +   rctx->cmd.engine = CCP_ENGINE_AES;
> > +   rctx->cmd.u.aes.type = ctx->u.aes.type;
> > +   rctx->cmd.u.aes.mode = ctx->u.aes.mode;
> > +   rctx->cmd.u.aes.action =
> > +           (encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT;
>
> Instead of this condition, why not changing the encrypt/decrypt function to
> directly provide the enc/dec variables?

Our existing code that uses this construct doesn't do that, but I
have no problem with the idea. Done.

> > +   rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
> > +   rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
> > +   rctx->cmd.u.aes.iv = iv_sg;
> > +   rctx->cmd.u.aes.iv_len = iv_len;
> > +   rctx->cmd.u.aes.src = req->src;
> > +   rctx->cmd.u.aes.src_len = req->cryptlen;
> > +   rctx->cmd.u.aes.aad_len = req->assoclen;
>
> Just to be on the safe side: is the implementation good when cryptlen or
> assoclen is 0?

The engine has been designed to handle those two conditions. I've been
watching the discussions around these issues.

The first encryption test in testmgr.h has no input data nor IV. This
implementation passes that test.

The second encryption test in testmgr.h has input data but no IV, and this
implementation passes.

Is that an acceptable validation, or do we need more?

Thanks,
Gary


-- 
This is my day job. Follow me at:
IG/Twitter/Facebook: @grhookphoto
IG/Twitter/Facebook: @grhphotographer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] crypto: ccp - Assign DMA commands to the channel's CCP
  2017-03-13 19:35 ` [PATCH] crypto: ccp - Assign DMA commands to the channel's CCP Gary R Hook
@ 2017-03-14  7:17   ` Stephan Müller
  2017-03-14 14:34     ` [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs Gary R Hook
  0 siblings, 1 reply; 7+ messages in thread
From: Stephan Müller @ 2017-03-14  7:17 UTC (permalink / raw)
  To: Gary R Hook; +Cc: linux-crypto

Am Montag, 13. März 2017, 20:35:07 CET schrieb Gary R Hook:

Hi Gary,

> On 03/03/2017 7:15 AM, Stephan Mueller wrote:
> > Am Donnerstag, 2. März 2017, 22:26:54 CET schrieb Gary R Hook:
> > 
> > Hi Gary,
> 
> Thanks for your comments, Stephan.
> 
> > > A version 5 device provides the primitive commands
> > > required for AES GCM. This patch adds support for
> > > en/decryption.
> > > 
> > > Signed-off-by: Gary R Hook <gary.hook@amd.com>
> > > ---
> > > 
> > >  drivers/crypto/ccp/Makefile                |    1
> > >  drivers/crypto/ccp/ccp-crypto-aes-galois.c |  257
> > > 
> > > ++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-main.c      
> > > |
> > > 12 +
> > > 
> > >  drivers/crypto/ccp/ccp-crypto.h            |   14 ++
> > >  drivers/crypto/ccp/ccp-dev-v5.c            |    2
> > >  drivers/crypto/ccp/ccp-dev.h               |    1
> > >  drivers/crypto/ccp/ccp-ops.c               |  252
> > > 
> > > +++++++++++++++++++++++++++ include/linux/ccp.h                        |
> > > 9 +
> > > 
> > >  8 files changed, 548 insertions(+)
> > >  create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c
> > > 
> > > diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> > > b/drivers/crypto/ccp/ccp-crypto-aes-galois.c new file mode 100644
> > > index 0000000..8bc18c9
> > > --- /dev/null
> > > +++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> > > @@ -0,0 +1,257 @@
> > > +/*
> > > + * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support
> > > + *
> > > + * Copyright (C) 2016 Advanced Micro Devices, Inc.
> > > + *
> > > + * Author: Gary R Hook <gary.hook@amd.com>
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify
> > > + * it under the terms of the GNU General Public License version 2 as
> > > + * published by the Free Software Foundation.
> > > + */
> > > +
> > > +#include <linux/module.h>
> > > +#include <linux/sched.h>
> > > +#include <linux/delay.h>
> > > +#include <linux/scatterlist.h>
> > > +#include <linux/crypto.h>
> > > +#include <crypto/internal/aead.h>
> > > +#include <crypto/algapi.h>
> > > +#include <crypto/aes.h>
> > > +#include <crypto/ctr.h>
> > > +#include <crypto/scatterwalk.h>
> > > +#include <linux/delay.h>
> > > +
> > > +#include "ccp-crypto.h"
> > > +
> > > +#define    AES_GCM_IVSIZE  12
> > > +
> > > +static int ccp_aes_gcm_complete(struct crypto_async_request *async_req,
> > > int ret) +{
> > > +   return ret;
> > > +}
> > > +
> > > +static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
> > > +                         unsigned int key_len)
> > > +{
> > > +   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> > > +
> > > +   switch (key_len) {
> > > +   case AES_KEYSIZE_128:
> > > +           ctx->u.aes.type = CCP_AES_TYPE_128;
> > > +           break;
> > > +   case AES_KEYSIZE_192:
> > > +           ctx->u.aes.type = CCP_AES_TYPE_192;
> > > +           break;
> > > +   case AES_KEYSIZE_256:
> > > +           ctx->u.aes.type = CCP_AES_TYPE_256;
> > > +           break;
> > > +   default:
> > > +           crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
> > > +           return -EINVAL;
> > > +   }
> > > +
> > > +   ctx->u.aes.mode = CCP_AES_MODE_GCM;
> > > +   ctx->u.aes.key_len = key_len;
> > > +
> > > +   memcpy(ctx->u.aes.key, key, key_len);
> > > +   sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
> > > +
> > > +   return 0;
> > > +}
> > > +
> > > +static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
> > > +                              unsigned int authsize)
> > > +{
> > > +   return 0;
> > > +}
> > > +
> > > +static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
> > > +{
> > > +   struct crypto_aead *tfm = crypto_aead_reqtfm(req);
> > > +   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> > > +   struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
> > > +   struct scatterlist *iv_sg = NULL;
> > > +   unsigned int iv_len = 0;
> > > +   int i;
> > > +   int ret = 0;
> > > +
> > > +   if (!ctx->u.aes.key_len)
> > > +           return -EINVAL;
> > > +
> > > +   if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
> > > +           return -EINVAL;
> > > +
> > > +   if (!req->iv)
> > > +           return -EINVAL;
> > > +
> > > +   /*
> > > +    * 5 parts:
> > > +    *   plaintext/ciphertext input
> > > +    *   AAD
> > > +    *   key
> > > +    *   IV
> > > +    *   Destination+tag buffer
> > > +    */
> > > +
> > > +   /* According to the way AES GCM has been implemented here,
> > > +    * per RFC 4106 it seems, the provided IV is fixed at 12 bytes,
> > 
> > When you have that restriction, should the cipher be called
> > rfc4106(gcm(aes))?
> > 
> > But then, the key is 4 bytes longer than a normal AES key as it contains
> > the leading 32 bits of the IV.
> 
> I had my wires crossed due to an incomplete understanding of an AEAD cipher
> in general, and GCM in particular. I'm hopeful that someone can help me
> understand:
> 
> For the AES GCM encryption tests in testmgr.h, where there is an IV,
> they're all
> 12 bytes in length. As I understand AES GCM the IV can be anywhere from
> 1 to 2^64
> bits in length; the value of 96 makes for convenience and efficiency.
> But it's
> neither a requirement nor restriction.

That is correct. For longer IVs, you would need to use Ghash to compress it to 
96 bits. The remaining 32 bits to get to one AES block is the counter that is 
used for the CTR AES mode in GCM.
> 
> There are no tests (in testmgr.h) that use an IV length other than  0 or 96.

See aes_gcm_rfc4106_enc_tv_template for other types of IV.

> My comment about RFC4106 has to do with requiring an IV 0f 96 bits + a word
> that
> is incremented for each block (making every nonce unique, per the
> requirement).
> But let's ignore that, please.
> 
> It looks as if:
> 
> What seems to be missing is the ability to register a (GCM) transform
> that can
> handle an IV of arbitrary (allowable) length. I have to specify the
> length (ivsize)
> when I register an algorithm, and everything I see in the existing code
> appears
> to expect a GCM ivsize to be 96 bits, period (or zero). This is what I
> meant when
> I referenced RFC4106: I perceive restrictions not in my code, but n the
> way GCM seems
> to be supported in the crypto AEAD framework. A complete GCM
> implementation would not
> seem to have a restriction to a specific IV length (rather, a range of
> allowed
> values).

96 bits is the use case in IPSEC. As the kernel crypto API transforms are used 
for IPSEC. Nobody would prevent you from supporting other IV sizes. But then 
you would need to add a Ghash operation to compress it to the right length. No 
other GCM implementation has that and hence the limitation.

But 96 bits is not the common case. See the 4106 implementations, you see the 
ivsize being 8. This is correct because setkey requires AES keysize + 4 bytes 
in length (see crypto_rfc4106_setkey for an example). The trailing 4 bytes of 
the key are the initial 4 bytes of the GCM IV.

My comment was about your comment to refer to RFC4106. I just wanted to 
understand your code and and make sense of your comments. :-)
> 
> Is my reading of the GCM description in error? Do we need/want the ability
> to have a flexible IV length for GCM? What am I not understanding?

In your case, just change the wording in the comment slightly and we are all 
good.
> 
> For reference, I'm working from the NIST doc:
> http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-s
> pec.pdf

> 
> > > +   rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
> > > +   rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
> > > +   rctx->cmd.u.aes.iv = iv_sg;
> > > +   rctx->cmd.u.aes.iv_len = iv_len;
> > > +   rctx->cmd.u.aes.src = req->src;
> > > +   rctx->cmd.u.aes.src_len = req->cryptlen;
> > > +   rctx->cmd.u.aes.aad_len = req->assoclen;
> > 
> > Just to be on the safe side: is the implementation good when cryptlen or
> > assoclen is 0?
> 
> The engine has been designed to handle those two conditions. I've been
> watching the discussions around these issues.
> 
> The first encryption test in testmgr.h has no input data nor IV. This
> implementation passes that test.
> 
> The second encryption test in testmgr.h has input data but no IV, and this
> implementation passes.
> 
> Is that an acceptable validation, or do we need more?

I would recommend at least a private test with no input and no AAD (i.e. 
authentication only).

Maybe you can add a patch to testmgr for this case. An example is found at 
[1]. Here, tag and exp is the expected result of the operation.

[1] https://github.com/smuellerDD/libkcapi/blob/master/test/test.sh#L330
> 
> Thanks,
> Gary



Ciao
Stephan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs
  2017-03-14  7:17   ` Stephan Müller
@ 2017-03-14 14:34     ` Gary R Hook
  2017-03-14 15:09       ` Stephan Müller
  0 siblings, 1 reply; 7+ messages in thread
From: Gary R Hook @ 2017-03-14 14:34 UTC (permalink / raw)
  To: Stephan Müller, Hook, Gary; +Cc: linux-crypto

On 03/14/2017 02:17 AM, Stephan Müller wrote:
> Am Montag, 13. März 2017, 20:35:07 CET schrieb Gary R Hook:
>
> Hi Gary,

Is it acceptable to snip stuff out? Most of this code seems irrelevant 
to this discussion....

>
>> On 03/03/2017 7:15 AM, Stephan Mueller wrote:
>> > Am Donnerstag, 2. März 2017, 22:26:54 CET schrieb Gary R Hook:
>> >
>> > Hi Gary,
>>
>> Thanks for your comments, Stephan.
>>
>> > > A version 5 device provides the primitive commands
>> > > required for AES GCM. This patch adds support for
>> > > en/decryption.
>> > >
>> > > Signed-off-by: Gary R Hook <gary.hook@amd.com>
>> > > ---
>> > >
>> > >  drivers/crypto/ccp/Makefile                |    1
>> > >  drivers/crypto/ccp/ccp-crypto-aes-galois.c |  257
>> > >
>> > > ++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-main.c
>> > > |
>> > > 12 +
>> > >
>> > >  drivers/crypto/ccp/ccp-crypto.h            |   14 ++
>> > >  drivers/crypto/ccp/ccp-dev-v5.c            |    2
>> > >  drivers/crypto/ccp/ccp-dev.h               |    1
>> > >  drivers/crypto/ccp/ccp-ops.c               |  252
>> > >
>> > > +++++++++++++++++++++++++++ include/linux/ccp.h                        |
>> > > 9 +
>> > >
>> > >  8 files changed, 548 insertions(+)
>> > >  create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c
>> > >
>> > > diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c
>> > > b/drivers/crypto/ccp/ccp-crypto-aes-galois.c new file mode 100644
>> > > index 0000000..8bc18c9
>> > > --- /dev/null
>> > > +++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
>> > > @@ -0,0 +1,257 @@
>> > > +/*
>> > > + * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support
>> > > + *
>> > > + * Copyright (C) 2016 Advanced Micro Devices, Inc.
>> > > + *
>> > > + * Author: Gary R Hook <gary.hook@amd.com>
>> > > + *
>> > > + * This program is free software; you can redistribute it and/or modify
>> > > + * it under the terms of the GNU General Public License version 2 as
>> > > + * published by the Free Software Foundation.
>> > > + */
>> > > +
>> > > +#include <linux/module.h>
>> > > +#include <linux/sched.h>
>> > > +#include <linux/delay.h>
>> > > +#include <linux/scatterlist.h>
>> > > +#include <linux/crypto.h>
>> > > +#include <crypto/internal/aead.h>
>> > > +#include <crypto/algapi.h>
>> > > +#include <crypto/aes.h>
>> > > +#include <crypto/ctr.h>
>> > > +#include <crypto/scatterwalk.h>
>> > > +#include <linux/delay.h>
>> > > +
>> > > +#include "ccp-crypto.h"
>> > > +
>> > > +#define    AES_GCM_IVSIZE  12
>> > > +
>> > > +static int ccp_aes_gcm_complete(struct crypto_async_request *async_req,
>> > > int ret) +{
>> > > +   return ret;
>> > > +}
>> > > +
>> > > +static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
>> > > +                         unsigned int key_len)
>> > > +{
>> > > +   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
>> > > +
>> > > +   switch (key_len) {
>> > > +   case AES_KEYSIZE_128:
>> > > +           ctx->u.aes.type = CCP_AES_TYPE_128;
>> > > +           break;
>> > > +   case AES_KEYSIZE_192:
>> > > +           ctx->u.aes.type = CCP_AES_TYPE_192;
>> > > +           break;
>> > > +   case AES_KEYSIZE_256:
>> > > +           ctx->u.aes.type = CCP_AES_TYPE_256;
>> > > +           break;
>> > > +   default:
>> > > +           crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
>> > > +           return -EINVAL;
>> > > +   }
>> > > +
>> > > +   ctx->u.aes.mode = CCP_AES_MODE_GCM;
>> > > +   ctx->u.aes.key_len = key_len;
>> > > +
>> > > +   memcpy(ctx->u.aes.key, key, key_len);
>> > > +   sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
>> > > +
>> > > +   return 0;
>> > > +}
>> > > +
>> > > +static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
>> > > +                              unsigned int authsize)
>> > > +{
>> > > +   return 0;
>> > > +}
>> > > +
>> > > +static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
>> > > +{
>> > > +   struct crypto_aead *tfm = crypto_aead_reqtfm(req);
>> > > +   struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
>> > > +   struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
>> > > +   struct scatterlist *iv_sg = NULL;
>> > > +   unsigned int iv_len = 0;
>> > > +   int i;
>> > > +   int ret = 0;
>> > > +
>> > > +   if (!ctx->u.aes.key_len)
>> > > +           return -EINVAL;
>> > > +
>> > > +   if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
>> > > +           return -EINVAL;
>> > > +
>> > > +   if (!req->iv)
>> > > +           return -EINVAL;
>> > > +
>> > > +   /*
>> > > +    * 5 parts:
>> > > +    *   plaintext/ciphertext input
>> > > +    *   AAD
>> > > +    *   key
>> > > +    *   IV
>> > > +    *   Destination+tag buffer
>> > > +    */
>> > > +
>> > > +   /* According to the way AES GCM has been implemented here,
>> > > +    * per RFC 4106 it seems, the provided IV is fixed at 12 bytes,
>> >
>> > When you have that restriction, should the cipher be called
>> > rfc4106(gcm(aes))?
>> >
>> > But then, the key is 4 bytes longer than a normal AES key as it contains
>> > the leading 32 bits of the IV.
>>
>> I had my wires crossed due to an incomplete understanding of an AEAD cipher
>> in general, and GCM in particular. I'm hopeful that someone can help me
>> understand:
>>
>> For the AES GCM encryption tests in testmgr.h, where there is an IV,
>> they're all
>> 12 bytes in length. As I understand AES GCM the IV can be anywhere from
>> 1 to 2^64
>> bits in length; the value of 96 makes for convenience and efficiency.
>> But it's
>> neither a requirement nor restriction.
>
> That is correct. For longer IVs, you would need to use Ghash to compress
> it to
> 96 bits. The remaining 32 bits to get to one AES block is the counter
> that is
> used for the CTR AES mode in GCM.

Yes, understood. It's all falling into place now. What seems to be missing
(to me) is a way for the transform to indicate that it allows all valid 
(GCM)
IV lengths, as opposed to the (specified in the data structure) 12 bytes. I
get the context of IPSec, but I would think AF_ALG allowing access to the
transforms means that we can't rely upon a context. And there seems to be no
way for an implementation to let a user know about any IV restrictions 
(or not).

Do we just let the implementation return an error when it can't handle 
something?

Or (highly possible) am I missing the obvious?


>> There are no tests (in testmgr.h) that use an IV length other than  0 or 96.
>
> See aes_gcm_rfc4106_enc_tv_template for other types of IV.

All 8 bytes, it seems, which makes sense for 4106.

>> My comment about RFC4106 has to do with requiring an IV 0f 96 bits + a word
>> that
>> is incremented for each block (making every nonce unique, per the
>> requirement).
>> But let's ignore that, please.
>>
>> It looks as if:
>>
>> What seems to be missing is the ability to register a (GCM) transform
>> that can
>> handle an IV of arbitrary (allowable) length. I have to specify the
>> length (ivsize)
>> when I register an algorithm, and everything I see in the existing code
>> appears
>> to expect a GCM ivsize to be 96 bits, period (or zero). This is what I
>> meant when
>> I referenced RFC4106: I perceive restrictions not in my code, but n the
>> way GCM seems
>> to be supported in the crypto AEAD framework. A complete GCM
>> implementation would not
>> seem to have a restriction to a specific IV length (rather, a range of
>> allowed
>> values).
>
> 96 bits is the use case in IPSEC. As the kernel crypto API transforms
> are used
> for IPSEC. Nobody would prevent you from supporting other IV sizes. But
> then
> you would need to add a Ghash operation to compress it to the right
> length. No
> other GCM implementation has that and hence the limitation.

Of course. That's the component that I'm missing, and I want to understand
whether there's a compelling need.

> But 96 bits is not the common case. See the 4106 implementations, you
> see the
> ivsize being 8. This is correct because setkey requires AES keysize + 4
> bytes
> in length (see crypto_rfc4106_setkey for an example). The trailing 4
> bytes of
> the key are the initial 4 bytes of the GCM IV.

Yes. The RFC4106 document is pretty clear on the layout of the IV.

> My comment was about your comment to refer to RFC4106. I just wanted to
> understand your code and and make sense of your comments. :-)
>>
>> Is my reading of the GCM description in error? Do we need/want the ability
>> to have a flexible IV length for GCM? What am I not understanding?
>
> In your case, just change the wording in the comment slightly and we are
> all good.

Will do. I appreciate the discussion! Very helpful.

>>
>> For reference, I'm working from the NIST doc:
>> http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-s
>> pec.pdf
>
>>
>> > > +   rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
>> > > +   rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
>> > > +   rctx->cmd.u.aes.iv = iv_sg;
>> > > +   rctx->cmd.u.aes.iv_len = iv_len;
>> > > +   rctx->cmd.u.aes.src = req->src;
>> > > +   rctx->cmd.u.aes.src_len = req->cryptlen;
>> > > +   rctx->cmd.u.aes.aad_len = req->assoclen;
>> >
>> > Just to be on the safe side: is the implementation good when cryptlen or
>> > assoclen is 0?
>>
>> The engine has been designed to handle those two conditions. I've been
>> watching the discussions around these issues.
>>
>> The first encryption test in testmgr.h has no input data nor IV. This
>> implementation passes that test.
>>
>> The second encryption test in testmgr.h has input data but no IV, and this
>> implementation passes.
>>
>> Is that an acceptable validation, or do we need more?
>
> I would recommend at least a private test with no input and no AAD (i.e.
> authentication only).
>
> Maybe you can add a patch to testmgr for this case. An example is found at
> [1]. Here, tag and exp is the expected result of the operation.
>
> [1] https://github.com/smuellerDD/libkcapi/blob/master/test/test.sh#L330
>>
>> Thanks,
>> Gary
>
>
>
> Ciao
> Stephan

-- 
This is my day job. Follow me at:
IG/Twitter/Facebook: @grhookphoto
IG/Twitter/Facebook: @grhphotographer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs
  2017-03-14 14:34     ` [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs Gary R Hook
@ 2017-03-14 15:09       ` Stephan Müller
  0 siblings, 0 replies; 7+ messages in thread
From: Stephan Müller @ 2017-03-14 15:09 UTC (permalink / raw)
  To: Gary R Hook; +Cc: Hook, Gary, linux-crypto

Am Dienstag, 14. März 2017, 15:34:00 CET schrieb Gary R Hook:

Hi Gary,

> On 03/14/2017 02:17 AM, Stephan Müller wrote:
> > Am Montag, 13. März 2017, 20:35:07 CET schrieb Gary R Hook:
> > 
> > Hi Gary,
> 
> Is it acceptable to snip stuff out? Most of this code seems irrelevant
> to this discussion....

Let us snip it :-)

> >> > 
> >> > But then, the key is 4 bytes longer than a normal AES key as it
> >> > contains
> >> > the leading 32 bits of the IV.
> >> 
> >> I had my wires crossed due to an incomplete understanding of an AEAD
> >> cipher
> >> in general, and GCM in particular. I'm hopeful that someone can help me
> >> understand:
> >> 
> >> For the AES GCM encryption tests in testmgr.h, where there is an IV,
> >> they're all
> >> 12 bytes in length. As I understand AES GCM the IV can be anywhere from
> >> 1 to 2^64
> >> bits in length; the value of 96 makes for convenience and efficiency.
> >> But it's
> >> neither a requirement nor restriction.
> > 
> > That is correct. For longer IVs, you would need to use Ghash to compress
> > it to
> > 96 bits. The remaining 32 bits to get to one AES block is the counter
> > that is
> > used for the CTR AES mode in GCM.
> 
> Yes, understood. It's all falling into place now. What seems to be missing
> (to me) is a way for the transform to indicate that it allows all valid
> (GCM)
> IV lengths, as opposed to the (specified in the data structure) 12 bytes.

The kernel crypto API does not support varying IV sizes. So, simply stay with 
12 / 8 bytes as explained should suffice.

> I
> get the context of IPSec, but I would think AF_ALG allowing access to the
> transforms means that we can't rely upon a context. And there seems to be no
> way for an implementation to let a user know about any IV restrictions (or
> not).

In algif_aead, we simply have:

        unsigned ivsize =
                crypto_aead_ivsize(crypto_aead_reqtfm(&ctx->aead_req));
...
                if (con.iv && con.iv->ivlen != ivsize)
                        return -EINVAL;

Thus, if the user space caller does not provide exactly ivsize bytes of IV, he 
gets an error.
> 
> Do we just let the implementation return an error when it can't handle
> something?
> 
> Or (highly possible) am I missing the obvious?
> 
> >> There are no tests (in testmgr.h) that use an IV length other than  0 or
> >> 96.> 
> > See aes_gcm_rfc4106_enc_tv_template for other types of IV.
> 
> All 8 bytes, it seems, which makes sense for 4106.
> 
> >> My comment about RFC4106 has to do with requiring an IV 0f 96 bits + a
> >> word
> >> that
> >> is incremented for each block (making every nonce unique, per the
> >> requirement).
> >> But let's ignore that, please.
> >> 
> >> It looks as if:
> >> 
> >> What seems to be missing is the ability to register a (GCM) transform
> >> that can
> >> handle an IV of arbitrary (allowable) length. I have to specify the
> >> length (ivsize)
> >> when I register an algorithm, and everything I see in the existing code
> >> appears
> >> to expect a GCM ivsize to be 96 bits, period (or zero). This is what I
> >> meant when
> >> I referenced RFC4106: I perceive restrictions not in my code, but n the
> >> way GCM seems
> >> to be supported in the crypto AEAD framework. A complete GCM
> >> implementation would not
> >> seem to have a restriction to a specific IV length (rather, a range of
> >> allowed
> >> values).
> > 
> > 96 bits is the use case in IPSEC. As the kernel crypto API transforms
> > are used
> > for IPSEC. Nobody would prevent you from supporting other IV sizes. But
> > then
> > you would need to add a Ghash operation to compress it to the right
> > length. No
> > other GCM implementation has that and hence the limitation.
> 
> Of course. That's the component that I'm missing, and I want to understand
> whether there's a compelling need.

I would not think that there is any need for it. If there would be, a generic 
helper for the IV compression should be added instead of having the algos 
implementing it itself over and over again.
> 
> > But 96 bits is not the common case. See the 4106 implementations, you
> > see the
> > ivsize being 8. This is correct because setkey requires AES keysize + 4
> > bytes
> > in length (see crypto_rfc4106_setkey for an example). The trailing 4
> > bytes of
> > the key are the initial 4 bytes of the GCM IV.
> 
> Yes. The RFC4106 document is pretty clear on the layout of the IV.
> 
> > My comment was about your comment to refer to RFC4106. I just wanted to
> > understand your code and and make sense of your comments. :-)
> > 
> >> Is my reading of the GCM description in error? Do we need/want the
> >> ability
> >> to have a flexible IV length for GCM? What am I not understanding?
> > 
> > In your case, just change the wording in the comment slightly and we are
> > all good.
> 
> Will do. I appreciate the discussion! Very helpful.
> 

Ciao
Stephan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs
  2017-03-02 21:26 ` [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs Gary R Hook
  2017-03-03  7:15   ` Stephan Müller
@ 2017-03-09 10:32   ` Herbert Xu
  1 sibling, 0 replies; 7+ messages in thread
From: Herbert Xu @ 2017-03-09 10:32 UTC (permalink / raw)
  To: Gary R Hook; +Cc: linux-crypto, thomas.lendacky, davem

On Thu, Mar 02, 2017 at 03:26:54PM -0600, Gary R Hook wrote:
> A version 5 device provides the primitive commands
> required for AES GCM. This patch adds support for
> en/decryption.
> 
> Signed-off-by: Gary R Hook <gary.hook@amd.com>

This patch doesn't apply to the current cryptodev tree.

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs
  2017-03-02 21:26 ` [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs Gary R Hook
@ 2017-03-03  7:15   ` Stephan Müller
  2017-03-09 10:32   ` Herbert Xu
  1 sibling, 0 replies; 7+ messages in thread
From: Stephan Müller @ 2017-03-03  7:15 UTC (permalink / raw)
  To: Gary R Hook; +Cc: linux-crypto, thomas.lendacky, herbert, davem

Am Donnerstag, 2. März 2017, 22:26:54 CET schrieb Gary R Hook:

Hi Gary,

> A version 5 device provides the primitive commands
> required for AES GCM. This patch adds support for
> en/decryption.
> 
> Signed-off-by: Gary R Hook <gary.hook@amd.com>
> ---
>  drivers/crypto/ccp/Makefile                |    1
>  drivers/crypto/ccp/ccp-crypto-aes-galois.c |  257
> ++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-main.c       |  
> 12 +
>  drivers/crypto/ccp/ccp-crypto.h            |   14 ++
>  drivers/crypto/ccp/ccp-dev-v5.c            |    2
>  drivers/crypto/ccp/ccp-dev.h               |    1
>  drivers/crypto/ccp/ccp-ops.c               |  252
> +++++++++++++++++++++++++++ include/linux/ccp.h                        |   
> 9 +
>  8 files changed, 548 insertions(+)
>  create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c
> 
> diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
> index 346ceb8..9ca1722 100644
> --- a/drivers/crypto/ccp/Makefile
> +++ b/drivers/crypto/ccp/Makefile
> @@ -12,4 +12,5 @@ ccp-crypto-objs := ccp-crypto-main.o \
>  		   ccp-crypto-aes.o \
>  		   ccp-crypto-aes-cmac.o \
>  		   ccp-crypto-aes-xts.o \
> +		   ccp-crypto-aes-galois.o \
>  		   ccp-crypto-sha.o
> diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> b/drivers/crypto/ccp/ccp-crypto-aes-galois.c new file mode 100644
> index 0000000..8bc18c9
> --- /dev/null
> +++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
> @@ -0,0 +1,257 @@
> +/*
> + * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support
> + *
> + * Copyright (C) 2016 Advanced Micro Devices, Inc.
> + *
> + * Author: Gary R Hook <gary.hook@amd.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/scatterlist.h>
> +#include <linux/crypto.h>
> +#include <crypto/internal/aead.h>
> +#include <crypto/algapi.h>
> +#include <crypto/aes.h>
> +#include <crypto/ctr.h>
> +#include <crypto/scatterwalk.h>
> +#include <linux/delay.h>
> +
> +#include "ccp-crypto.h"
> +
> +#define	AES_GCM_IVSIZE	12
> +
> +static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int
> ret) +{
> +	return ret;
> +}
> +
> +static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
> +			      unsigned int key_len)
> +{
> +	struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> +
> +	switch (key_len) {
> +	case AES_KEYSIZE_128:
> +		ctx->u.aes.type = CCP_AES_TYPE_128;
> +		break;
> +	case AES_KEYSIZE_192:
> +		ctx->u.aes.type = CCP_AES_TYPE_192;
> +		break;
> +	case AES_KEYSIZE_256:
> +		ctx->u.aes.type = CCP_AES_TYPE_256;
> +		break;
> +	default:
> +		crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
> +		return -EINVAL;
> +	}
> +
> +	ctx->u.aes.mode = CCP_AES_MODE_GCM;
> +	ctx->u.aes.key_len = key_len;
> +
> +	memcpy(ctx->u.aes.key, key, key_len);
> +	sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
> +
> +	return 0;
> +}
> +
> +static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
> +				   unsigned int authsize)
> +{
> +	return 0;
> +}
> +
> +static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
> +{
> +	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
> +	struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
> +	struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
> +	struct scatterlist *iv_sg = NULL;
> +	unsigned int iv_len = 0;
> +	int i;
> +	int ret = 0;
> +
> +	if (!ctx->u.aes.key_len)
> +		return -EINVAL;
> +
> +	if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
> +		return -EINVAL;
> +
> +	if (!req->iv)
> +		return -EINVAL;
> +
> +	/*
> +	 * 5 parts:
> +	 *   plaintext/ciphertext input
> +	 *   AAD
> +	 *   key
> +	 *   IV
> +	 *   Destination+tag buffer
> +	 */
> +
> +	/* According to the way AES GCM has been implemented here,
> +	 * per RFC 4106 it seems, the provided IV is fixed at 12 bytes,

When you have that restriction, should the cipher be called rfc4106(gcm(aes))?

But then, the key is 4 bytes longer than a normal AES key as it contains the 
leading 32 bits of the IV.

> +	 * occupies the beginning of the IV array. Write a 32-bit
> +	 * integer after that (bytes 13-16) with a value of "1".
> +	 */
> +	memcpy(rctx->iv, req->iv, AES_GCM_IVSIZE);
> +	for (i = 0; i < 3; i++)
> +		rctx->iv[i + AES_GCM_IVSIZE] = 0;
> +	rctx->iv[AES_BLOCK_SIZE - 1] = 1;
> +
> +	/* Set up a scatterlist for the IV */
> +	iv_sg = &rctx->iv_sg;
> +	iv_len = AES_BLOCK_SIZE;
> +	sg_init_one(iv_sg, rctx->iv, iv_len);
> +
> +	/* The AAD + plaintext are concatenated in the src buffer */
> +	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
> +	INIT_LIST_HEAD(&rctx->cmd.entry);
> +	rctx->cmd.engine = CCP_ENGINE_AES;
> +	rctx->cmd.u.aes.type = ctx->u.aes.type;
> +	rctx->cmd.u.aes.mode = ctx->u.aes.mode;
> +	rctx->cmd.u.aes.action =
> +		(encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT;

Instead of this condition, why not changing the encrypt/decrypt function to 
directly provide the enc/dec variables?

> +	rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
> +	rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
> +	rctx->cmd.u.aes.iv = iv_sg;
> +	rctx->cmd.u.aes.iv_len = iv_len;
> +	rctx->cmd.u.aes.src = req->src;
> +	rctx->cmd.u.aes.src_len = req->cryptlen;
> +	rctx->cmd.u.aes.aad_len = req->assoclen;

Just to be on the safe side: is the implementation good when cryptlen or 
assoclen is 0?

Ciao
Stephan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs
  2017-03-02 21:26 [PATCH V2 0/3] Series short description Gary R Hook
@ 2017-03-02 21:26 ` Gary R Hook
  2017-03-03  7:15   ` Stephan Müller
  2017-03-09 10:32   ` Herbert Xu
  0 siblings, 2 replies; 7+ messages in thread
From: Gary R Hook @ 2017-03-02 21:26 UTC (permalink / raw)
  To: linux-crypto; +Cc: thomas.lendacky, gary.hook, herbert, davem

A version 5 device provides the primitive commands
required for AES GCM. This patch adds support for
en/decryption.

Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/crypto/ccp/Makefile                |    1 
 drivers/crypto/ccp/ccp-crypto-aes-galois.c |  257 ++++++++++++++++++++++++++++
 drivers/crypto/ccp/ccp-crypto-main.c       |   12 +
 drivers/crypto/ccp/ccp-crypto.h            |   14 ++
 drivers/crypto/ccp/ccp-dev-v5.c            |    2 
 drivers/crypto/ccp/ccp-dev.h               |    1 
 drivers/crypto/ccp/ccp-ops.c               |  252 +++++++++++++++++++++++++++
 include/linux/ccp.h                        |    9 +
 8 files changed, 548 insertions(+)
 create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.c

diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index 346ceb8..9ca1722 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -12,4 +12,5 @@ ccp-crypto-objs := ccp-crypto-main.o \
 		   ccp-crypto-aes.o \
 		   ccp-crypto-aes-cmac.o \
 		   ccp-crypto-aes-xts.o \
+		   ccp-crypto-aes-galois.o \
 		   ccp-crypto-sha.o
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
new file mode 100644
index 0000000..8bc18c9
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c
@@ -0,0 +1,257 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES GCM crypto API support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook <gary.hook@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/internal/aead.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/ctr.h>
+#include <crypto/scatterwalk.h>
+#include <linux/delay.h>
+
+#include "ccp-crypto.h"
+
+#define	AES_GCM_IVSIZE	12
+
+static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int ret)
+{
+	return ret;
+}
+
+static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
+			      unsigned int key_len)
+{
+	struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		ctx->u.aes.type = CCP_AES_TYPE_128;
+		break;
+	case AES_KEYSIZE_192:
+		ctx->u.aes.type = CCP_AES_TYPE_192;
+		break;
+	case AES_KEYSIZE_256:
+		ctx->u.aes.type = CCP_AES_TYPE_256;
+		break;
+	default:
+		crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	ctx->u.aes.mode = CCP_AES_MODE_GCM;
+	ctx->u.aes.key_len = key_len;
+
+	memcpy(ctx->u.aes.key, key, key_len);
+	sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
+
+	return 0;
+}
+
+static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
+				   unsigned int authsize)
+{
+	return 0;
+}
+
+static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
+	struct ccp_aes_req_ctx *rctx = aead_request_ctx(req);
+	struct scatterlist *iv_sg = NULL;
+	unsigned int iv_len = 0;
+	int i;
+	int ret = 0;
+
+	if (!ctx->u.aes.key_len)
+		return -EINVAL;
+
+	if (ctx->u.aes.mode != CCP_AES_MODE_GCM)
+		return -EINVAL;
+
+	if (!req->iv)
+		return -EINVAL;
+
+	/*
+	 * 5 parts:
+	 *   plaintext/ciphertext input
+	 *   AAD
+	 *   key
+	 *   IV
+	 *   Destination+tag buffer
+	 */
+
+	/* According to the way AES GCM has been implemented here,
+	 * per RFC 4106 it seems, the provided IV is fixed at 12 bytes,
+	 * occupies the beginning of the IV array. Write a 32-bit
+	 * integer after that (bytes 13-16) with a value of "1".
+	 */
+	memcpy(rctx->iv, req->iv, AES_GCM_IVSIZE);
+	for (i = 0; i < 3; i++)
+		rctx->iv[i + AES_GCM_IVSIZE] = 0;
+	rctx->iv[AES_BLOCK_SIZE - 1] = 1;
+
+	/* Set up a scatterlist for the IV */
+	iv_sg = &rctx->iv_sg;
+	iv_len = AES_BLOCK_SIZE;
+	sg_init_one(iv_sg, rctx->iv, iv_len);
+
+	/* The AAD + plaintext are concatenated in the src buffer */
+	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+	INIT_LIST_HEAD(&rctx->cmd.entry);
+	rctx->cmd.engine = CCP_ENGINE_AES;
+	rctx->cmd.u.aes.type = ctx->u.aes.type;
+	rctx->cmd.u.aes.mode = ctx->u.aes.mode;
+	rctx->cmd.u.aes.action =
+		(encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT;
+	rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
+	rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
+	rctx->cmd.u.aes.iv = iv_sg;
+	rctx->cmd.u.aes.iv_len = iv_len;
+	rctx->cmd.u.aes.src = req->src;
+	rctx->cmd.u.aes.src_len = req->cryptlen;
+	rctx->cmd.u.aes.aad_len = req->assoclen;
+
+	/* The cipher text + the tag are in the dst buffer */
+	rctx->cmd.u.aes.dst = req->dst;
+
+	ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+	return ret;
+}
+
+static int ccp_aes_gcm_encrypt(struct aead_request *req)
+{
+	return ccp_aes_gcm_crypt(req, true);
+}
+
+static int ccp_aes_gcm_decrypt(struct aead_request *req)
+{
+	return ccp_aes_gcm_crypt(req, false);
+}
+
+static int ccp_aes_gcm_cra_init(struct crypto_aead *tfm)
+{
+	struct ccp_ctx *ctx = crypto_aead_ctx(tfm);
+
+	ctx->complete = ccp_aes_gcm_complete;
+	ctx->u.aes.key_len = 0;
+
+	crypto_aead_set_reqsize(tfm, sizeof(struct ccp_aes_req_ctx));
+
+	return 0;
+}
+
+static void ccp_aes_gcm_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static struct aead_alg ccp_aes_gcm_defaults = {
+	.setkey = ccp_aes_gcm_setkey,
+	.setauthsize = ccp_aes_gcm_setauthsize,
+	.encrypt = ccp_aes_gcm_encrypt,
+	.decrypt = ccp_aes_gcm_decrypt,
+	.init = ccp_aes_gcm_cra_init,
+	.ivsize = AES_GCM_IVSIZE,
+	.maxauthsize = AES_BLOCK_SIZE,
+	.base = {
+		.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_ASYNC |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize	= AES_BLOCK_SIZE,
+		.cra_ctxsize	= sizeof(struct ccp_ctx),
+		.cra_priority	= CCP_CRA_PRIORITY,
+		.cra_type	= &crypto_ablkcipher_type,
+		.cra_exit	= ccp_aes_gcm_cra_exit,
+		.cra_module	= THIS_MODULE,
+	},
+};
+
+struct ccp_aes_aead_def {
+	enum ccp_aes_mode mode;
+	unsigned int version;
+	const char *name;
+	const char *driver_name;
+	unsigned int blocksize;
+	unsigned int ivsize;
+	struct aead_alg *alg_defaults;
+};
+
+static struct ccp_aes_aead_def aes_aead_algs[] = {
+	{
+		.mode		= CCP_AES_MODE_GHASH,
+		.version	= CCP_VERSION(5, 0),
+		.name		= "gcm(aes)",
+		.driver_name	= "gcm-aes-ccp",
+		.blocksize	= 1,
+		.ivsize		= AES_BLOCK_SIZE,
+		.alg_defaults	= &ccp_aes_gcm_defaults,
+	},
+};
+
+static int ccp_register_aes_aead(struct list_head *head,
+				 const struct ccp_aes_aead_def *def)
+{
+	struct ccp_crypto_aead *ccp_aead;
+	struct aead_alg *alg;
+	int ret;
+
+	ccp_aead = kzalloc(sizeof(*ccp_aead), GFP_KERNEL);
+	if (!ccp_aead)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&ccp_aead->entry);
+
+	ccp_aead->mode = def->mode;
+
+	/* Copy the defaults and override as necessary */
+	alg = &ccp_aead->alg;
+	*alg = *def->alg_defaults;
+	snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+	snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		 def->driver_name);
+	alg->base.cra_blocksize = def->blocksize;
+	alg->base.cra_ablkcipher.ivsize = def->ivsize;
+
+	ret = crypto_register_aead(alg);
+	if (ret) {
+		pr_err("%s ablkcipher algorithm registration error (%d)\n",
+		       alg->base.cra_name, ret);
+		kfree(ccp_aead);
+		return ret;
+	}
+
+	list_add(&ccp_aead->entry, head);
+
+	return 0;
+}
+
+int ccp_register_aes_aeads(struct list_head *head)
+{
+	int i, ret;
+	unsigned int ccpversion = ccp_version();
+
+	for (i = 0; i < ARRAY_SIZE(aes_aead_algs); i++) {
+		if (aes_aead_algs[i].version > ccpversion)
+			continue;
+		ret = ccp_register_aes_aead(head, &aes_aead_algs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c
index e0380e5..a33b8d6 100644
--- a/drivers/crypto/ccp/ccp-crypto-main.c
+++ b/drivers/crypto/ccp/ccp-crypto-main.c
@@ -36,6 +36,7 @@
 /* List heads for the supported algorithms */
 static LIST_HEAD(hash_algs);
 static LIST_HEAD(cipher_algs);
+static LIST_HEAD(aead_algs);
 
 /* For any tfm, requests for that tfm must be returned on the order
  * received.  With multiple queues available, the CCP can process more
@@ -335,6 +336,10 @@ static int ccp_register_algs(void)
 		ret = ccp_register_aes_xts_algs(&cipher_algs);
 		if (ret)
 			return ret;
+
+		ret = ccp_register_aes_aeads(&aead_algs);
+		if (ret)
+			return ret;
 	}
 
 	if (!sha_disable) {
@@ -350,6 +355,7 @@ static void ccp_unregister_algs(void)
 {
 	struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp;
 	struct ccp_crypto_ablkcipher_alg *ablk_alg, *ablk_tmp;
+	struct ccp_crypto_aead *aead_alg, *aead_tmp;
 
 	list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) {
 		crypto_unregister_ahash(&ahash_alg->alg);
@@ -362,6 +368,12 @@ static void ccp_unregister_algs(void)
 		list_del(&ablk_alg->entry);
 		kfree(ablk_alg);
 	}
+
+	list_for_each_entry_safe(aead_alg, aead_tmp, &aead_algs, entry) {
+		crypto_unregister_aead(&aead_alg->alg);
+		list_del(&aead_alg->entry);
+		kfree(aead_alg);
+	}
 }
 
 static int ccp_crypto_init(void)
diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h
index 95cce27..34da62d 100644
--- a/drivers/crypto/ccp/ccp-crypto.h
+++ b/drivers/crypto/ccp/ccp-crypto.h
@@ -19,6 +19,8 @@
 #include <linux/ccp.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/internal/aead.h>
+#include <crypto/aead.h>
 #include <crypto/ctr.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
@@ -33,6 +35,14 @@ struct ccp_crypto_ablkcipher_alg {
 	struct crypto_alg alg;
 };
 
+struct ccp_crypto_aead {
+	struct list_head entry;
+
+	u32 mode;
+
+	struct aead_alg alg;
+};
+
 struct ccp_crypto_ahash_alg {
 	struct list_head entry;
 
@@ -95,6 +105,9 @@ struct ccp_aes_req_ctx {
 	struct scatterlist iv_sg;
 	u8 iv[AES_BLOCK_SIZE];
 
+	struct scatterlist tag_sg;
+	u8 tag[AES_BLOCK_SIZE];
+
 	/* Fields used for RFC3686 requests */
 	u8 *rfc3686_info;
 	u8 rfc3686_iv[AES_BLOCK_SIZE];
@@ -212,6 +225,7 @@ struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table,
 int ccp_register_aes_algs(struct list_head *head);
 int ccp_register_aes_cmac_algs(struct list_head *head);
 int ccp_register_aes_xts_algs(struct list_head *head);
+int ccp_register_aes_aeads(struct list_head *head);
 int ccp_register_sha_algs(struct list_head *head);
 
 #endif
diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
index d9e1876..d44a738 100644
--- a/drivers/crypto/ccp/ccp-dev-v5.c
+++ b/drivers/crypto/ccp/ccp-dev-v5.c
@@ -289,6 +289,8 @@ static int ccp5_perform_aes(struct ccp_op *op)
 	CCP_AES_TYPE(&function) = op->u.aes.type;
 	if (op->u.aes.mode == CCP_AES_MODE_CFB)
 		CCP_AES_SIZE(&function) = 0x7f;
+	if ((op->u.aes.mode == CCP_AES_MODE_GCTR) && op->eom)
+		CCP_AES_SIZE(&function) = op->u.aes.size;
 
 	CCP5_CMD_FUNCTION(&desc) = function.raw;
 
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index 830f35e..8f313e6 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -466,6 +466,7 @@ struct ccp_aes_op {
 	enum ccp_aes_type type;
 	enum ccp_aes_mode mode;
 	enum ccp_aes_action action;
+	unsigned int size;
 };
 
 struct ccp_xts_aes_op {
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index 213a752..83c8cf7 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -600,6 +600,255 @@ static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q,
 	return ret;
 }
 
+static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
+			       struct ccp_cmd *cmd)
+{
+	struct ccp_aes_engine *aes = &cmd->u.aes;
+	struct ccp_dm_workarea key, ctx, final_wa, tag;
+	struct ccp_data src, dst;
+	struct ccp_data aad;
+	struct ccp_op op;
+
+	unsigned long long *final;
+	unsigned int dm_offset;
+	unsigned int ilen;
+	bool in_place = true; /* Default value */
+	int ret;
+
+	struct scatterlist *p_inp, sg_inp[2];
+	struct scatterlist *p_tag, sg_tag[2];
+	struct scatterlist *p_outp, sg_outp[2];
+	struct scatterlist *p_aad;
+
+	if (!aes->iv)
+		return -EINVAL;
+
+	if (!((aes->key_len == AES_KEYSIZE_128) ||
+		(aes->key_len == AES_KEYSIZE_192) ||
+		(aes->key_len == AES_KEYSIZE_256)))
+		return -EINVAL;
+
+	if (!aes->key) /* Gotta have a key SGL */
+		return -EINVAL;
+
+	/* First, decompose the source buffer into AAD & PT,
+	 * and the destination buffer into AAD, CT & tag, or
+	 * the input into CT & tag.
+	 * It is expected that the input and output SGs will
+	 * be valid, even if the AAD and input lengths are 0.
+	 */
+	p_aad = aes->src;
+	p_inp = scatterwalk_ffwd(sg_inp, aes->src, aes->aad_len);
+	p_outp = scatterwalk_ffwd(sg_outp, aes->dst, aes->aad_len);
+	if (aes->action == CCP_AES_ACTION_ENCRYPT) {
+		ilen = aes->src_len;
+		p_tag = scatterwalk_ffwd(sg_tag, p_outp, ilen);
+	} else {
+		/* Input length for decryption includes tag */
+		ilen = aes->src_len - AES_BLOCK_SIZE;
+		p_tag = scatterwalk_ffwd(sg_tag, p_inp, ilen);
+	}
+
+	memset(&op, 0, sizeof(op));
+	op.cmd_q = cmd_q;
+	op.jobid = CCP_NEW_JOBID(cmd_q->ccp);
+	op.sb_key = cmd_q->sb_key; /* Pre-allocated */
+	op.sb_ctx = cmd_q->sb_ctx; /* Pre-allocated */
+	op.init = 1;
+	op.u.aes.type = aes->type;
+
+	/* Copy the key to the LSB */
+	ret = ccp_init_dm_workarea(&key, cmd_q,
+				   CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES,
+				   DMA_TO_DEVICE);
+	if (ret)
+		return ret;
+
+	dm_offset = CCP_SB_BYTES - aes->key_len;
+	ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len);
+	ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key,
+			     CCP_PASSTHRU_BYTESWAP_256BIT);
+	if (ret) {
+		cmd->engine_error = cmd_q->cmd_error;
+		goto e_key;
+	}
+
+	/* Copy the context (IV) to the LSB.
+	 * There is an assumption here that the IV is 96 bits in length, plus
+	 * a nonce of 32 bits. If no IV is present, use a zeroed buffer.
+	 */
+	ret = ccp_init_dm_workarea(&ctx, cmd_q,
+				   CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES,
+				   DMA_BIDIRECTIONAL);
+	if (ret)
+		goto e_key;
+
+	dm_offset = CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES - aes->iv_len;
+	ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len);
+
+	ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx,
+			     CCP_PASSTHRU_BYTESWAP_256BIT);
+	if (ret) {
+		cmd->engine_error = cmd_q->cmd_error;
+		goto e_ctx;
+	}
+
+	op.init = 1;
+	if (aes->aad_len > 0) {
+		/* Step 1: Run a GHASH over the Additional Authenticated Data */
+		ret = ccp_init_data(&aad, cmd_q, p_aad, aes->aad_len,
+				    AES_BLOCK_SIZE,
+				    DMA_TO_DEVICE);
+		if (ret)
+			goto e_ctx;
+
+		op.u.aes.mode = CCP_AES_MODE_GHASH;
+		op.u.aes.action = CCP_AES_GHASHAAD;
+
+		while (aad.sg_wa.bytes_left) {
+			ccp_prepare_data(&aad, NULL, &op, AES_BLOCK_SIZE, true);
+
+			ret = cmd_q->ccp->vdata->perform->aes(&op);
+			if (ret) {
+				cmd->engine_error = cmd_q->cmd_error;
+				goto e_aad;
+			}
+
+			ccp_process_data(&aad, NULL, &op);
+			op.init = 0;
+		}
+	}
+
+	op.u.aes.mode = CCP_AES_MODE_GCTR;
+	op.u.aes.action = aes->action;
+
+	if (ilen > 0) {
+		/* Step 2: Run a GCTR over the plaintext */
+		in_place = (sg_virt(p_inp) == sg_virt(p_outp)) ? true : false;
+
+		ret = ccp_init_data(&src, cmd_q, p_inp, ilen,
+				    AES_BLOCK_SIZE,
+				    in_place ? DMA_BIDIRECTIONAL
+					     : DMA_TO_DEVICE);
+		if (ret)
+			goto e_ctx;
+
+		if (in_place) {
+			dst = src;
+		} else {
+			ret = ccp_init_data(&dst, cmd_q, p_outp, ilen,
+					    AES_BLOCK_SIZE, DMA_FROM_DEVICE);
+			if (ret)
+				goto e_src;
+		}
+
+		op.soc = 0;
+		op.eom = 0;
+		op.init = 1;
+		while (src.sg_wa.bytes_left) {
+			ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true);
+			if (!src.sg_wa.bytes_left) {
+				unsigned int nbytes = aes->src_len
+						      % AES_BLOCK_SIZE;
+
+				if (nbytes) {
+					op.eom = 1;
+					op.u.aes.size = (nbytes * 8) - 1;
+				}
+			}
+
+			ret = cmd_q->ccp->vdata->perform->aes(&op);
+			if (ret) {
+				cmd->engine_error = cmd_q->cmd_error;
+				goto e_dst;
+			}
+
+			ccp_process_data(&src, &dst, &op);
+			op.init = 0;
+		}
+	}
+
+	/* Step 3: Update the IV portion of the context with the original IV */
+	ret = ccp_copy_from_sb(cmd_q, &ctx, op.jobid, op.sb_ctx,
+			       CCP_PASSTHRU_BYTESWAP_256BIT);
+	if (ret) {
+		cmd->engine_error = cmd_q->cmd_error;
+		goto e_dst;
+	}
+
+	ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len);
+
+	ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx,
+			     CCP_PASSTHRU_BYTESWAP_256BIT);
+	if (ret) {
+		cmd->engine_error = cmd_q->cmd_error;
+		goto e_dst;
+	}
+
+	/* Step 4: Concatenate the lengths of the AAD and source, and
+	 * hash that 16 byte buffer.
+	 */
+	ret = ccp_init_dm_workarea(&final_wa, cmd_q, AES_BLOCK_SIZE,
+				   DMA_BIDIRECTIONAL);
+	if (ret)
+		goto e_dst;
+	final = (unsigned long long *) final_wa.address;
+	final[0] = cpu_to_be64(aes->aad_len * 8);
+	final[1] = cpu_to_be64(ilen * 8);
+
+	op.u.aes.mode = CCP_AES_MODE_GHASH;
+	op.u.aes.action = CCP_AES_GHASHFINAL;
+	op.src.type = CCP_MEMTYPE_SYSTEM;
+	op.src.u.dma.address = final_wa.dma.address;
+	op.src.u.dma.length = AES_BLOCK_SIZE;
+	op.dst.type = CCP_MEMTYPE_SYSTEM;
+	op.dst.u.dma.address = final_wa.dma.address;
+	op.dst.u.dma.length = AES_BLOCK_SIZE;
+	op.eom = 1;
+	op.u.aes.size = 0;
+	ret = cmd_q->ccp->vdata->perform->aes(&op);
+	if (ret)
+		goto e_dst;
+
+	if (aes->action == CCP_AES_ACTION_ENCRYPT) {
+		/* Put the ciphered tag after the ciphertext. */
+		ccp_get_dm_area(&final_wa, 0, p_tag, 0, AES_BLOCK_SIZE);
+	} else {
+		/* Does this ciphered tag match the input? */
+		ret = ccp_init_dm_workarea(&tag, cmd_q, AES_BLOCK_SIZE,
+					   DMA_BIDIRECTIONAL);
+		if (ret)
+			goto e_tag;
+		ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE);
+
+		ret = memcmp(tag.address, final_wa.address, AES_BLOCK_SIZE);
+		ccp_dm_free(&tag);
+	}
+
+e_tag:
+	ccp_dm_free(&final_wa);
+
+e_dst:
+	if (aes->src_len && !in_place)
+		ccp_free_data(&dst, cmd_q);
+
+e_src:
+	if (aes->src_len)
+		ccp_free_data(&src, cmd_q);
+
+e_aad:
+	if (aes->aad_len)
+		ccp_free_data(&aad, cmd_q);
+
+e_ctx:
+	ccp_dm_free(&ctx);
+
+e_key:
+	ccp_dm_free(&key);
+
+	return ret;
+}
+
 static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
 {
 	struct ccp_aes_engine *aes = &cmd->u.aes;
@@ -613,6 +862,9 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
 	if (aes->mode == CCP_AES_MODE_CMAC)
 		return ccp_run_aes_cmac_cmd(cmd_q, cmd);
 
+	if (aes->mode == CCP_AES_MODE_GCM)
+		return ccp_run_aes_gcm_cmd(cmd_q, cmd);
+
 	if (!((aes->key_len == AES_KEYSIZE_128) ||
 	      (aes->key_len == AES_KEYSIZE_192) ||
 	      (aes->key_len == AES_KEYSIZE_256)))
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
index 90a1fbe..6f78295 100644
--- a/include/linux/ccp.h
+++ b/include/linux/ccp.h
@@ -123,6 +123,10 @@ enum ccp_aes_mode {
 	CCP_AES_MODE_CFB,
 	CCP_AES_MODE_CTR,
 	CCP_AES_MODE_CMAC,
+	CCP_AES_MODE_GHASH,
+	CCP_AES_MODE_GCTR,
+	CCP_AES_MODE_GCM,
+	CCP_AES_MODE_GMAC,
 	CCP_AES_MODE__LAST,
 };
 
@@ -137,6 +141,9 @@ enum ccp_aes_action {
 	CCP_AES_ACTION_ENCRYPT,
 	CCP_AES_ACTION__LAST,
 };
+/* Overloaded field */
+#define	CCP_AES_GHASHAAD	CCP_AES_ACTION_DECRYPT
+#define	CCP_AES_GHASHFINAL	CCP_AES_ACTION_ENCRYPT
 
 /**
  * struct ccp_aes_engine - CCP AES operation
@@ -181,6 +188,8 @@ struct ccp_aes_engine {
 	struct scatterlist *cmac_key;	/* K1/K2 cmac key required for
 					 * final cmac cmd */
 	u32 cmac_key_len;	/* In bytes */
+
+	u32 aad_len;		/* In bytes */
 };
 
 /***** XTS-AES engine *****/

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-03-14 15:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20170310180341.21062.82465.stgit@taos>
2017-03-13 19:35 ` [PATCH] crypto: ccp - Assign DMA commands to the channel's CCP Gary R Hook
2017-03-14  7:17   ` Stephan Müller
2017-03-14 14:34     ` [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs Gary R Hook
2017-03-14 15:09       ` Stephan Müller
2017-03-02 21:26 [PATCH V2 0/3] Series short description Gary R Hook
2017-03-02 21:26 ` [PATCH V2 2/3] crypto: ccp - Enable support for AES GCM on v5 CCPs Gary R Hook
2017-03-03  7:15   ` Stephan Müller
2017-03-09 10:32   ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).