Re: [PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-11 Thread Herbert Xu
On Fri, Jul 10, 2015 at 07:39:35PM +0530, Lokesh Vutla wrote:

 If you don't mind can you elaborate more on the usage of rctx and ctx
 in the driver?

The ctx is a property of the tfm and it's shared by all users
of that tfm.  So it must not be written to unless you use locking.

The reqeust context on the other hand is specific to a request
so it can be used to store information.

Cheers,
-- 
Email: Herbert Xu herb...@gondor.apana.org.au
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-10 Thread Lokesh Vutla
Hi Herbert,
On Wednesday 08 July 2015 09:48 AM, Herbert Xu wrote:
 On Tue, Jul 07, 2015 at 09:01:48PM +0530, Lokesh Vutla wrote:

 +static int omap_aes_gcm_copy_buffers(struct omap_aes_dev *dd,
 + struct aead_request *req)

[..snip..]

 +static int do_encrypt_iv(struct aead_request *req, u32 *tag)
 +{
 +struct scatterlist iv_sg;
 +struct ablkcipher_request *ablk_req;
 +struct crypto_ablkcipher *tfm;
 +struct tcrypt_result result;
 +struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
 +int ret = 0;
 +
 +tfm = crypto_alloc_ablkcipher(ctr(aes), 0, 0);
 
 Ugh, you cannot allocate crypto transforms in the data path.  You
 should allocate it in init instead.  Also using ctr(aes) is overkill.
 Just use aes and do the xor by hand.
 
 +static int omap_aes_gcm_crypt(struct aead_request *req, unsigned long mode)
 +{
 +struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
 +struct omap_aes_reqctx *rctx = aead_request_ctx(req);
 +struct crypto_aead *aead = crypto_aead_reqtfm(req);
 +unsigned int authlen = crypto_aead_authsize(aead);
 +struct omap_aes_dev *dd;
 +__be32 counter = cpu_to_be32(1);
 +int err;
 +
 +memset(ctx-auth_tag, 0, sizeof(ctx-auth_tag));
 
 The ctx is shared memory and you must not write to it as multiple
 requests can be called on the same tfm.  Use rctx instead.

May be a dumb question. 
If you don't mind can you elaborate more on the usage of rctx and ctx
in the driver?

Thanks and regards,
Lokesh
 
 +memcpy(req-iv + 12, counter, 4);
 
 The IV is only 12 bytes long so you're corrupting memory here.
 You should use rctx here too.
 
 +if (req-assoclen + req-cryptlen == 0) {
 +scatterwalk_map_and_copy(ctx-auth_tag, req-dst, 0, authlen,
 + 1);
 +return 0;
 +}
 
 How can this be right? Did you enable the selftest?
 
 Cheers,
 

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-08 Thread Lokesh Vutla
On Wednesday 08 July 2015 01:23 PM, Herbert Xu wrote:
 On Wed, Jul 08, 2015 at 03:48:05PM +0800, Herbert Xu wrote:
 On Wed, Jul 08, 2015 at 12:29:47PM +0530, Lokesh Vutla wrote:

 + if (req-assoclen + req-cryptlen == 0) {
 + scatterwalk_map_and_copy(ctx-auth_tag, req-dst, 0, authlen,
 +  1);
 + return 0;
 + }

 How can this be right? Did you enable the selftest?
 Why not? Self tests are passed for this case.

 As per the equation given in GCM spec[1], we can see that
 if assoclen and cryptlen is 0, then output of GCM  is just E(K, Y0)
 where Y0 = IV||(0^31)1
 I have E(K, Y0) calculated in previous step. And copying it
 to destination if assoclen and cryptlen is 0.

 Correct me if I am wrong.

 It should be E(K, Y0) ^ GHASH(0).  So unless GHASH(0) == 0, your
 code doesn't work.
 
 OK, GHASH(0) is indeed zero so I guess your code does work after
 all.
Sorry. I did not see this message and replied on the other thread.

Thanks and regards,
Lokesh
 
 Cheers,
 

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-08 Thread Lokesh Vutla
On Wednesday 08 July 2015 01:18 PM, Herbert Xu wrote:
 On Wed, Jul 08, 2015 at 12:29:47PM +0530, Lokesh Vutla wrote:

 +  if (req-assoclen + req-cryptlen == 0) {
 +  scatterwalk_map_and_copy(ctx-auth_tag, req-dst, 0, authlen,
 +   1);
 +  return 0;
 +  }

 How can this be right? Did you enable the selftest?
 Why not? Self tests are passed for this case.

 As per the equation given in GCM spec[1], we can see that
 if assoclen and cryptlen is 0, then output of GCM  is just E(K, Y0)
 where Y0 = IV||(0^31)1
 I have E(K, Y0) calculated in previous step. And copying it
 to destination if assoclen and cryptlen is 0.

 Correct me if I am wrong.
 
 It should be E(K, Y0) ^ GHASH(0).  So unless GHASH(0) == 0, your
 code doesn't work.
Yes, thats right. I have considered that.
So, we need GHASH(H, {}, {}).
As per the spec, 
GHASH(H, A, C) = X(m + n + 1). 
m = n = 0 in our case.

X0 = 0
X1 = (X(m  + n) ^ (len(A) || len(C)) . H
X1 = 0 . H  (GF(128) Multiplication)
X1 = 0  

The same thing is given in the Test case 1 of the spec. GHASH(H, {}, {}) = 0

Thanks and regards,
Lokesh

 
 Cheers,
 

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-08 Thread Lokesh Vutla
On Wednesday 08 July 2015 09:48 AM, Herbert Xu wrote:
 On Tue, Jul 07, 2015 at 09:01:48PM +0530, Lokesh Vutla wrote:

 +static int omap_aes_gcm_copy_buffers(struct omap_aes_dev *dd,
 + struct aead_request *req)
 +{
 +void *buf_in;
 +int pages, alen, clen, cryptlen, nsg;
 +struct crypto_aead *aead = crypto_aead_reqtfm(req);
 +unsigned int authlen = crypto_aead_authsize(aead);
 +u32 dec = !(dd-flags  FLAGS_ENCRYPT);
 +struct scatterlist *input, *assoc, tmp[2];
 +
 +alen = ALIGN(req-assoclen, AES_BLOCK_SIZE);
 +cryptlen = req-cryptlen - (dec * authlen);
 +clen = ALIGN(cryptlen, AES_BLOCK_SIZE);
 +
 +dd-sgs_copied = 0;
 +
 +nsg = !!(req-assoclen  req-cryptlen);
 +
 +assoc = req-src[0];
 +sg_init_table(dd-in_sgl, nsg + 1);
 +if (req-assoclen) {
 +if (omap_aes_check_aligned(assoc, req-assoclen)) {
 +dd-sgs_copied |= AES_ASSOC_DATA_COPIED;
 +pages = get_order(alen);
 +buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
 +if (!buf_in) {
 +pr_err(Couldn't allocate for unaligncases.\n);
 +return -1;
 +}
 +
 +scatterwalk_map_and_copy(buf_in, assoc, 0,
 + req-assoclen, 0);
 +memset(buf_in + req-assoclen, 0, alen - req-assoclen);
 +} else {
 +buf_in = sg_virt(req-assoc);
 
 req-assoc is now obsolete. Did you test this code?
Sorry, I missed it. Ill update.

 
 +static int do_encrypt_iv(struct aead_request *req, u32 *tag)
 +{
 +struct scatterlist iv_sg;
 +struct ablkcipher_request *ablk_req;
 +struct crypto_ablkcipher *tfm;
 +struct tcrypt_result result;
 +struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
 +int ret = 0;
 +
 +tfm = crypto_alloc_ablkcipher(ctr(aes), 0, 0);
 
 Ugh, you cannot allocate crypto transforms in the data path.  You
 should allocate it in init instead.  Also using ctr(aes) is overkill.
 Just use aes and do the xor by hand.
Ill take care of this.
 
 +static int omap_aes_gcm_crypt(struct aead_request *req, unsigned long mode)
 +{
 +struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
 +struct omap_aes_reqctx *rctx = aead_request_ctx(req);
 +struct crypto_aead *aead = crypto_aead_reqtfm(req);
 +unsigned int authlen = crypto_aead_authsize(aead);
 +struct omap_aes_dev *dd;
 +__be32 counter = cpu_to_be32(1);
 +int err;
 +
 +memset(ctx-auth_tag, 0, sizeof(ctx-auth_tag));
 
 The ctx is shared memory and you must not write to it as multiple
 requests can be called on the same tfm.  Use rctx instead.
 
 +memcpy(req-iv + 12, counter, 4);
 
 The IV is only 12 bytes long so you're corrupting memory here.
 You should use rctx here too.
Ok, Ill use rctx. Thanks for pointing.

 
 +if (req-assoclen + req-cryptlen == 0) {
 +scatterwalk_map_and_copy(ctx-auth_tag, req-dst, 0, authlen,
 + 1);
 +return 0;
 +}
 
 How can this be right? Did you enable the selftest?
Why not? Self tests are passed for this case.

As per the equation given in GCM spec[1], we can see that
if assoclen and cryptlen is 0, then output of GCM  is just E(K, Y0)
where Y0 = IV||(0^31)1
I have E(K, Y0) calculated in previous step. And copying it
to destination if assoclen and cryptlen is 0.

Correct me if I am wrong.

Thanks and regards,
Lokesh

[1] 
http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf

 
 Cheers,
 

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-07 Thread Lokesh Vutla
OMAP AES hw supports AES-GCM mode.
Adding support for GCM mode in omap-aes driver.

Signed-off-by: Lokesh Vutla lokeshvu...@ti.com
---
 drivers/crypto/Kconfig|   1 +
 drivers/crypto/Makefile   |   3 +-
 drivers/crypto/omap-aes-gcm.c | 376 ++
 drivers/crypto/omap-aes.c | 300 ++---
 drivers/crypto/omap-aes.h | 212 
 5 files changed, 718 insertions(+), 174 deletions(-)
 create mode 100644 drivers/crypto/omap-aes-gcm.c
 create mode 100644 drivers/crypto/omap-aes.h

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 4044125..6e67271 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -293,6 +293,7 @@ config CRYPTO_DEV_OMAP_AES
depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP2PLUS
select CRYPTO_AES
select CRYPTO_BLKCIPHER
+   select CRYPTO_AEAD
help
  OMAP processors have AES module accelerator. Select this if you
  want to use the OMAP module for AES algorithms.
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index e35c07a..73115bd 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_CRYPTO_DEV_MXS_DCP) += mxs-dcp.o
 obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o
 n2_crypto-y := n2_core.o n2_asm.o
 obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
-obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
+obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes-driver.o
+omap-aes-driver-objs := omap-aes.o omap-aes-gcm.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
diff --git a/drivers/crypto/omap-aes-gcm.c b/drivers/crypto/omap-aes-gcm.c
new file mode 100644
index 000..f0faa72
--- /dev/null
+++ b/drivers/crypto/omap-aes-gcm.c
@@ -0,0 +1,376 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for OMAP AES GCM HW acceleration.
+ *
+ * Copyright (c) 2015 Texas Instruments Incorporated
+ *
+ * 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/errno.h
+#include linux/scatterlist.h
+#include linux/dma-mapping.h
+#include linux/dmaengine.h
+#include linux/omap-dma.h
+#include linux/interrupt.h
+#include crypto/scatterwalk.h
+#include crypto/aes.h
+#include crypto/internal/aead.h
+#include omap-aes.h
+
+static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd,
+struct aead_request *req);
+
+static void omap_aes_gcm_finish_req(struct omap_aes_dev *dd, int ret)
+{
+   struct aead_request *req = dd-aead_req;
+
+   dd-flags = ~FLAGS_BUSY;
+   dd-in_sg = NULL;
+   dd-out_sg = NULL;
+
+   req-base.complete(req-base, ret);
+}
+
+static void omap_aes_gcm_done_task(struct omap_aes_dev *dd)
+{
+   void *buf;
+   u8 *tag;
+   int pages, alen, clen, i, ret = 0, nsg;
+
+   alen = ALIGN(dd-assoc_len, AES_BLOCK_SIZE);
+   clen = ALIGN(dd-total, AES_BLOCK_SIZE);
+
+   nsg = !!(dd-assoc_len  dd-total);
+
+   dma_sync_sg_for_device(dd-dev, dd-out_sg, dd-out_sg_len,
+  DMA_FROM_DEVICE);
+   dma_unmap_sg(dd-dev, dd-in_sg, dd-in_sg_len, DMA_TO_DEVICE);
+   dma_unmap_sg(dd-dev, dd-out_sg, dd-out_sg_len, DMA_FROM_DEVICE);
+   omap_aes_crypt_dma_stop(dd);
+
+   if (dd-sgs_copied  AES_OUT_DATA_COPIED) {
+   buf = sg_virt(dd-out_sgl);
+   scatterwalk_map_and_copy(buf, dd-orig_out, dd-assoc_len,
+dd-total, 1);
+
+   pages = get_order(clen);
+   free_pages((unsigned long)buf, pages);
+   }
+
+   if (dd-flags  FLAGS_ENCRYPT)
+   scatterwalk_map_and_copy(dd-ctx-auth_tag,
+dd-aead_req-dst,
+dd-total + dd-assoc_len,
+dd-authsize, 1);
+
+   if (dd-sgs_copied  AES_ASSOC_DATA_COPIED) {
+   buf = sg_virt(dd-in_sgl[0]);
+   pages = get_order(alen);
+   free_pages((unsigned long)buf, pages);
+   }
+   if (dd-sgs_copied  AES_IN_DATA_COPIED) {
+   buf = sg_virt(dd-in_sgl[nsg]);
+   pages = get_order(clen);
+   free_pages((unsigned long)buf, pages);
+   }
+
+   if (!(dd-flags  FLAGS_ENCRYPT)) {
+   tag = (u8 *)dd-ctx-auth_tag;
+   for (i = 0; i  dd-authsize; i++) {
+   if (tag[i]) {
+   dev_err(dd-dev, GCM decryption: Tag Message 
is wrong\n);
+   ret = -EBADMSG;
+   }
+   }
+   }
+
+   omap_aes_gcm_finish_req(dd, ret);
+   omap_aes_gcm_handle_queue(dd, NULL);
+}
+
+static int 

Re: [PATCH v2 6/7] crypto: omap-aes: Add support for GCM mode

2015-07-07 Thread Herbert Xu
On Tue, Jul 07, 2015 at 09:01:48PM +0530, Lokesh Vutla wrote:

 +static int omap_aes_gcm_copy_buffers(struct omap_aes_dev *dd,
 +  struct aead_request *req)
 +{
 + void *buf_in;
 + int pages, alen, clen, cryptlen, nsg;
 + struct crypto_aead *aead = crypto_aead_reqtfm(req);
 + unsigned int authlen = crypto_aead_authsize(aead);
 + u32 dec = !(dd-flags  FLAGS_ENCRYPT);
 + struct scatterlist *input, *assoc, tmp[2];
 +
 + alen = ALIGN(req-assoclen, AES_BLOCK_SIZE);
 + cryptlen = req-cryptlen - (dec * authlen);
 + clen = ALIGN(cryptlen, AES_BLOCK_SIZE);
 +
 + dd-sgs_copied = 0;
 +
 + nsg = !!(req-assoclen  req-cryptlen);
 +
 + assoc = req-src[0];
 + sg_init_table(dd-in_sgl, nsg + 1);
 + if (req-assoclen) {
 + if (omap_aes_check_aligned(assoc, req-assoclen)) {
 + dd-sgs_copied |= AES_ASSOC_DATA_COPIED;
 + pages = get_order(alen);
 + buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
 + if (!buf_in) {
 + pr_err(Couldn't allocate for unaligncases.\n);
 + return -1;
 + }
 +
 + scatterwalk_map_and_copy(buf_in, assoc, 0,
 +  req-assoclen, 0);
 + memset(buf_in + req-assoclen, 0, alen - req-assoclen);
 + } else {
 + buf_in = sg_virt(req-assoc);

req-assoc is now obsolete. Did you test this code?

 +static int do_encrypt_iv(struct aead_request *req, u32 *tag)
 +{
 + struct scatterlist iv_sg;
 + struct ablkcipher_request *ablk_req;
 + struct crypto_ablkcipher *tfm;
 + struct tcrypt_result result;
 + struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
 + int ret = 0;
 +
 + tfm = crypto_alloc_ablkcipher(ctr(aes), 0, 0);

Ugh, you cannot allocate crypto transforms in the data path.  You
should allocate it in init instead.  Also using ctr(aes) is overkill.
Just use aes and do the xor by hand.

 +static int omap_aes_gcm_crypt(struct aead_request *req, unsigned long mode)
 +{
 + struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
 + struct omap_aes_reqctx *rctx = aead_request_ctx(req);
 + struct crypto_aead *aead = crypto_aead_reqtfm(req);
 + unsigned int authlen = crypto_aead_authsize(aead);
 + struct omap_aes_dev *dd;
 + __be32 counter = cpu_to_be32(1);
 + int err;
 +
 + memset(ctx-auth_tag, 0, sizeof(ctx-auth_tag));

The ctx is shared memory and you must not write to it as multiple
requests can be called on the same tfm.  Use rctx instead.

 + memcpy(req-iv + 12, counter, 4);

The IV is only 12 bytes long so you're corrupting memory here.
You should use rctx here too.

 + if (req-assoclen + req-cryptlen == 0) {
 + scatterwalk_map_and_copy(ctx-auth_tag, req-dst, 0, authlen,
 +  1);
 + return 0;
 + }

How can this be right? Did you enable the selftest?

Cheers,
-- 
Email: Herbert Xu herb...@gondor.apana.org.au
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html