[PATCH next 1/2] crypto: atmel-sha: fix missing "return" instructions

2017-02-09 Thread Cyrille Pitchen
This patch fixes a previous patch: "crypto: atmel-sha - update request
queue management to make it more generic".

Indeed the patch above should have replaced the "return -EINVAL;" lines by
"return atmel_sha_complete(dd, -EINVAL);" but instead replaced them by a
simple call of "atmel_sha_complete(dd, -EINVAL);".
Hence all "return" instructions were missing.

Reported-by: Dan Carpenter <dan.carpen...@oracle.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 22d0c0c118da..d6c3d9529d36 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -668,7 +668,7 @@ static int atmel_sha_xmit_dma(struct atmel_sha_dev *dd, 
dma_addr_t dma_addr1,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
if (!in_desc)
-   atmel_sha_complete(dd, -EINVAL);
+   return atmel_sha_complete(dd, -EINVAL);
 
in_desc->callback = atmel_sha_dma_callback;
in_desc->callback_param = dd;
@@ -725,7 +725,7 @@ static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
ctx->block_size);
-   atmel_sha_complete(dd, -EINVAL);
+   return atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags &= ~SHA_FLAGS_SG;
@@ -816,7 +816,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n",
ctx->buflen + ctx->block_size);
-   atmel_sha_complete(dd, -EINVAL);
+   return atmel_sha_complete(dd, -EINVAL);
}
 
if (length == 0) {
@@ -830,7 +830,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (!dma_map_sg(dd->dev, ctx->sg, 1,
DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   atmel_sha_complete(dd, -EINVAL);
+   return atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags |= SHA_FLAGS_SG;
@@ -844,7 +844,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
 
if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   atmel_sha_complete(dd, -EINVAL);
+   return atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags |= SHA_FLAGS_SG;
-- 
2.7.4



[PATCH next 0/2] crypto: atmel-sha: fix error management

2017-02-09 Thread Cyrille Pitchen
Hi all,

this series is based on next-20170209.

The first patch fixes a bug reported by Dan Carpenter. I didn't put a
Fixes tag since the buggy patch is only in linux-next for now so its
commit ID is likely to change when entering Linus' tree.
It fixes a wrong 'sed' command: many "return -EINVAL;" lines should have
been replaced by "return atmel_sha_complete(dd, -EINVAL);" but instead
were replaced by direct calls of "atmel_sha_complete(dd, -EINVAL);".
My bad, sorry for that!

The second patch fixes the way error cases are handled from
atmel_sha_start(). For instance, when atmel_sha_update_req() returned an
error, atmel_sha_final_req() may have been called after anyway. This issue
was present even before my rework of the request queue management, which
introduced atmel_sha_start(), so I guess this is a long time issue.

Finally, for driver maintainance purpose, I'm preparing other patches to
fix the very same and very unlikely issue in both atmel-aes.c and
atmel-sha.c:

atmel_{aes|sha}_hw_init() may fail, for instance if clk_enable() fails.
If so, atmel_{aes|sha}_complete() is called to release the hardware and
report the error. Indeed this _complete() function should be called to
report and handle any error. However it also incondionnally calls
clk_disable(). Hence the following sequence may be buggy:

err = atmel_{aes|sha}_hw_init(dd); /* clk_enable() may have failed. */
if (err)
return atmel_{aes|sha}_hw_init(dd, err);
/* clk_disable() is called anyway. */

I didn't finalize my fixes yet for this unlikely bug. Besides the bug was
already present in v4.9 and before, so before introducing
atmel_sha_complete().

from atmel_sha_handle_queue(), the older sequence was:

err = atmel_sha_hw_init(dd);

if (err)
goto err1;

[...]

err1:
if (err != -EINPROGRESS)
/* done_task will not finish it, so do it here */
atmel_sha_finish_req(req, err);

Best regards,

Cyrille

Cyrille Pitchen (2):
  crypto: atmel-sha: fix missing "return" instructions
  crypto: atmel-sha: fix error management in atmel_sha_start()

 drivers/crypto/atmel-sha.c | 37 +++--
 1 file changed, 27 insertions(+), 10 deletions(-)

-- 
2.7.4



[PATCH next 2/2] crypto: atmel-sha: fix error management in atmel_sha_start()

2017-02-09 Thread Cyrille Pitchen
This patch clarifies and fixes how errors should be handled by
atmel_sha_start().

For update operations, the previous code wrongly assumed that
(err != -EINPROGRESS) implies (err == 0). It's wrong because that doesn't
take the error cases (err < 0) into account.

This patch also adds many comments to detail all the possible returned
values and what should be done in each case.

Especially, when an error occurs, since atmel_sha_complete() has already
been called, hence releasing the hardware, atmel_sha_start() must not call
atmel_sha_finish_req() later otherwise atmel_sha_complete() would be
called a second time.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 27 ++-
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index d6c3d9529d36..0d207dac9aa2 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -1106,22 +1106,39 @@ static int atmel_sha_start(struct atmel_sha_dev *dd)
ctx->op, req->nbytes);
 
err = atmel_sha_hw_init(dd);
-
if (err)
-   goto err1;
+   return atmel_sha_complete(dd, err);
+
+   /*
+* atmel_sha_update_req() and atmel_sha_final_req() can return either:
+*  -EINPROGRESS: the hardware is busy and the SHA driver will resume
+*its job later in the done_task.
+*This is the main path.
+*
+* 0: the SHA driver can continue its job then release the hardware
+*later, if needed, with atmel_sha_finish_req().
+*This is the alternate path.
+*
+* < 0: an error has occurred so atmel_sha_complete(dd, err) has already
+*  been called, hence the hardware has been released.
+*  The SHA driver must stop its job without calling
+*  atmel_sha_finish_req(), otherwise atmel_sha_complete() would be
+*  called a second time.
+*
+* Please note that currently, atmel_sha_final_req() never returns 0.
+*/
 
dd->resume = atmel_sha_done;
if (ctx->op == SHA_OP_UPDATE) {
err = atmel_sha_update_req(dd);
-   if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
+   if (!err && (ctx->flags & SHA_FLAGS_FINUP))
/* no final() after finup() */
err = atmel_sha_final_req(dd);
} else if (ctx->op == SHA_OP_FINAL) {
err = atmel_sha_final_req(dd);
}
 
-err1:
-   if (err != -EINPROGRESS)
+   if (!err)
/* done_task will not finish it, so do it here */
atmel_sha_finish_req(req, err);
 
-- 
2.7.4



Re: [bug report] crypto: atmel-sha - update request queue management to make it more generic

2017-02-07 Thread Cyrille Pitchen
Hi Dan,

Le 07/02/2017 à 11:56, Dan Carpenter a écrit :
> Hello Cyrille Pitchen,
> 
> The patch a29af939b24d: "crypto: atmel-sha - update request queue
> management to make it more generic" from Jan 26, 2017, leads to the
> following static checker warning:
> 
>   drivers/crypto/atmel-sha.c:673 atmel_sha_xmit_dma()
>   error: we previously assumed 'in_desc' could be null (see line 670)
> 
> drivers/crypto/atmel-sha.c
>652  
>653  dmaengine_slave_config(dd->dma_lch_in.chan, 
> >dma_lch_in.dma_conf);
>654  
>655  if (length2) {
>656  sg_init_table(sg, 2);
>657  sg_dma_address([0]) = dma_addr1;
>658  sg_dma_len([0]) = length1;
>659  sg_dma_address([1]) = dma_addr2;
>660  sg_dma_len([1]) = length2;
>661  in_desc = 
> dmaengine_prep_slave_sg(dd->dma_lch_in.chan, sg, 2,
>662  DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | 
> DMA_CTRL_ACK);
>663  } else {
>664  sg_init_table(sg, 1);
>665  sg_dma_address([0]) = dma_addr1;
>666  sg_dma_len([0]) = length1;
>667  in_desc = 
> dmaengine_prep_slave_sg(dd->dma_lch_in.chan, sg, 1,
>668  DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | 
> DMA_CTRL_ACK);
>669  }
>670  if (!in_desc)
>671  atmel_sha_complete(dd, -EINVAL);
> 
> Did you mean return atmel_sha_complete(dd, -EINVAL);???  That patch
> change a bunch of returns to just call atmel_sha_complete().  Someone
> should probably review it again to make sure there aren't other bugs
> as well.

Indeed, you're totally right: the "return -EINVAL" lines updated by the
patch should have been replaced by "return atmel_sha_complete(dd, -EINVAL);".

Sorry for that :(
and thanks for having caught it :)

I will prepare a fix for it.

Best regards,

Cyrille

> 
>672  
>673  in_desc->callback = atmel_sha_dma_callback;
> ^
> NULL dereference.
> 
>674  in_desc->callback_param = dd;
>675  
>676  atmel_sha_write_ctrl(dd, 1);
>677  
> 
> regards,
> dan carpenter
> 



[PATCH v3 09/12] crypto: atmel-sha: add support to hmac(shaX)

2017-01-26 Thread Cyrille Pitchen
This patch adds support to the hmac(shaX) algorithms.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h |   4 +
 drivers/crypto/atmel-sha.c  | 598 +++-
 2 files changed, 601 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index 8d62d31eda08..1b9f3d33079e 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -26,6 +26,7 @@
 #define SHA_MR_ALGO_SHA384 (2 << 8)
 #define SHA_MR_ALGO_SHA512 (3 << 8)
 #define SHA_MR_ALGO_SHA224 (4 << 8)
+#define SHA_MR_HMAC(1 << 11)
 #defineSHA_MR_DUALBUFF (1 << 16)
 
 #define SHA_IER0x10
@@ -42,6 +43,9 @@
 #define SHA_ISR_URAT_MR(0x2 << 12)
 #define SHA_ISR_URAT_WO(0x5 << 12)
 
+#define SHA_MSR0x20
+#define SHA_BCR0x30
+
 #defineSHA_HW_VERSION  0xFC
 
 #define SHA_TPR0x108
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index a4fc60b67099..78c3c02e4483 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,13 +51,20 @@
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
 
-/* bits[10:8] are reserved. */
+/* bits[11:8] are reserved. */
 #define SHA_FLAGS_ALGO_MASKSHA_MR_ALGO_MASK
 #define SHA_FLAGS_SHA1 SHA_MR_ALGO_SHA1
 #define SHA_FLAGS_SHA256   SHA_MR_ALGO_SHA256
 #define SHA_FLAGS_SHA384   SHA_MR_ALGO_SHA384
 #define SHA_FLAGS_SHA512   SHA_MR_ALGO_SHA512
 #define SHA_FLAGS_SHA224   SHA_MR_ALGO_SHA224
+#define SHA_FLAGS_HMAC SHA_MR_HMAC
+#define SHA_FLAGS_HMAC_SHA1(SHA_FLAGS_HMAC | SHA_FLAGS_SHA1)
+#define SHA_FLAGS_HMAC_SHA256  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA256)
+#define SHA_FLAGS_HMAC_SHA384  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA384)
+#define SHA_FLAGS_HMAC_SHA512  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA512)
+#define SHA_FLAGS_HMAC_SHA224  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA224)
+#define SHA_FLAGS_MODE_MASK(SHA_FLAGS_HMAC | SHA_FLAGS_ALGO_MASK)
 
 #define SHA_FLAGS_FINUPBIT(16)
 #define SHA_FLAGS_SG   BIT(17)
@@ -67,8 +74,10 @@
 #define SHA_FLAGS_IDATAR0  BIT(26)
 #define SHA_FLAGS_WAIT_DATARDY BIT(27)
 
+#define SHA_OP_INIT0
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
+#define SHA_OP_DIGEST  3
 
 #define SHA_BUFFER_LEN (PAGE_SIZE / 16)
 
@@ -80,6 +89,7 @@ struct atmel_sha_caps {
boolhas_sha224;
boolhas_sha_384_512;
boolhas_uihv;
+   boolhas_hmac;
 };
 
 struct atmel_sha_dev;
@@ -105,6 +115,7 @@ struct atmel_sha_reqctx {
unsigned inttotal;  /* total request */
 
size_t block_size;
+   size_t hash_size;
 
u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
@@ -152,6 +163,8 @@ struct atmel_sha_dev {
 
struct atmel_sha_caps   caps;
 
+   struct scatterlist  tmp;
+
u32 hw_version;
 };
 
@@ -1522,11 +1535,579 @@ static int atmel_sha_cpu_start(struct atmel_sha_dev 
*dd,
return atmel_sha_cpu_transfer(dd);
 }
 
+static int atmel_sha_cpu_hash(struct atmel_sha_dev *dd,
+ const void *data, unsigned int datalen,
+ bool auto_padding,
+ atmel_sha_fn_t resume)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   u32 msglen = (auto_padding) ? datalen : 0;
+   u32 mr = SHA_MR_MODE_AUTO;
+
+   if (!(IS_ALIGNED(datalen, ctx->block_size) || auto_padding))
+   return atmel_sha_complete(dd, -EINVAL);
+
+   mr |= (ctx->flags & SHA_FLAGS_ALGO_MASK);
+   atmel_sha_write(dd, SHA_MR, mr);
+   atmel_sha_write(dd, SHA_MSR, msglen);
+   atmel_sha_write(dd, SHA_BCR, msglen);
+   atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST);
+
+   sg_init_one(>tmp, data, datalen);
+   return atmel_sha_cpu_start(dd, >tmp, datalen, false, true, resume);
+}
+
+
+/* hmac functions */
+
+struct atmel_sha_hmac_key {
+   boolvalid;
+   unsigned intkeylen;
+   u8  buffer[SHA512_BLOCK_SIZE];
+   u8  *keydup;
+};
+
+static inline void atmel_sha_hmac_key_init(struct atmel_sha_hmac_key *hkey)
+{
+   memset(hkey, 0, sizeof(*hkey));
+}
+
+static inline void atmel_sha_hmac_key_release(struct atmel_sha_hmac_key *hkey)
+{
+   kfree(hkey->keydup);
+   memset(hkey, 0, sizeof(*hkey));
+}
+
+static inline int atmel_sha_hmac_key_set(struct atmel_sha_hmac_key *hkey,
+const u8 *key,
+

[PATCH v3 08/12] crypto: atmel-sha: add simple DMA transfers

2017-01-26 Thread Cyrille Pitchen
This patch adds a simple function to perform data transfer with the DMA
controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 116 +
 1 file changed, 116 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 58d9ca8ac0f2..a4fc60b67099 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -123,6 +123,9 @@ struct atmel_sha_ctx {
 struct atmel_sha_dma {
struct dma_chan *chan;
struct dma_slave_config dma_conf;
+   struct scatterlist  *sg;
+   int nents;
+   unsigned intlast_sg_length;
 };
 
 struct atmel_sha_dev {
@@ -1321,6 +1324,119 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
 }
 
 
+/* DMA transfer functions */
+
+static bool atmel_sha_dma_check_aligned(struct atmel_sha_dev *dd,
+   struct scatterlist *sg,
+   size_t len)
+{
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   size_t bs = ctx->block_size;
+   int nents;
+
+   for (nents = 0; sg; sg = sg_next(sg), ++nents) {
+   if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+   return false;
+
+   /*
+* This is the last sg, the only one that is allowed to
+* have an unaligned length.
+*/
+   if (len <= sg->length) {
+   dma->nents = nents + 1;
+   dma->last_sg_length = sg->length;
+   sg->length = ALIGN(len, sizeof(u32));
+   return true;
+   }
+
+   /* All other sg lengths MUST be aligned to the block size. */
+   if (!IS_ALIGNED(sg->length, bs))
+   return false;
+
+   len -= sg->length;
+   }
+
+   return false;
+}
+
+static void atmel_sha_dma_callback2(void *data)
+{
+   struct atmel_sha_dev *dd = data;
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct scatterlist *sg;
+   int nents;
+
+   dmaengine_terminate_all(dma->chan);
+   dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+
+   sg = dma->sg;
+   for (nents = 0; nents < dma->nents - 1; ++nents)
+   sg = sg_next(sg);
+   sg->length = dma->last_sg_length;
+
+   dd->is_async = true;
+   (void)atmel_sha_wait_for_data_ready(dd, dd->resume);
+}
+
+static int atmel_sha_dma_start(struct atmel_sha_dev *dd,
+  struct scatterlist *src,
+  size_t len,
+  atmel_sha_fn_t resume)
+{
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct dma_slave_config *config = >dma_conf;
+   struct dma_chan *chan = dma->chan;
+   struct dma_async_tx_descriptor *desc;
+   dma_cookie_t cookie;
+   unsigned int sg_len;
+   int err;
+
+   dd->resume = resume;
+
+   /*
+* dma->nents has already been initialized by
+* atmel_sha_dma_check_aligned().
+*/
+   dma->sg = src;
+   sg_len = dma_map_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+   if (!sg_len) {
+   err = -ENOMEM;
+   goto exit;
+   }
+
+   config->src_maxburst = 16;
+   config->dst_maxburst = 16;
+   err = dmaengine_slave_config(chan, config);
+   if (err)
+   goto unmap_sg;
+
+   desc = dmaengine_prep_slave_sg(chan, dma->sg, sg_len, DMA_MEM_TO_DEV,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc) {
+   err = -ENOMEM;
+   goto unmap_sg;
+   }
+
+   desc->callback = atmel_sha_dma_callback2;
+   desc->callback_param = dd;
+   cookie = dmaengine_submit(desc);
+   err = dma_submit_error(cookie);
+   if (err)
+   goto unmap_sg;
+
+   dma_async_issue_pending(chan);
+
+   return -EINPROGRESS;
+
+unmap_sg:
+   dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+exit:
+   return atmel_sha_complete(dd, err);
+}
+
+
 /* CPU transfer functions */
 
 static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
-- 
2.7.4

--
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 v3 10/12] crypto: atmel-aes: fix atmel_aes_handle_queue()

2017-01-26 Thread Cyrille Pitchen
This patch fixes the value returned by atmel_aes_handle_queue(), which
could have been wrong previously when the crypto request was started
synchronously but became asynchronous during the ctx->start() call.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 0e3d0d655b96..9fd2f63b8bc0 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -879,6 +879,7 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
struct crypto_async_request *areq, *backlog;
struct atmel_aes_base_ctx *ctx;
unsigned long flags;
+   bool start_async;
int err, ret = 0;
 
spin_lock_irqsave(>lock, flags);
@@ -904,10 +905,12 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev 
*dd,
 
dd->areq = areq;
dd->ctx = ctx;
-   dd->is_async = (areq != new_areq);
+   start_async = (areq != new_areq);
+   dd->is_async = start_async;
 
+   /* WARNING: ctx->start() MAY change dd->is_async. */
err = ctx->start(dd);
-   return (dd->is_async) ? ret : err;
+   return (start_async) ? ret : err;
 }
 
 
-- 
2.7.4

--
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 v3 02/12] crypto: atmel-sha: update request queue management to make it more generic

2017-01-26 Thread Cyrille Pitchen
This patch is a transitional patch. It splits the atmel_sha_handle_queue()
function. Now atmel_sha_handle_queue() only manages the request queue and
calls a new .start() hook from the atmel_sha_ctx structure.
This hook allows to implement different kind of requests still handled by
a single queue.

Also when the req parameter of atmel_sha_handle_queue() refers to the very
same request as the one returned by crypto_dequeue_request(), the queue
management now gives a chance to this crypto request to be handled
synchronously, hence reducing latencies. The .start() hook returns 0 if
the crypto request was handled synchronously and -EINPROGRESS if the
crypto request still need to be handled asynchronously.

Besides, the new .is_async member of the atmel_sha_dev structure helps
tagging this asynchronous state. Indeed, the req->base.complete() callback
should not be called if the crypto request is handled synchronously.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 74 +-
 1 file changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 33a36e667547..2dbed8bb8d26 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -105,8 +105,11 @@ struct atmel_sha_reqctx {
u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
 
+typedef int (*atmel_sha_fn_t)(struct atmel_sha_dev *);
+
 struct atmel_sha_ctx {
struct atmel_sha_dev*dd;
+   atmel_sha_fn_t  start;
 
unsigned long   flags;
 };
@@ -134,6 +137,7 @@ struct atmel_sha_dev {
unsigned long   flags;
struct crypto_queue queue;
struct ahash_request*req;
+   boolis_async;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -163,6 +167,24 @@ static inline void atmel_sha_write(struct atmel_sha_dev 
*dd,
writel_relaxed(value, dd->io_base + offset);
 }
 
+static inline int atmel_sha_complete(struct atmel_sha_dev *dd, int err)
+{
+   struct ahash_request *req = dd->req;
+
+   dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
+  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+
+   clk_disable(dd->iclk);
+
+   if (dd->is_async && req->base.complete)
+   req->base.complete(>base, err);
+
+   /* handle new request */
+   tasklet_schedule(>queue_task);
+
+   return err;
+}
+
 static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
 {
size_t count;
@@ -474,6 +496,8 @@ static void atmel_sha_dma_callback(void *data)
 {
struct atmel_sha_dev *dd = data;
 
+   dd->is_async = true;
+
/* dma_lch_in - completed - wait DATRDY */
atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
 }
@@ -509,7 +533,7 @@ static int atmel_sha_xmit_dma(struct atmel_sha_dev *dd, 
dma_addr_t dma_addr1,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
if (!in_desc)
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
 
in_desc->callback = atmel_sha_dma_callback;
in_desc->callback_param = dd;
@@ -566,7 +590,7 @@ static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
ctx->block_size);
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags &= ~SHA_FLAGS_SG;
@@ -657,7 +681,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n",
ctx->buflen + ctx->block_size);
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
if (length == 0) {
@@ -671,7 +695,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (!dma_map_sg(dd->dev, ctx->sg, 1,
DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags |= SHA_FLAGS_SG;
@@ -685,7 +709,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
 
if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   return -EINVAL;
+   atmel_sha_compl

[PATCH v3 11/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2017-01-26 Thread Cyrille Pitchen
This patchs allows to combine the AES and SHA hardware accelerators on
some Atmel SoCs. Doing so, AES blocks are only written to/read from the
AES hardware. Those blocks are also transferred from the AES to the SHA
accelerator internally, without additionnal accesses to the system busses.

Hence, the AES and SHA accelerators work in parallel to process all the
data blocks, instead of serializing the process by (de)crypting those
blocks first then authenticating them after like the generic
crypto/authenc.c driver does.

Of course, both the AES and SHA hardware accelerators need to be available
before we can start to process the data blocks. Hence we use their crypto
request queue to synchronize both drivers.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/Kconfig  |  12 ++
 drivers/crypto/atmel-aes-regs.h |  16 ++
 drivers/crypto/atmel-aes.c  | 448 +++-
 drivers/crypto/atmel-authenc.h  |  64 ++
 drivers/crypto/atmel-sha-regs.h |  14 ++
 drivers/crypto/atmel-sha.c  | 344 --
 6 files changed, 883 insertions(+), 15 deletions(-)
 create mode 100644 drivers/crypto/atmel-authenc.h

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index bf7da55cffe6..74824612d3e9 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -415,6 +415,18 @@ config CRYPTO_DEV_BFIN_CRC
  Newer Blackfin processors have CRC hardware. Select this if you
  want to use the Blackfin CRC module.
 
+config CRYPTO_DEV_ATMEL_AUTHENC
+   tristate "Support for Atmel IPSEC/SSL hw accelerator"
+   depends on (ARCH_AT91 && HAS_DMA) || COMPILE_TEST
+   select CRYPTO_AUTHENC
+   select CRYPTO_DEV_ATMEL_AES
+   select CRYPTO_DEV_ATMEL_SHA
+   help
+ Some Atmel processors can combine the AES and SHA hw accelerators
+ to enhance support of IPSEC/SSL.
+ Select this if you want to use the Atmel modules for
+ authenc(hmac(shaX),Y(cbc)) algorithms.
+
 config CRYPTO_DEV_ATMEL_AES
tristate "Support for Atmel AES hw accelerator"
depends on HAS_DMA
diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
index 0ec04407b533..7694679802b3 100644
--- a/drivers/crypto/atmel-aes-regs.h
+++ b/drivers/crypto/atmel-aes-regs.h
@@ -68,6 +68,22 @@
 #define AES_CTRR   0x98
 #define AES_GCMHR(x)   (0x9c + ((x) * 0x04))
 
+#define AES_EMR0xb0
+#define AES_EMR_APEN   BIT(0)  /* Auto Padding Enable */
+#define AES_EMR_APMBIT(1)  /* Auto Padding Mode */
+#define AES_EMR_APM_IPSEC  0x0
+#define AES_EMR_APM_SSLBIT(1)
+#define AES_EMR_PLIPEN BIT(4)  /* PLIP Enable */
+#define AES_EMR_PLIPD  BIT(5)  /* PLIP Decipher */
+#define AES_EMR_PADLEN_MASK(0xFu << 8)
+#define AES_EMR_PADLEN_OFFSET  8
+#define AES_EMR_PADLEN(padlen) (((padlen) << AES_EMR_PADLEN_OFFSET) &\
+AES_EMR_PADLEN_MASK)
+#define AES_EMR_NHEAD_MASK (0xFu << 16)
+#define AES_EMR_NHEAD_OFFSET   16
+#define AES_EMR_NHEAD(nhead)   (((nhead) << AES_EMR_NHEAD_OFFSET) &\
+AES_EMR_NHEAD_MASK)
+
 #define AES_TWR(x) (0xc0 + ((x) * 0x04))
 #define AES_ALPHAR(x)  (0xd0 + ((x) * 0x04))
 
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 9fd2f63b8bc0..29e20c37f3a6 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include "atmel-aes-regs.h"
+#include "atmel-authenc.h"
 
 #define ATMEL_AES_PRIORITY 300
 
@@ -78,6 +79,7 @@
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
 #define AES_FLAGS_DUMP_REG BIT(4)
+#define AES_FLAGS_OWN_SHA  BIT(5)
 
 #define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
 
@@ -92,6 +94,7 @@ struct atmel_aes_caps {
boolhas_ctr32;
boolhas_gcm;
boolhas_xts;
+   boolhas_authenc;
u32 max_burst_size;
 };
 
@@ -144,10 +147,31 @@ struct atmel_aes_xts_ctx {
u32 key2[AES_KEYSIZE_256 / sizeof(u32)];
 };
 
+#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+struct atmel_aes_authenc_ctx {
+   struct atmel_aes_base_ctx   base;
+   struct atmel_sha_authenc_ctx*auth;
+};
+#endif
+
 struct atmel_aes_reqctx {
unsigned long   mode;
 };
 
+#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+struct atmel_aes_authenc_reqctx {
+   struct atmel_aes_reqctx base;
+
+   struct scatterlist  src[2];
+   struct scatterlist  dst[2];
+   size_t  textlen;
+   u32 digest[SHA512_DIGEST_SIZE / sizeof(u32)];
+
+   /* auth_req MUST be place last. */
+   struct ahash_requestauth_req;
+};
+

[PATCH v3 01/12] crypto: atmel-sha: create function to get an Atmel SHA device

2017-01-26 Thread Cyrille Pitchen
This is a transitional patch: it creates the atmel_sha_find_dev() function,
which will be used in further patches to share the source code responsible
for finding a Atmel SHA device.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 97e34799e077..33a36e667547 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -260,11 +260,8 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
}
 }
 
-static int atmel_sha_init(struct ahash_request *req)
+static struct atmel_sha_dev *atmel_sha_find_dev(struct atmel_sha_ctx *tctx)
 {
-   struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-   struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
-   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
struct atmel_sha_dev *dd = NULL;
struct atmel_sha_dev *tmp;
 
@@ -281,6 +278,16 @@ static int atmel_sha_init(struct ahash_request *req)
 
spin_unlock_bh(_sha.lock);
 
+   return dd;
+}
+
+static int atmel_sha_init(struct ahash_request *req)
+{
+   struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+   struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   struct atmel_sha_dev *dd = atmel_sha_find_dev(tctx);
+
ctx->dd = dd;
 
ctx->flags = 0;
-- 
2.7.4

--
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 v3 04/12] crypto: atmel-sha: redefine SHA_FLAGS_SHA* flags to match SHA_MR_ALGO_SHA*

2017-01-26 Thread Cyrille Pitchen
This patch modifies the SHA_FLAGS_SHA* flags: those algo flags are now
organized as values of a single bitfield instead of individual bits.
This allows to reduce the number of bits needed to encode all possible
values. Also the new values match the SHA_MR_ALGO_SHA* values hence
the algorithm bitfield of the SHA_MR register could simply be set with:

mr = (mr & ~SHA_FLAGS_ALGO_MASK) | (ctx->flags & SHA_FLAGS_ALGO_MASK)

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h |  1 +
 drivers/crypto/atmel-sha.c  | 45 +
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index e08897109cab..deb0b0b15096 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -19,6 +19,7 @@
 #define SHA_MR_PROCDLY (1 << 4)
 #define SHA_MR_UIHV(1 << 5)
 #define SHA_MR_UIEHV   (1 << 6)
+#define SHA_MR_ALGO_MASK   GENMASK(10, 8)
 #define SHA_MR_ALGO_SHA1   (0 << 8)
 #define SHA_MR_ALGO_SHA256 (1 << 8)
 #define SHA_MR_ALGO_SHA384 (2 << 8)
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 643d79a05dda..b29a4e5bc404 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,14 +51,16 @@
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
 
+/* bits[10:8] are reserved. */
+#define SHA_FLAGS_ALGO_MASKSHA_MR_ALGO_MASK
+#define SHA_FLAGS_SHA1 SHA_MR_ALGO_SHA1
+#define SHA_FLAGS_SHA256   SHA_MR_ALGO_SHA256
+#define SHA_FLAGS_SHA384   SHA_MR_ALGO_SHA384
+#define SHA_FLAGS_SHA512   SHA_MR_ALGO_SHA512
+#define SHA_FLAGS_SHA224   SHA_MR_ALGO_SHA224
+
 #define SHA_FLAGS_FINUPBIT(16)
 #define SHA_FLAGS_SG   BIT(17)
-#define SHA_FLAGS_ALGO_MASKGENMASK(22, 18)
-#define SHA_FLAGS_SHA1 BIT(18)
-#define SHA_FLAGS_SHA224   BIT(19)
-#define SHA_FLAGS_SHA256   BIT(20)
-#define SHA_FLAGS_SHA384   BIT(21)
-#define SHA_FLAGS_SHA512   BIT(22)
 #define SHA_FLAGS_ERRORBIT(23)
 #define SHA_FLAGS_PAD  BIT(24)
 #define SHA_FLAGS_RESTORE  BIT(25)
@@ -264,7 +266,9 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
bits[1] = cpu_to_be64(size[0] << 3);
bits[0] = cpu_to_be64(size[1] << 3 | size[0] >> 61);
 
-   if (ctx->flags & (SHA_FLAGS_SHA384 | SHA_FLAGS_SHA512)) {
+   switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+   case SHA_FLAGS_SHA384:
+   case SHA_FLAGS_SHA512:
index = ctx->bufcnt & 0x7f;
padlen = (index < 112) ? (112 - index) : ((128+112) - index);
*(ctx->buffer + ctx->bufcnt) = 0x80;
@@ -272,7 +276,9 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
ctx->bufcnt += padlen + 16;
ctx->flags |= SHA_FLAGS_PAD;
-   } else {
+   break;
+
+   default:
index = ctx->bufcnt & 0x3f;
padlen = (index < 56) ? (56 - index) : ((64+56) - index);
*(ctx->buffer + ctx->bufcnt) = 0x80;
@@ -280,6 +286,7 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
memcpy(ctx->buffer + ctx->bufcnt + padlen, [1], 8);
ctx->bufcnt += padlen + 8;
ctx->flags |= SHA_FLAGS_PAD;
+   break;
}
 }
 
@@ -828,16 +835,28 @@ static void atmel_sha_copy_ready_hash(struct 
ahash_request *req)
if (!req->result)
return;
 
-   if (ctx->flags & SHA_FLAGS_SHA1)
+   switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+   default:
+   case SHA_FLAGS_SHA1:
memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA224)
+   break;
+
+   case SHA_FLAGS_SHA224:
memcpy(req->result, ctx->digest, SHA224_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA256)
+   break;
+
+   case SHA_FLAGS_SHA256:
memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA384)
+   break;
+
+   case SHA_FLAGS_SHA384:
memcpy(req->result, ctx->digest, SHA384_DIGEST_SIZE);
-   else
+   break;
+
+   case SHA_FLAGS_SHA512:
memcpy(req->result, ctx->digest, SHA512_DIGEST_SIZE);
+   break;
+   }
 }
 
 static int atmel_sha_finish(struct ahash_request *req)
-- 
2.7.4

--
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 v3 06/12] crypto: atmel-sha: add SHA_MR_MODE_IDATAR0

2017-01-26 Thread Cyrille Pitchen
This patch defines an alias macro to SHA_MR_MODE_PDC, which is not suited
for DMA usage.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index deb0b0b15096..8d62d31eda08 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -16,6 +16,7 @@
 #define SHA_MR_MODE_MANUAL 0x0
 #define SHA_MR_MODE_AUTO   0x1
 #define SHA_MR_MODE_PDC0x2
+#define SHA_MR_MODE_IDATAR00x2
 #define SHA_MR_PROCDLY (1 << 4)
 #define SHA_MR_UIHV(1 << 5)
 #define SHA_MR_UIEHV   (1 << 6)
-- 
2.7.4

--
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 v3 05/12] crypto: atmel-sha: add atmel_sha_wait_for_data_ready()

2017-01-26 Thread Cyrille Pitchen
This patch simply defines a helper function to test the 'Data Ready' flag
of the Status Register. It also gives a chance for the crypto request to
be processed synchronously if this 'Data Ready' flag is already set when
polling the Status Register. Indeed, running synchronously avoid the
latency of the 'Data Ready' interrupt.

When the 'Data Ready' flag has not been set yet, we enable the associated
interrupt and resume processing the crypto request asynchronously from the
'done' task just as before.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index b29a4e5bc404..be0d72cf4352 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -434,6 +434,19 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, 
int dma)
atmel_sha_write(dd, SHA_MR, valmr);
 }
 
+static inline int atmel_sha_wait_for_data_ready(struct atmel_sha_dev *dd,
+   atmel_sha_fn_t resume)
+{
+   u32 isr = atmel_sha_read(dd, SHA_ISR);
+
+   if (unlikely(isr & SHA_INT_DATARDY))
+   return resume(dd);
+
+   dd->resume = resume;
+   atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+   return -EINPROGRESS;
+}
+
 static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf,
  size_t length, int final)
 {
-- 
2.7.4

--
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 v3 07/12] crypto: atmel-sha: add atmel_sha_cpu_start()

2017-01-26 Thread Cyrille Pitchen
This patch adds a simple function to perform data transfer with PIO, hence
handled by the CPU.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 90 ++
 1 file changed, 90 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index be0d72cf4352..58d9ca8ac0f2 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -64,6 +64,8 @@
 #define SHA_FLAGS_ERRORBIT(23)
 #define SHA_FLAGS_PAD  BIT(24)
 #define SHA_FLAGS_RESTORE  BIT(25)
+#define SHA_FLAGS_IDATAR0  BIT(26)
+#define SHA_FLAGS_WAIT_DATARDY BIT(27)
 
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
@@ -141,6 +143,7 @@ struct atmel_sha_dev {
struct ahash_request*req;
boolis_async;
atmel_sha_fn_t  resume;
+   atmel_sha_fn_t  cpu_transfer_complete;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -1317,6 +1320,93 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
return IRQ_NONE;
 }
 
+
+/* CPU transfer functions */
+
+static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   const u32 *words = (const u32 *)ctx->buffer;
+   size_t i, num_words;
+   u32 isr, din, din_inc;
+
+   din_inc = (ctx->flags & SHA_FLAGS_IDATAR0) ? 0 : 1;
+   for (;;) {
+   /* Write data into the Input Data Registers. */
+   num_words = DIV_ROUND_UP(ctx->bufcnt, sizeof(u32));
+   for (i = 0, din = 0; i < num_words; ++i, din += din_inc)
+   atmel_sha_write(dd, SHA_REG_DIN(din), words[i]);
+
+   ctx->offset += ctx->bufcnt;
+   ctx->total -= ctx->bufcnt;
+
+   if (!ctx->total)
+   break;
+
+   /*
+* Prepare next block:
+* Fill ctx->buffer now with the next data to be written into
+* IDATARx: it gives time for the SHA hardware to process
+* the current data so the SHA_INT_DATARDY flag might be set
+* in SHA_ISR when polling this register at the beginning of
+* the next loop.
+*/
+   ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
+   scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
+ctx->offset, ctx->bufcnt, 0);
+
+   /* Wait for hardware to be ready again. */
+   isr = atmel_sha_read(dd, SHA_ISR);
+   if (!(isr & SHA_INT_DATARDY)) {
+   /* Not ready yet. */
+   dd->resume = atmel_sha_cpu_transfer;
+   atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+   return -EINPROGRESS;
+   }
+   }
+
+   if (unlikely(!(ctx->flags & SHA_FLAGS_WAIT_DATARDY)))
+   return dd->cpu_transfer_complete(dd);
+
+   return atmel_sha_wait_for_data_ready(dd, dd->cpu_transfer_complete);
+}
+
+static int atmel_sha_cpu_start(struct atmel_sha_dev *dd,
+  struct scatterlist *sg,
+  unsigned int len,
+  bool idatar0_only,
+  bool wait_data_ready,
+  atmel_sha_fn_t resume)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+
+   if (!len)
+   return resume(dd);
+
+   ctx->flags &= ~(SHA_FLAGS_IDATAR0 | SHA_FLAGS_WAIT_DATARDY);
+
+   if (idatar0_only)
+   ctx->flags |= SHA_FLAGS_IDATAR0;
+
+   if (wait_data_ready)
+   ctx->flags |= SHA_FLAGS_WAIT_DATARDY;
+
+   ctx->sg = sg;
+   ctx->total = len;
+   ctx->offset = 0;
+
+   /* Prepare the first block to be written. */
+   ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
+   scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
+ctx->offset, ctx->bufcnt, 0);
+
+   dd->cpu_transfer_complete = resume;
+   return atmel_sha_cpu_transfer(dd);
+}
+
+
 static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
 {
int i;
-- 
2.7.4

--
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 v3 03/12] crypto: atmel-sha: make atmel_sha_done_task more generic

2017-01-26 Thread Cyrille Pitchen
This patch is a transitional patch. It updates atmel_sha_done_task() to
make it more generic. Indeed, it adds a new .resume() member in the
atmel_sha_dev structure. This hook is called from atmel_sha_done_task()
to resume processing an asynchronous request.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 2dbed8bb8d26..643d79a05dda 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -138,6 +138,7 @@ struct atmel_sha_dev {
struct crypto_queue queue;
struct ahash_request*req;
boolis_async;
+   atmel_sha_fn_t  resume;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -946,6 +947,8 @@ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
return (start_async) ? ret : err;
 }
 
+static int atmel_sha_done(struct atmel_sha_dev *dd);
+
 static int atmel_sha_start(struct atmel_sha_dev *dd)
 {
struct ahash_request *req = dd->req;
@@ -960,6 +963,7 @@ static int atmel_sha_start(struct atmel_sha_dev *dd)
if (err)
goto err1;
 
+   dd->resume = atmel_sha_done;
if (ctx->op == SHA_OP_UPDATE) {
err = atmel_sha_update_req(dd);
if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
@@ -1215,13 +1219,10 @@ static void atmel_sha_queue_task(unsigned long data)
atmel_sha_handle_queue(dd, NULL);
 }
 
-static void atmel_sha_done_task(unsigned long data)
+static int atmel_sha_done(struct atmel_sha_dev *dd)
 {
-   struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
int err = 0;
 
-   dd->is_async = true;
-
if (SHA_FLAGS_CPU & dd->flags) {
if (SHA_FLAGS_OUTPUT_READY & dd->flags) {
dd->flags &= ~SHA_FLAGS_OUTPUT_READY;
@@ -1245,11 +1246,21 @@ static void atmel_sha_done_task(unsigned long data)
goto finish;
}
}
-   return;
+   return err;
 
 finish:
/* finish curent request */
atmel_sha_finish_req(dd->req, err);
+
+   return err;
+}
+
+static void atmel_sha_done_task(unsigned long data)
+{
+   struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
+
+   dd->is_async = true;
+   (void)dd->resume(dd);
 }
 
 static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
-- 
2.7.4

--
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 v3 00/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2017-01-26 Thread Cyrille Pitchen
Hi all,

this series of patches has been based and tested on next-20170125 with
CRYPTO_MANAGER_DISABLED_TESTS not set.

The series adds support to the hmac(shaX) algorithms first, then combines
both the Atmel SHA and AES hardware accelerators to implement
authenc(hmac(shaX),Y(aes)) algorithms as used by IPSEC/SSL connections.

It has also been tested with strongswan + xl2tpd to create an IPSEC+L2TP
(transport mode) VPN and strongswan only (tunnel mode) for an IPSEC VPN.

Then iperf was used to measure the bandwidth improvement in tunnel mode:

driversAES SHA SPLIP iperf half-duplex
 Mbit/s
authenc(hmac(sha1-generic),cbc(aes))SW   SW  N/A 27.7
authenc(hmac(sha1-generic),atmel-cbc-aes)   HW   SW  N/A 30.2 (mainline)
authenc(atmel-hmac-sha1,atmel-cbc-aes)  HW   HW   no 29.1
atmel-authenc-hmac-sha1-cbc-aes HW   HW  yes 38.8

SPLIP: Secure Protocol Layers Improved Performances (AES+SHA combined).

Some patches of this series are purely transitional: I've split the
modifications into many patches to ease the review.

Best regards,

Cyrille


ChangeLog:

v2 -> v3:
- add calls to memzero_explicit(, ...) before exiting from
  atmel_aes_authenc_setkey().
- add missing comparison test between req->cryptlen and authsize values
  in atmel_aes_authenc_crypt().
- remove the atmel_aes_authenc_copy_assoc() function: I have tested with
  a strongswan IPSec ESP Tunnel Mode connection and it still works even if
  this driver no longer copies the AAD. FWI, I have also tested with the
  crypto/authenc.c driver after having removed the
  crypto_authenc_copy_assoc() function and it worked as well. However I
  didn't check whether I was in the special case req->src == req->dst.

v1 -> v2:
- add missing drivers/crypto/atmel-authenc.h file in patch 11.


Cyrille Pitchen (12):
  crypto: atmel-sha: create function to get an Atmel SHA device
  crypto: atmel-sha: update request queue management to make it more
generic
  crypto: atmel-sha: make atmel_sha_done_task more generic
  crypto: atmel-sha: redefine SHA_FLAGS_SHA* flags to match
SHA_MR_ALGO_SHA*
  crypto: atmel-sha: add atmel_sha_wait_for_data_ready()
  crypto: atmel-sha: add SHA_MR_MODE_IDATAR0
  crypto: atmel-sha: add atmel_sha_cpu_start()
  crypto: atmel-sha: add simple DMA transfers
  crypto: atmel-sha: add support to hmac(shaX)
  crypto: atmel-aes: fix atmel_aes_handle_queue()
  crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes
  crypto: atmel-sha: add verbose debug facilities to print hw register
names

 drivers/crypto/Kconfig  |   12 +
 drivers/crypto/atmel-aes-regs.h |   16 +
 drivers/crypto/atmel-aes.c  |  455 -
 drivers/crypto/atmel-authenc.h  |   64 ++
 drivers/crypto/atmel-sha-regs.h |   20 +
 drivers/crypto/atmel-sha.c  | 1438 +--
 6 files changed, 1937 insertions(+), 68 deletions(-)
 create mode 100644 drivers/crypto/atmel-authenc.h

-- 
2.7.4

--
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 00/13] crypto: copy AAD during encrypt for AEAD ciphers

2017-01-20 Thread Cyrille Pitchen
Hi all,

Le 13/01/2017 à 12:39, Herbert Xu a écrit :
> On Fri, Jan 13, 2017 at 12:36:56PM +0100, Stephan Müller wrote:
>>
>> I thought I understood that you would not want to see it in any 
>> implementation. But, ok, if you want to leave it.
> 
> If you remove it from authenc then authenc will be broken.
> 

Hence if the copy of the associated data is needed in the crypto/authenc.c
driver, then I should also keep this copy in the drivers/crypto/atmel-aes.c
for authenc(hmac(shaX),cbc-aes) algorithms [1], shouldn't I?

If so, should I keep the current not optimized implementation of
atmel_aes_authenc_copy_assoc() or try to use the code extracted by Stephan
from crypto/authenc.c using the null cipher as proposed in this thread?

As said earlier in this thread, copying the associated data is not a so big
deal when compared to the main crypto processing.

For instance, with IPSec ESP with AES in CBC mode, the associated data
layout should be:
Security Parameters Index (SPI): 4 bytes
Sequence Number: 4 bytes
AES IV: 16 bytes

So it's only a 24 byte copy.

I've taken Stephan's other comments into account from his review of the
atmel-authenc driver so I'm preparing a new series but I don't know what to
do for the associated data copy.

Please let me know what you recommend, thanks!

Best regards,

Cyrille


[1] https://lkml.org/lkml/2016/12/22/306
--
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 00/13] crypto: copy AAD during encrypt for AEAD ciphers

2017-01-18 Thread Cyrille Pitchen
Hi Stephan,

this series of patches sounds like a good idea. I haven't tested it with
the Atmel AES hardware yet but I have many dummy questions:

Looking at some driver patches in the series, it seems you only add a call
to crypto_aead_copy_ad() but I don't see any removal of the previous driver
specific implementation to perform that copy.

I take the Atmel gcm(aes) driver case aside since looking at the current
code, it seems that I've forgotten to copy that assoc data from req->src
into req->dst scatter list. Then I assume that I was lucky so when I tested
with the test manager or IPSec connections, I always fell in the case where
req->src == req->dst. I thought the test manager also covered the case
req->src != req->dst but I don't remember very well and I haven't checked
recently, sorry!

Then I now look at the default drivers/gcm.c driver and, if I understand
this driver correctly, it doesn't copy the associated data from req->src
into req->dst when req->src != req->dst...
What does it mean? Did I misunderstand the gmc.c driver or is it a bug? Is
that copy the associated data needed after all?
Also looking at the drivers/authenc.c driver, this one does copy the
associated data.
So now I understand why I didn't make the copy for gcm(aes) but did it for
authenc(hmac(shaX),cbc(aes)) in atmel-aes.c: when I add new crypto
algorithms support in the Atmel drivers, I always take the crypto/*.c
drivers as reference.

So finally, what shall we do? copy or not copy? That is my question!

One last question: why do we copy those associated data only for encrypting
requests but not for decrypting requests?

The associated data might still be needed in the req->dst scatter list even
when it only refers to plain data so no other crypto operation is needed
after. However, let's take the example of an IPSec connection with ESP: the
first 8 bytes of the ESP header (4-byte SPI + 4-byte sequence number) are
used as associated data. They must be authenticated but they cannot be
ciphered as we need the plain SPI value to attach some IP packet to the
relevant IPSec session hence knowing the crypto algorithms to be used to
process the network packet.
However, once the received IPSec packet has been decrypted and
authenticated, the sequence number part the the ESP header might still be
needed in req->dst if for some reason the req->src is no longer available
when performing the anti-replay check.
Maybe the issue simply never occurs because req->src is always == req->dst
or maybe because the anti-replay check is always performed before the
crypto stuff. I dunno!

So why not copying the associated data also when processing decrypt
requests too?

Sorry for those newbie questions! I try to improve my understanding and
knowledge of the crypto subsystem and its interaction with the network
subsystem without digging too much in the source code :p

Best regards,

Cyrille

Le 10/01/2017 à 02:36, Stephan Müller a écrit :
> Hi,
> 
> to all driver maintainers: the patches I added are compile tested, but
> I do not have the hardware to verify the code. May I ask the respective
> hardware maintainers to verify that the code is appropriate and works
> as intended? Thanks a lot.
> 
> Herbert, this is my proprosal for our discussion around copying the
> AAD for algif_aead. Instead of adding the code to algif_aead and wait
> until it transpires to all cipher implementations, I thought it would
> be more helpful to fix all cipher implementations.
> 
> To do so, the AAD copy function found in authenc is extracted to a global
> service function. Furthermore, the generic AEAD TFM initialization code
> now allocates the null cipher too. This allows us now to only invoke
> the AAD copy function in the various implementations without any additional
> allocation logic.
> 
> The code for x86 and the generic code was tested with libkcapi.
> 
> The code for the drivers is compile tested for drivers applicable to
> x86 only. All others are neither compile tested nor functionally tested.
> 
> Stephan Mueller (13):
>   crypto: service function to copy AAD from src to dst
>   crypto: gcm_generic - copy AAD during encryption
>   crypto: ccm_generic - copy AAD during encryption
>   crypto: rfc4106-gcm-aesni - copy AAD during encryption
>   crypto: ccm-aes-ce - copy AAD during encryption
>   crypto: talitos - copy AAD during encryption
>   crypto: picoxcell - copy AAD during encryption
>   crypto: ixp4xx - copy AAD during encryption
>   crypto: atmel - copy AAD during encryption
>   crypto: caam - copy AAD during encryption
>   crypto: chelsio - copy AAD during encryption
>   crypto: nx - copy AAD during encryption
>   crypto: qat - copy AAD during encryption
> 
>  arch/arm64/crypto/aes-ce-ccm-glue.c  |  4 
>  arch/x86/crypto/aesni-intel_glue.c   |  5 +
>  crypto/Kconfig   |  4 ++--
>  crypto/aead.c| 36 
> ++--
>  crypto/authenc.c | 36 
> 

Re: [PATCH v2 11/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2017-01-09 Thread Cyrille Pitchen
Hi Stephan,

Le 23/12/2016 à 12:34, Stephan Müller a écrit :
> Am Donnerstag, 22. Dezember 2016, 17:38:00 CET schrieb Cyrille Pitchen:
> 
> Hi Cyrille,
> 
>> This patchs allows to combine the AES and SHA hardware accelerators on
>> some Atmel SoCs. Doing so, AES blocks are only written to/read from the
>> AES hardware. Those blocks are also transferred from the AES to the SHA
>> accelerator internally, without additionnal accesses to the system busses.
>>
>> Hence, the AES and SHA accelerators work in parallel to process all the
>> data blocks, instead of serializing the process by (de)crypting those
>> blocks first then authenticating them after like the generic
>> crypto/authenc.c driver does.
>>
>> Of course, both the AES and SHA hardware accelerators need to be available
>> before we can start to process the data blocks. Hence we use their crypto
>> request queue to synchronize both drivers.
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
>> ---
>>  drivers/crypto/Kconfig  |  12 +
>>  drivers/crypto/atmel-aes-regs.h |  16 ++
>>  drivers/crypto/atmel-aes.c  | 471
>> +++- drivers/crypto/atmel-authenc.h  | 
>> 64 ++
>>  drivers/crypto/atmel-sha-regs.h |  14 ++
>>  drivers/crypto/atmel-sha.c  | 344 +++--
>>  6 files changed, 906 insertions(+), 15 deletions(-)
>>  create mode 100644 drivers/crypto/atmel-authenc.h
>>
>> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
>> index 79564785ae30..719a868d8ea1 100644
>> --- a/drivers/crypto/Kconfig
>> +++ b/drivers/crypto/Kconfig
>> @@ -415,6 +415,18 @@ config CRYPTO_DEV_BFIN_CRC
>>Newer Blackfin processors have CRC hardware. Select this if you
>>want to use the Blackfin CRC module.
>>
>> +config CRYPTO_DEV_ATMEL_AUTHENC
>> +tristate "Support for Atmel IPSEC/SSL hw accelerator"
>> +depends on (ARCH_AT91 && HAS_DMA) || COMPILE_TEST
>> +select CRYPTO_AUTHENC
>> +select CRYPTO_DEV_ATMEL_AES
>> +select CRYPTO_DEV_ATMEL_SHA
>> +help
>> +  Some Atmel processors can combine the AES and SHA hw accelerators
>> +  to enhance support of IPSEC/SSL.
>> +  Select this if you want to use the Atmel modules for
>> +  authenc(hmac(shaX),Y(cbc)) algorithms.
>> +
>>  config CRYPTO_DEV_ATMEL_AES
>>  tristate "Support for Atmel AES hw accelerator"
>>  depends on HAS_DMA
>> diff --git a/drivers/crypto/atmel-aes-regs.h
>> b/drivers/crypto/atmel-aes-regs.h index 0ec04407b533..7694679802b3 100644
>> --- a/drivers/crypto/atmel-aes-regs.h
>> +++ b/drivers/crypto/atmel-aes-regs.h
>> @@ -68,6 +68,22 @@
>>  #define AES_CTRR0x98
>>  #define AES_GCMHR(x)(0x9c + ((x) * 0x04))
>>
>> +#define AES_EMR 0xb0
>> +#define AES_EMR_APENBIT(0)  /* Auto Padding Enable */
>> +#define AES_EMR_APM BIT(1)  /* Auto Padding Mode */
>> +#define AES_EMR_APM_IPSEC   0x0
>> +#define AES_EMR_APM_SSL BIT(1)
>> +#define AES_EMR_PLIPEN  BIT(4)  /* PLIP Enable */
>> +#define AES_EMR_PLIPD   BIT(5)  /* PLIP Decipher */
>> +#define AES_EMR_PADLEN_MASK (0xFu << 8)
>> +#define AES_EMR_PADLEN_OFFSET   8
>> +#define AES_EMR_PADLEN(padlen)  (((padlen) << AES_EMR_PADLEN_OFFSET) &\
>> + AES_EMR_PADLEN_MASK)
>> +#define AES_EMR_NHEAD_MASK  (0xFu << 16)
>> +#define AES_EMR_NHEAD_OFFSET16
>> +#define AES_EMR_NHEAD(nhead)(((nhead) << AES_EMR_NHEAD_OFFSET) &\
>> + AES_EMR_NHEAD_MASK)
>> +
>>  #define AES_TWR(x)  (0xc0 + ((x) * 0x04))
>>  #define AES_ALPHAR(x)   (0xd0 + ((x) * 0x04))
>>
>> diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
>> index 9fd2f63b8bc0..3c651e0c3113 100644
>> --- a/drivers/crypto/atmel-aes.c
>> +++ b/drivers/crypto/atmel-aes.c
>> @@ -41,6 +41,7 @@
>>  #include 
>>  #include 
>>  #include "atmel-aes-regs.h"
>> +#include "atmel-authenc.h"
>>
>>  #define ATMEL_AES_PRIORITY  300
>>
>> @@ -78,6 +79,7 @@
>>  #define AES_FLAGS_INIT  BIT(2)
>>  #define AES_FLAGS_BUSY  BIT(3)
>>  #define AES_FLAGS_DUMP_REG  BIT(4)
>> +#define AES_FLAGS_OWN_SHA   BIT(5)
>>
>>  #define AES_FLAGS_PERSISTENT(AES_FLAGS_INIT | AES_FLAGS_BUSY)
>>
>> @@ -92,6 +94,7 @@ struct atmel_aes_

[PATCH v2 00/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2016-12-22 Thread Cyrille Pitchen
Hi all,

this series of patches has been based and tested on next-20161222 with
CRYPTO_MANAGER_DISABLED_TESTS not set.

The series adds support to the hmac(shaX) algorithms first, then combines
both the Atmel SHA and AES hardware accelerators to implement
authenc(hmac(shaX),Y(aes)) algorithms as used by IPSEC/SSL connections.

It has also been tested with strongswan + xl2tpd to create an IPSEC+L2TP
(transport mode) VPN and strongswan only (tunnel mode) for an IPSEC VPN.

Then iperf was used to measure the bandwidth improvement in tunnel mode:

driversAES SHA SPLIP iperf half-duplex
 Mbit/s
authenc(hmac(sha1-generic),cbc(aes))SW   SW  N/A 27.7
authenc(hmac(sha1-generic),atmel-cbc-aes)   HW   SW  N/A 30.2 (mainline)
authenc(atmel-hmac-sha1,atmel-cbc-aes)  HW   HW   no 29.1
atmel-authenc-hmac-sha1-cbc-aes HW   HW  yes 38.8

SPLIP: Secure Protocol Layers Improved Performances (AES+SHA combined).

Some patches of this series are purely transitional: I've split the
modifications into many patches to ease the review.

Best regards,

Cyrille


ChangeLog:

v1 -> v2:
- add missing drivers/crypto/atmel-authenc.h file in patch 11.


Cyrille Pitchen (12):
  crypto: atmel-sha: create function to get an Atmel SHA device
  crypto: atmel-sha: update request queue management to make it more
generic
  crypto: atmel-sha: make atmel_sha_done_task more generic
  crypto: atmel-sha: redefine SHA_FLAGS_SHA* flags to match
SHA_MR_ALGO_SHA*
  crypto: atmel-sha: add atmel_sha_wait_for_data_ready()
  crypto: atmel-sha: add SHA_MR_MODE_IDATAR0
  crypto: atmel-sha: add atmel_sha_cpu_start()
  crypto: atmel-sha: add simple DMA transfers
  crypto: atmel-sha: add support to hmac(shaX)
  crypto: atmel-aes: fix atmel_aes_handle_queue()
  crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes
  crypto: atmel-sha: add verbose debug facilities to print hw register
names

 drivers/crypto/Kconfig  |   12 +
 drivers/crypto/atmel-aes-regs.h |   16 +
 drivers/crypto/atmel-aes.c  |  478 -
 drivers/crypto/atmel-authenc.h  |   64 ++
 drivers/crypto/atmel-sha-regs.h |   20 +
 drivers/crypto/atmel-sha.c  | 1438 +--
 6 files changed, 1960 insertions(+), 68 deletions(-)
 create mode 100644 drivers/crypto/atmel-authenc.h

-- 
2.7.4

--
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 01/12] crypto: atmel-sha: create function to get an Atmel SHA device

2016-12-22 Thread Cyrille Pitchen
This is a transitional patch: it creates the atmel_sha_find_dev() function,
which will be used in further patches to share the source code responsible
for finding a Atmel SHA device.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 97e34799e077..33a36e667547 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -260,11 +260,8 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
}
 }
 
-static int atmel_sha_init(struct ahash_request *req)
+static struct atmel_sha_dev *atmel_sha_find_dev(struct atmel_sha_ctx *tctx)
 {
-   struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-   struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
-   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
struct atmel_sha_dev *dd = NULL;
struct atmel_sha_dev *tmp;
 
@@ -281,6 +278,16 @@ static int atmel_sha_init(struct ahash_request *req)
 
spin_unlock_bh(_sha.lock);
 
+   return dd;
+}
+
+static int atmel_sha_init(struct ahash_request *req)
+{
+   struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+   struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   struct atmel_sha_dev *dd = atmel_sha_find_dev(tctx);
+
ctx->dd = dd;
 
ctx->flags = 0;
-- 
2.7.4

--
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 03/12] crypto: atmel-sha: make atmel_sha_done_task more generic

2016-12-22 Thread Cyrille Pitchen
This patch is a transitional patch. It updates atmel_sha_done_task() to
make it more generic. Indeed, it adds a new .resume() member in the
atmel_sha_dev structure. This hook is called from atmel_sha_done_task()
to resume processing an asynchronous request.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 2dbed8bb8d26..643d79a05dda 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -138,6 +138,7 @@ struct atmel_sha_dev {
struct crypto_queue queue;
struct ahash_request*req;
boolis_async;
+   atmel_sha_fn_t  resume;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -946,6 +947,8 @@ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
return (start_async) ? ret : err;
 }
 
+static int atmel_sha_done(struct atmel_sha_dev *dd);
+
 static int atmel_sha_start(struct atmel_sha_dev *dd)
 {
struct ahash_request *req = dd->req;
@@ -960,6 +963,7 @@ static int atmel_sha_start(struct atmel_sha_dev *dd)
if (err)
goto err1;
 
+   dd->resume = atmel_sha_done;
if (ctx->op == SHA_OP_UPDATE) {
err = atmel_sha_update_req(dd);
if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
@@ -1215,13 +1219,10 @@ static void atmel_sha_queue_task(unsigned long data)
atmel_sha_handle_queue(dd, NULL);
 }
 
-static void atmel_sha_done_task(unsigned long data)
+static int atmel_sha_done(struct atmel_sha_dev *dd)
 {
-   struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
int err = 0;
 
-   dd->is_async = true;
-
if (SHA_FLAGS_CPU & dd->flags) {
if (SHA_FLAGS_OUTPUT_READY & dd->flags) {
dd->flags &= ~SHA_FLAGS_OUTPUT_READY;
@@ -1245,11 +1246,21 @@ static void atmel_sha_done_task(unsigned long data)
goto finish;
}
}
-   return;
+   return err;
 
 finish:
/* finish curent request */
atmel_sha_finish_req(dd->req, err);
+
+   return err;
+}
+
+static void atmel_sha_done_task(unsigned long data)
+{
+   struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
+
+   dd->is_async = true;
+   (void)dd->resume(dd);
 }
 
 static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
-- 
2.7.4

--
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 02/12] crypto: atmel-sha: update request queue management to make it more generic

2016-12-22 Thread Cyrille Pitchen
This patch is a transitional patch. It splits the atmel_sha_handle_queue()
function. Now atmel_sha_handle_queue() only manages the request queue and
calls a new .start() hook from the atmel_sha_ctx structure.
This hook allows to implement different kind of requests still handled by
a single queue.

Also when the req parameter of atmel_sha_handle_queue() refers to the very
same request as the one returned by crypto_dequeue_request(), the queue
management now gives a chance to this crypto request to be handled
synchronously, hence reducing latencies. The .start() hook returns 0 if
the crypto request was handled synchronously and -EINPROGRESS if the
crypto request still need to be handled asynchronously.

Besides, the new .is_async member of the atmel_sha_dev structure helps
tagging this asynchronous state. Indeed, the req->base.complete() callback
should not be called if the crypto request is handled synchronously.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 74 +-
 1 file changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 33a36e667547..2dbed8bb8d26 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -105,8 +105,11 @@ struct atmel_sha_reqctx {
u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
 
+typedef int (*atmel_sha_fn_t)(struct atmel_sha_dev *);
+
 struct atmel_sha_ctx {
struct atmel_sha_dev*dd;
+   atmel_sha_fn_t  start;
 
unsigned long   flags;
 };
@@ -134,6 +137,7 @@ struct atmel_sha_dev {
unsigned long   flags;
struct crypto_queue queue;
struct ahash_request*req;
+   boolis_async;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -163,6 +167,24 @@ static inline void atmel_sha_write(struct atmel_sha_dev 
*dd,
writel_relaxed(value, dd->io_base + offset);
 }
 
+static inline int atmel_sha_complete(struct atmel_sha_dev *dd, int err)
+{
+   struct ahash_request *req = dd->req;
+
+   dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
+  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+
+   clk_disable(dd->iclk);
+
+   if (dd->is_async && req->base.complete)
+   req->base.complete(>base, err);
+
+   /* handle new request */
+   tasklet_schedule(>queue_task);
+
+   return err;
+}
+
 static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
 {
size_t count;
@@ -474,6 +496,8 @@ static void atmel_sha_dma_callback(void *data)
 {
struct atmel_sha_dev *dd = data;
 
+   dd->is_async = true;
+
/* dma_lch_in - completed - wait DATRDY */
atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
 }
@@ -509,7 +533,7 @@ static int atmel_sha_xmit_dma(struct atmel_sha_dev *dd, 
dma_addr_t dma_addr1,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
if (!in_desc)
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
 
in_desc->callback = atmel_sha_dma_callback;
in_desc->callback_param = dd;
@@ -566,7 +590,7 @@ static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
ctx->block_size);
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags &= ~SHA_FLAGS_SG;
@@ -657,7 +681,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n",
ctx->buflen + ctx->block_size);
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
if (length == 0) {
@@ -671,7 +695,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (!dma_map_sg(dd->dev, ctx->sg, 1,
DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags |= SHA_FLAGS_SG;
@@ -685,7 +709,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
 
if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   return -EINVAL;
+   atmel_sha_compl

[PATCH v2 05/12] crypto: atmel-sha: add atmel_sha_wait_for_data_ready()

2016-12-22 Thread Cyrille Pitchen
This patch simply defines a helper function to test the 'Data Ready' flag
of the Status Register. It also gives a chance for the crypto request to
be processed synchronously if this 'Data Ready' flag is already set when
polling the Status Register. Indeed, running synchronously avoid the
latency of the 'Data Ready' interrupt.

When the 'Data Ready' flag has not been set yet, we enable the associated
interrupt and resume processing the crypto request asynchronously from the
'done' task just as before.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index b29a4e5bc404..be0d72cf4352 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -434,6 +434,19 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, 
int dma)
atmel_sha_write(dd, SHA_MR, valmr);
 }
 
+static inline int atmel_sha_wait_for_data_ready(struct atmel_sha_dev *dd,
+   atmel_sha_fn_t resume)
+{
+   u32 isr = atmel_sha_read(dd, SHA_ISR);
+
+   if (unlikely(isr & SHA_INT_DATARDY))
+   return resume(dd);
+
+   dd->resume = resume;
+   atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+   return -EINPROGRESS;
+}
+
 static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf,
  size_t length, int final)
 {
-- 
2.7.4

--
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 08/12] crypto: atmel-sha: add simple DMA transfers

2016-12-22 Thread Cyrille Pitchen
This patch adds a simple function to perform data transfer with the DMA
controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 116 +
 1 file changed, 116 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 58d9ca8ac0f2..a4fc60b67099 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -123,6 +123,9 @@ struct atmel_sha_ctx {
 struct atmel_sha_dma {
struct dma_chan *chan;
struct dma_slave_config dma_conf;
+   struct scatterlist  *sg;
+   int nents;
+   unsigned intlast_sg_length;
 };
 
 struct atmel_sha_dev {
@@ -1321,6 +1324,119 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
 }
 
 
+/* DMA transfer functions */
+
+static bool atmel_sha_dma_check_aligned(struct atmel_sha_dev *dd,
+   struct scatterlist *sg,
+   size_t len)
+{
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   size_t bs = ctx->block_size;
+   int nents;
+
+   for (nents = 0; sg; sg = sg_next(sg), ++nents) {
+   if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+   return false;
+
+   /*
+* This is the last sg, the only one that is allowed to
+* have an unaligned length.
+*/
+   if (len <= sg->length) {
+   dma->nents = nents + 1;
+   dma->last_sg_length = sg->length;
+   sg->length = ALIGN(len, sizeof(u32));
+   return true;
+   }
+
+   /* All other sg lengths MUST be aligned to the block size. */
+   if (!IS_ALIGNED(sg->length, bs))
+   return false;
+
+   len -= sg->length;
+   }
+
+   return false;
+}
+
+static void atmel_sha_dma_callback2(void *data)
+{
+   struct atmel_sha_dev *dd = data;
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct scatterlist *sg;
+   int nents;
+
+   dmaengine_terminate_all(dma->chan);
+   dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+
+   sg = dma->sg;
+   for (nents = 0; nents < dma->nents - 1; ++nents)
+   sg = sg_next(sg);
+   sg->length = dma->last_sg_length;
+
+   dd->is_async = true;
+   (void)atmel_sha_wait_for_data_ready(dd, dd->resume);
+}
+
+static int atmel_sha_dma_start(struct atmel_sha_dev *dd,
+  struct scatterlist *src,
+  size_t len,
+  atmel_sha_fn_t resume)
+{
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct dma_slave_config *config = >dma_conf;
+   struct dma_chan *chan = dma->chan;
+   struct dma_async_tx_descriptor *desc;
+   dma_cookie_t cookie;
+   unsigned int sg_len;
+   int err;
+
+   dd->resume = resume;
+
+   /*
+* dma->nents has already been initialized by
+* atmel_sha_dma_check_aligned().
+*/
+   dma->sg = src;
+   sg_len = dma_map_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+   if (!sg_len) {
+   err = -ENOMEM;
+   goto exit;
+   }
+
+   config->src_maxburst = 16;
+   config->dst_maxburst = 16;
+   err = dmaengine_slave_config(chan, config);
+   if (err)
+   goto unmap_sg;
+
+   desc = dmaengine_prep_slave_sg(chan, dma->sg, sg_len, DMA_MEM_TO_DEV,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc) {
+   err = -ENOMEM;
+   goto unmap_sg;
+   }
+
+   desc->callback = atmel_sha_dma_callback2;
+   desc->callback_param = dd;
+   cookie = dmaengine_submit(desc);
+   err = dma_submit_error(cookie);
+   if (err)
+   goto unmap_sg;
+
+   dma_async_issue_pending(chan);
+
+   return -EINPROGRESS;
+
+unmap_sg:
+   dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+exit:
+   return atmel_sha_complete(dd, err);
+}
+
+
 /* CPU transfer functions */
 
 static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
-- 
2.7.4

--
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 10/12] crypto: atmel-aes: fix atmel_aes_handle_queue()

2016-12-22 Thread Cyrille Pitchen
This patch fixes the value returned by atmel_aes_handle_queue(), which
could have been wrong previously when the crypto request was started
synchronously but became asynchronous during the ctx->start() call.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 0e3d0d655b96..9fd2f63b8bc0 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -879,6 +879,7 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
struct crypto_async_request *areq, *backlog;
struct atmel_aes_base_ctx *ctx;
unsigned long flags;
+   bool start_async;
int err, ret = 0;
 
spin_lock_irqsave(>lock, flags);
@@ -904,10 +905,12 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev 
*dd,
 
dd->areq = areq;
dd->ctx = ctx;
-   dd->is_async = (areq != new_areq);
+   start_async = (areq != new_areq);
+   dd->is_async = start_async;
 
+   /* WARNING: ctx->start() MAY change dd->is_async. */
err = ctx->start(dd);
-   return (dd->is_async) ? ret : err;
+   return (start_async) ? ret : err;
 }
 
 
-- 
2.7.4

--
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 06/12] crypto: atmel-sha: add SHA_MR_MODE_IDATAR0

2016-12-22 Thread Cyrille Pitchen
This patch defines an alias macro to SHA_MR_MODE_PDC, which is not suited
for DMA usage.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index deb0b0b15096..8d62d31eda08 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -16,6 +16,7 @@
 #define SHA_MR_MODE_MANUAL 0x0
 #define SHA_MR_MODE_AUTO   0x1
 #define SHA_MR_MODE_PDC0x2
+#define SHA_MR_MODE_IDATAR00x2
 #define SHA_MR_PROCDLY (1 << 4)
 #define SHA_MR_UIHV(1 << 5)
 #define SHA_MR_UIEHV   (1 << 6)
-- 
2.7.4

--
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 12/12] crypto: atmel-sha: add verbose debug facilities to print hw register names

2016-12-22 Thread Cyrille Pitchen
When VERBOSE_DEBUG is defined and SHA_FLAGS_DUMP_REG flag is set in
dd->flags, this patch prints the register names and values when performing
IO accesses.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 110 -
 1 file changed, 108 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index cc5294dbead4..22d0c0c118da 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,6 +51,7 @@
 #define SHA_FLAGS_INIT BIT(4)
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
+#define SHA_FLAGS_DUMP_REG BIT(7)
 
 /* bits[11:8] are reserved. */
 
@@ -167,14 +168,118 @@ static struct atmel_sha_drv atmel_sha = {
.lock = __SPIN_LOCK_UNLOCKED(atmel_sha.lock),
 };
 
+#ifdef VERBOSE_DEBUG
+static const char *atmel_sha_reg_name(u32 offset, char *tmp, size_t sz, bool 
wr)
+{
+   switch (offset) {
+   case SHA_CR:
+   return "CR";
+
+   case SHA_MR:
+   return "MR";
+
+   case SHA_IER:
+   return "IER";
+
+   case SHA_IDR:
+   return "IDR";
+
+   case SHA_IMR:
+   return "IMR";
+
+   case SHA_ISR:
+   return "ISR";
+
+   case SHA_MSR:
+   return "MSR";
+
+   case SHA_BCR:
+   return "BCR";
+
+   case SHA_REG_DIN(0):
+   case SHA_REG_DIN(1):
+   case SHA_REG_DIN(2):
+   case SHA_REG_DIN(3):
+   case SHA_REG_DIN(4):
+   case SHA_REG_DIN(5):
+   case SHA_REG_DIN(6):
+   case SHA_REG_DIN(7):
+   case SHA_REG_DIN(8):
+   case SHA_REG_DIN(9):
+   case SHA_REG_DIN(10):
+   case SHA_REG_DIN(11):
+   case SHA_REG_DIN(12):
+   case SHA_REG_DIN(13):
+   case SHA_REG_DIN(14):
+   case SHA_REG_DIN(15):
+   snprintf(tmp, sz, "IDATAR[%u]", (offset - SHA_REG_DIN(0)) >> 2);
+   break;
+
+   case SHA_REG_DIGEST(0):
+   case SHA_REG_DIGEST(1):
+   case SHA_REG_DIGEST(2):
+   case SHA_REG_DIGEST(3):
+   case SHA_REG_DIGEST(4):
+   case SHA_REG_DIGEST(5):
+   case SHA_REG_DIGEST(6):
+   case SHA_REG_DIGEST(7):
+   case SHA_REG_DIGEST(8):
+   case SHA_REG_DIGEST(9):
+   case SHA_REG_DIGEST(10):
+   case SHA_REG_DIGEST(11):
+   case SHA_REG_DIGEST(12):
+   case SHA_REG_DIGEST(13):
+   case SHA_REG_DIGEST(14):
+   case SHA_REG_DIGEST(15):
+   if (wr)
+   snprintf(tmp, sz, "IDATAR[%u]",
+16u + ((offset - SHA_REG_DIGEST(0)) >> 2));
+   else
+   snprintf(tmp, sz, "ODATAR[%u]",
+(offset - SHA_REG_DIGEST(0)) >> 2);
+   break;
+
+   case SHA_HW_VERSION:
+   return "HWVER";
+
+   default:
+   snprintf(tmp, sz, "0x%02x", offset);
+   break;
+   }
+
+   return tmp;
+}
+
+#endif /* VERBOSE_DEBUG */
+
 static inline u32 atmel_sha_read(struct atmel_sha_dev *dd, u32 offset)
 {
-   return readl_relaxed(dd->io_base + offset);
+   u32 value = readl_relaxed(dd->io_base + offset);
+
+#ifdef VERBOSE_DEBUG
+   if (dd->flags & SHA_FLAGS_DUMP_REG) {
+   char tmp[16];
+
+   dev_vdbg(dd->dev, "read 0x%08x from %s\n", value,
+atmel_sha_reg_name(offset, tmp, sizeof(tmp), false));
+   }
+#endif /* VERBOSE_DEBUG */
+
+   return value;
 }
 
 static inline void atmel_sha_write(struct atmel_sha_dev *dd,
u32 offset, u32 value)
 {
+#ifdef VERBOSE_DEBUG
+   if (dd->flags & SHA_FLAGS_DUMP_REG) {
+   char tmp[16];
+
+   dev_vdbg(dd->dev, "write 0x%08x into %s\n", value,
+atmel_sha_reg_name(offset, tmp, sizeof(tmp), true));
+   }
+#endif /* VERBOSE_DEBUG */
+
writel_relaxed(value, dd->io_base + offset);
 }
 
@@ -183,7 +288,8 @@ static inline int atmel_sha_complete(struct atmel_sha_dev 
*dd, int err)
struct ahash_request *req = dd->req;
 
dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
-  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY |
+  SHA_FLAGS_DUMP_REG);
 
clk_disable(dd->iclk);
 
-- 
2.7.4

--
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 04/12] crypto: atmel-sha: redefine SHA_FLAGS_SHA* flags to match SHA_MR_ALGO_SHA*

2016-12-22 Thread Cyrille Pitchen
This patch modifies the SHA_FLAGS_SHA* flags: those algo flags are now
organized as values of a single bitfield instead of individual bits.
This allows to reduce the number of bits needed to encode all possible
values. Also the new values match the SHA_MR_ALGO_SHA* values hence
the algorithm bitfield of the SHA_MR register could simply be set with:

mr = (mr & ~SHA_FLAGS_ALGO_MASK) | (ctx->flags & SHA_FLAGS_ALGO_MASK)

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h |  1 +
 drivers/crypto/atmel-sha.c  | 45 +
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index e08897109cab..deb0b0b15096 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -19,6 +19,7 @@
 #define SHA_MR_PROCDLY (1 << 4)
 #define SHA_MR_UIHV(1 << 5)
 #define SHA_MR_UIEHV   (1 << 6)
+#define SHA_MR_ALGO_MASK   GENMASK(10, 8)
 #define SHA_MR_ALGO_SHA1   (0 << 8)
 #define SHA_MR_ALGO_SHA256 (1 << 8)
 #define SHA_MR_ALGO_SHA384 (2 << 8)
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 643d79a05dda..b29a4e5bc404 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,14 +51,16 @@
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
 
+/* bits[10:8] are reserved. */
+#define SHA_FLAGS_ALGO_MASKSHA_MR_ALGO_MASK
+#define SHA_FLAGS_SHA1 SHA_MR_ALGO_SHA1
+#define SHA_FLAGS_SHA256   SHA_MR_ALGO_SHA256
+#define SHA_FLAGS_SHA384   SHA_MR_ALGO_SHA384
+#define SHA_FLAGS_SHA512   SHA_MR_ALGO_SHA512
+#define SHA_FLAGS_SHA224   SHA_MR_ALGO_SHA224
+
 #define SHA_FLAGS_FINUPBIT(16)
 #define SHA_FLAGS_SG   BIT(17)
-#define SHA_FLAGS_ALGO_MASKGENMASK(22, 18)
-#define SHA_FLAGS_SHA1 BIT(18)
-#define SHA_FLAGS_SHA224   BIT(19)
-#define SHA_FLAGS_SHA256   BIT(20)
-#define SHA_FLAGS_SHA384   BIT(21)
-#define SHA_FLAGS_SHA512   BIT(22)
 #define SHA_FLAGS_ERRORBIT(23)
 #define SHA_FLAGS_PAD  BIT(24)
 #define SHA_FLAGS_RESTORE  BIT(25)
@@ -264,7 +266,9 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
bits[1] = cpu_to_be64(size[0] << 3);
bits[0] = cpu_to_be64(size[1] << 3 | size[0] >> 61);
 
-   if (ctx->flags & (SHA_FLAGS_SHA384 | SHA_FLAGS_SHA512)) {
+   switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+   case SHA_FLAGS_SHA384:
+   case SHA_FLAGS_SHA512:
index = ctx->bufcnt & 0x7f;
padlen = (index < 112) ? (112 - index) : ((128+112) - index);
*(ctx->buffer + ctx->bufcnt) = 0x80;
@@ -272,7 +276,9 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
ctx->bufcnt += padlen + 16;
ctx->flags |= SHA_FLAGS_PAD;
-   } else {
+   break;
+
+   default:
index = ctx->bufcnt & 0x3f;
padlen = (index < 56) ? (56 - index) : ((64+56) - index);
*(ctx->buffer + ctx->bufcnt) = 0x80;
@@ -280,6 +286,7 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
memcpy(ctx->buffer + ctx->bufcnt + padlen, [1], 8);
ctx->bufcnt += padlen + 8;
ctx->flags |= SHA_FLAGS_PAD;
+   break;
}
 }
 
@@ -828,16 +835,28 @@ static void atmel_sha_copy_ready_hash(struct 
ahash_request *req)
if (!req->result)
return;
 
-   if (ctx->flags & SHA_FLAGS_SHA1)
+   switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+   default:
+   case SHA_FLAGS_SHA1:
memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA224)
+   break;
+
+   case SHA_FLAGS_SHA224:
memcpy(req->result, ctx->digest, SHA224_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA256)
+   break;
+
+   case SHA_FLAGS_SHA256:
memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA384)
+   break;
+
+   case SHA_FLAGS_SHA384:
memcpy(req->result, ctx->digest, SHA384_DIGEST_SIZE);
-   else
+   break;
+
+   case SHA_FLAGS_SHA512:
memcpy(req->result, ctx->digest, SHA512_DIGEST_SIZE);
+   break;
+   }
 }
 
 static int atmel_sha_finish(struct ahash_request *req)
-- 
2.7.4

--
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 11/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2016-12-22 Thread Cyrille Pitchen
This patchs allows to combine the AES and SHA hardware accelerators on
some Atmel SoCs. Doing so, AES blocks are only written to/read from the
AES hardware. Those blocks are also transferred from the AES to the SHA
accelerator internally, without additionnal accesses to the system busses.

Hence, the AES and SHA accelerators work in parallel to process all the
data blocks, instead of serializing the process by (de)crypting those
blocks first then authenticating them after like the generic
crypto/authenc.c driver does.

Of course, both the AES and SHA hardware accelerators need to be available
before we can start to process the data blocks. Hence we use their crypto
request queue to synchronize both drivers.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/Kconfig  |  12 +
 drivers/crypto/atmel-aes-regs.h |  16 ++
 drivers/crypto/atmel-aes.c  | 471 +++-
 drivers/crypto/atmel-authenc.h  |  64 ++
 drivers/crypto/atmel-sha-regs.h |  14 ++
 drivers/crypto/atmel-sha.c  | 344 +++--
 6 files changed, 906 insertions(+), 15 deletions(-)
 create mode 100644 drivers/crypto/atmel-authenc.h

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 79564785ae30..719a868d8ea1 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -415,6 +415,18 @@ config CRYPTO_DEV_BFIN_CRC
  Newer Blackfin processors have CRC hardware. Select this if you
  want to use the Blackfin CRC module.
 
+config CRYPTO_DEV_ATMEL_AUTHENC
+   tristate "Support for Atmel IPSEC/SSL hw accelerator"
+   depends on (ARCH_AT91 && HAS_DMA) || COMPILE_TEST
+   select CRYPTO_AUTHENC
+   select CRYPTO_DEV_ATMEL_AES
+   select CRYPTO_DEV_ATMEL_SHA
+   help
+ Some Atmel processors can combine the AES and SHA hw accelerators
+ to enhance support of IPSEC/SSL.
+ Select this if you want to use the Atmel modules for
+ authenc(hmac(shaX),Y(cbc)) algorithms.
+
 config CRYPTO_DEV_ATMEL_AES
tristate "Support for Atmel AES hw accelerator"
depends on HAS_DMA
diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
index 0ec04407b533..7694679802b3 100644
--- a/drivers/crypto/atmel-aes-regs.h
+++ b/drivers/crypto/atmel-aes-regs.h
@@ -68,6 +68,22 @@
 #define AES_CTRR   0x98
 #define AES_GCMHR(x)   (0x9c + ((x) * 0x04))
 
+#define AES_EMR0xb0
+#define AES_EMR_APEN   BIT(0)  /* Auto Padding Enable */
+#define AES_EMR_APMBIT(1)  /* Auto Padding Mode */
+#define AES_EMR_APM_IPSEC  0x0
+#define AES_EMR_APM_SSLBIT(1)
+#define AES_EMR_PLIPEN BIT(4)  /* PLIP Enable */
+#define AES_EMR_PLIPD  BIT(5)  /* PLIP Decipher */
+#define AES_EMR_PADLEN_MASK(0xFu << 8)
+#define AES_EMR_PADLEN_OFFSET  8
+#define AES_EMR_PADLEN(padlen) (((padlen) << AES_EMR_PADLEN_OFFSET) &\
+AES_EMR_PADLEN_MASK)
+#define AES_EMR_NHEAD_MASK (0xFu << 16)
+#define AES_EMR_NHEAD_OFFSET   16
+#define AES_EMR_NHEAD(nhead)   (((nhead) << AES_EMR_NHEAD_OFFSET) &\
+AES_EMR_NHEAD_MASK)
+
 #define AES_TWR(x) (0xc0 + ((x) * 0x04))
 #define AES_ALPHAR(x)  (0xd0 + ((x) * 0x04))
 
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 9fd2f63b8bc0..3c651e0c3113 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include "atmel-aes-regs.h"
+#include "atmel-authenc.h"
 
 #define ATMEL_AES_PRIORITY 300
 
@@ -78,6 +79,7 @@
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
 #define AES_FLAGS_DUMP_REG BIT(4)
+#define AES_FLAGS_OWN_SHA  BIT(5)
 
 #define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
 
@@ -92,6 +94,7 @@ struct atmel_aes_caps {
boolhas_ctr32;
boolhas_gcm;
boolhas_xts;
+   boolhas_authenc;
u32 max_burst_size;
 };
 
@@ -144,10 +147,31 @@ struct atmel_aes_xts_ctx {
u32 key2[AES_KEYSIZE_256 / sizeof(u32)];
 };
 
+#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+struct atmel_aes_authenc_ctx {
+   struct atmel_aes_base_ctx   base;
+   struct atmel_sha_authenc_ctx*auth;
+};
+#endif
+
 struct atmel_aes_reqctx {
unsigned long   mode;
 };
 
+#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+struct atmel_aes_authenc_reqctx {
+   struct atmel_aes_reqctx base;
+
+   struct scatterlist  src[2];
+   struct scatterlist  dst[2];
+   size_t  textlen;
+   u32 digest[SHA512_DIGEST_SIZE / sizeof(u32)];
+
+   /* auth_req MUST be place last. */
+   struct ahash_requestauth_req;
+};
+

[PATCH v2 07/12] crypto: atmel-sha: add atmel_sha_cpu_start()

2016-12-22 Thread Cyrille Pitchen
This patch adds a simple function to perform data transfer with PIO, hence
handled by the CPU.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 90 ++
 1 file changed, 90 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index be0d72cf4352..58d9ca8ac0f2 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -64,6 +64,8 @@
 #define SHA_FLAGS_ERRORBIT(23)
 #define SHA_FLAGS_PAD  BIT(24)
 #define SHA_FLAGS_RESTORE  BIT(25)
+#define SHA_FLAGS_IDATAR0  BIT(26)
+#define SHA_FLAGS_WAIT_DATARDY BIT(27)
 
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
@@ -141,6 +143,7 @@ struct atmel_sha_dev {
struct ahash_request*req;
boolis_async;
atmel_sha_fn_t  resume;
+   atmel_sha_fn_t  cpu_transfer_complete;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -1317,6 +1320,93 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
return IRQ_NONE;
 }
 
+
+/* CPU transfer functions */
+
+static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   const u32 *words = (const u32 *)ctx->buffer;
+   size_t i, num_words;
+   u32 isr, din, din_inc;
+
+   din_inc = (ctx->flags & SHA_FLAGS_IDATAR0) ? 0 : 1;
+   for (;;) {
+   /* Write data into the Input Data Registers. */
+   num_words = DIV_ROUND_UP(ctx->bufcnt, sizeof(u32));
+   for (i = 0, din = 0; i < num_words; ++i, din += din_inc)
+   atmel_sha_write(dd, SHA_REG_DIN(din), words[i]);
+
+   ctx->offset += ctx->bufcnt;
+   ctx->total -= ctx->bufcnt;
+
+   if (!ctx->total)
+   break;
+
+   /*
+* Prepare next block:
+* Fill ctx->buffer now with the next data to be written into
+* IDATARx: it gives time for the SHA hardware to process
+* the current data so the SHA_INT_DATARDY flag might be set
+* in SHA_ISR when polling this register at the beginning of
+* the next loop.
+*/
+   ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
+   scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
+ctx->offset, ctx->bufcnt, 0);
+
+   /* Wait for hardware to be ready again. */
+   isr = atmel_sha_read(dd, SHA_ISR);
+   if (!(isr & SHA_INT_DATARDY)) {
+   /* Not ready yet. */
+   dd->resume = atmel_sha_cpu_transfer;
+   atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+   return -EINPROGRESS;
+   }
+   }
+
+   if (unlikely(!(ctx->flags & SHA_FLAGS_WAIT_DATARDY)))
+   return dd->cpu_transfer_complete(dd);
+
+   return atmel_sha_wait_for_data_ready(dd, dd->cpu_transfer_complete);
+}
+
+static int atmel_sha_cpu_start(struct atmel_sha_dev *dd,
+  struct scatterlist *sg,
+  unsigned int len,
+  bool idatar0_only,
+  bool wait_data_ready,
+  atmel_sha_fn_t resume)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+
+   if (!len)
+   return resume(dd);
+
+   ctx->flags &= ~(SHA_FLAGS_IDATAR0 | SHA_FLAGS_WAIT_DATARDY);
+
+   if (idatar0_only)
+   ctx->flags |= SHA_FLAGS_IDATAR0;
+
+   if (wait_data_ready)
+   ctx->flags |= SHA_FLAGS_WAIT_DATARDY;
+
+   ctx->sg = sg;
+   ctx->total = len;
+   ctx->offset = 0;
+
+   /* Prepare the first block to be written. */
+   ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
+   scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
+ctx->offset, ctx->bufcnt, 0);
+
+   dd->cpu_transfer_complete = resume;
+   return atmel_sha_cpu_transfer(dd);
+}
+
+
 static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
 {
int i;
-- 
2.7.4

--
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 09/12] crypto: atmel-sha: add support to hmac(shaX)

2016-12-22 Thread Cyrille Pitchen
This patch adds support to the hmac(shaX) algorithms.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h |   4 +
 drivers/crypto/atmel-sha.c  | 598 +++-
 2 files changed, 601 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index 8d62d31eda08..1b9f3d33079e 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -26,6 +26,7 @@
 #define SHA_MR_ALGO_SHA384 (2 << 8)
 #define SHA_MR_ALGO_SHA512 (3 << 8)
 #define SHA_MR_ALGO_SHA224 (4 << 8)
+#define SHA_MR_HMAC(1 << 11)
 #defineSHA_MR_DUALBUFF (1 << 16)
 
 #define SHA_IER0x10
@@ -42,6 +43,9 @@
 #define SHA_ISR_URAT_MR(0x2 << 12)
 #define SHA_ISR_URAT_WO(0x5 << 12)
 
+#define SHA_MSR0x20
+#define SHA_BCR0x30
+
 #defineSHA_HW_VERSION  0xFC
 
 #define SHA_TPR0x108
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index a4fc60b67099..78c3c02e4483 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,13 +51,20 @@
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
 
-/* bits[10:8] are reserved. */
+/* bits[11:8] are reserved. */
 #define SHA_FLAGS_ALGO_MASKSHA_MR_ALGO_MASK
 #define SHA_FLAGS_SHA1 SHA_MR_ALGO_SHA1
 #define SHA_FLAGS_SHA256   SHA_MR_ALGO_SHA256
 #define SHA_FLAGS_SHA384   SHA_MR_ALGO_SHA384
 #define SHA_FLAGS_SHA512   SHA_MR_ALGO_SHA512
 #define SHA_FLAGS_SHA224   SHA_MR_ALGO_SHA224
+#define SHA_FLAGS_HMAC SHA_MR_HMAC
+#define SHA_FLAGS_HMAC_SHA1(SHA_FLAGS_HMAC | SHA_FLAGS_SHA1)
+#define SHA_FLAGS_HMAC_SHA256  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA256)
+#define SHA_FLAGS_HMAC_SHA384  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA384)
+#define SHA_FLAGS_HMAC_SHA512  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA512)
+#define SHA_FLAGS_HMAC_SHA224  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA224)
+#define SHA_FLAGS_MODE_MASK(SHA_FLAGS_HMAC | SHA_FLAGS_ALGO_MASK)
 
 #define SHA_FLAGS_FINUPBIT(16)
 #define SHA_FLAGS_SG   BIT(17)
@@ -67,8 +74,10 @@
 #define SHA_FLAGS_IDATAR0  BIT(26)
 #define SHA_FLAGS_WAIT_DATARDY BIT(27)
 
+#define SHA_OP_INIT0
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
+#define SHA_OP_DIGEST  3
 
 #define SHA_BUFFER_LEN (PAGE_SIZE / 16)
 
@@ -80,6 +89,7 @@ struct atmel_sha_caps {
boolhas_sha224;
boolhas_sha_384_512;
boolhas_uihv;
+   boolhas_hmac;
 };
 
 struct atmel_sha_dev;
@@ -105,6 +115,7 @@ struct atmel_sha_reqctx {
unsigned inttotal;  /* total request */
 
size_t block_size;
+   size_t hash_size;
 
u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
@@ -152,6 +163,8 @@ struct atmel_sha_dev {
 
struct atmel_sha_caps   caps;
 
+   struct scatterlist  tmp;
+
u32 hw_version;
 };
 
@@ -1522,11 +1535,579 @@ static int atmel_sha_cpu_start(struct atmel_sha_dev 
*dd,
return atmel_sha_cpu_transfer(dd);
 }
 
+static int atmel_sha_cpu_hash(struct atmel_sha_dev *dd,
+ const void *data, unsigned int datalen,
+ bool auto_padding,
+ atmel_sha_fn_t resume)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   u32 msglen = (auto_padding) ? datalen : 0;
+   u32 mr = SHA_MR_MODE_AUTO;
+
+   if (!(IS_ALIGNED(datalen, ctx->block_size) || auto_padding))
+   return atmel_sha_complete(dd, -EINVAL);
+
+   mr |= (ctx->flags & SHA_FLAGS_ALGO_MASK);
+   atmel_sha_write(dd, SHA_MR, mr);
+   atmel_sha_write(dd, SHA_MSR, msglen);
+   atmel_sha_write(dd, SHA_BCR, msglen);
+   atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST);
+
+   sg_init_one(>tmp, data, datalen);
+   return atmel_sha_cpu_start(dd, >tmp, datalen, false, true, resume);
+}
+
+
+/* hmac functions */
+
+struct atmel_sha_hmac_key {
+   boolvalid;
+   unsigned intkeylen;
+   u8  buffer[SHA512_BLOCK_SIZE];
+   u8  *keydup;
+};
+
+static inline void atmel_sha_hmac_key_init(struct atmel_sha_hmac_key *hkey)
+{
+   memset(hkey, 0, sizeof(*hkey));
+}
+
+static inline void atmel_sha_hmac_key_release(struct atmel_sha_hmac_key *hkey)
+{
+   kfree(hkey->keydup);
+   memset(hkey, 0, sizeof(*hkey));
+}
+
+static inline int atmel_sha_hmac_key_set(struct atmel_sha_hmac_key *hkey,
+const u8 *key,
+

[PATCH 05/12] crypto: atmel-sha: add atmel_sha_wait_for_data_ready()

2016-12-22 Thread Cyrille Pitchen
This patch simply defines a helper function to test the 'Data Ready' flag
of the Status Register. It also gives a chance for the crypto request to
be processed synchronously if this 'Data Ready' flag is already set when
polling the Status Register. Indeed, running synchronously avoid the
latency of the 'Data Ready' interrupt.

When the 'Data Ready' flag has not been set yet, we enable the associated
interrupt and resume processing the crypto request asynchronously from the
'done' task just as before.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index b29a4e5bc404..be0d72cf4352 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -434,6 +434,19 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, 
int dma)
atmel_sha_write(dd, SHA_MR, valmr);
 }
 
+static inline int atmel_sha_wait_for_data_ready(struct atmel_sha_dev *dd,
+   atmel_sha_fn_t resume)
+{
+   u32 isr = atmel_sha_read(dd, SHA_ISR);
+
+   if (unlikely(isr & SHA_INT_DATARDY))
+   return resume(dd);
+
+   dd->resume = resume;
+   atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+   return -EINPROGRESS;
+}
+
 static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf,
  size_t length, int final)
 {
-- 
2.7.4

--
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 01/12] crypto: atmel-sha: create function to get an Atmel SHA device

2016-12-22 Thread Cyrille Pitchen
This is a transitional patch: it creates the atmel_sha_find_dev() function,
which will be used in further patches to share the source code responsible
for finding a Atmel SHA device.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 97e34799e077..33a36e667547 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -260,11 +260,8 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
}
 }
 
-static int atmel_sha_init(struct ahash_request *req)
+static struct atmel_sha_dev *atmel_sha_find_dev(struct atmel_sha_ctx *tctx)
 {
-   struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-   struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
-   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
struct atmel_sha_dev *dd = NULL;
struct atmel_sha_dev *tmp;
 
@@ -281,6 +278,16 @@ static int atmel_sha_init(struct ahash_request *req)
 
spin_unlock_bh(_sha.lock);
 
+   return dd;
+}
+
+static int atmel_sha_init(struct ahash_request *req)
+{
+   struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+   struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   struct atmel_sha_dev *dd = atmel_sha_find_dev(tctx);
+
ctx->dd = dd;
 
ctx->flags = 0;
-- 
2.7.4

--
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 11/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2016-12-22 Thread Cyrille Pitchen
This patchs allows to combine the AES and SHA hardware accelerators on
some Atmel SoCs. Doing so, AES blocks are only written to/read from the
AES hardware. Those blocks are also transferred from the AES to the SHA
accelerator internally, without additionnal accesses to the system busses.

Hence, the AES and SHA accelerators work in parallel to process all the
data blocks, instead of serializing the process by (de)crypting those
blocks first then authenticating them after like the generic
crypto/authenc.c driver does.

Of course, both the AES and SHA hardware accelerators need to be available
before we can start to process the data blocks. Hence we use their crypto
request queue to synchronize both drivers.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/Kconfig  |  12 +
 drivers/crypto/atmel-aes-regs.h |  16 ++
 drivers/crypto/atmel-aes.c  | 471 +++-
 drivers/crypto/atmel-sha-regs.h |  14 ++
 drivers/crypto/atmel-sha.c  | 344 +++--
 5 files changed, 842 insertions(+), 15 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 79564785ae30..719a868d8ea1 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -415,6 +415,18 @@ config CRYPTO_DEV_BFIN_CRC
  Newer Blackfin processors have CRC hardware. Select this if you
  want to use the Blackfin CRC module.
 
+config CRYPTO_DEV_ATMEL_AUTHENC
+   tristate "Support for Atmel IPSEC/SSL hw accelerator"
+   depends on (ARCH_AT91 && HAS_DMA) || COMPILE_TEST
+   select CRYPTO_AUTHENC
+   select CRYPTO_DEV_ATMEL_AES
+   select CRYPTO_DEV_ATMEL_SHA
+   help
+ Some Atmel processors can combine the AES and SHA hw accelerators
+ to enhance support of IPSEC/SSL.
+ Select this if you want to use the Atmel modules for
+ authenc(hmac(shaX),Y(cbc)) algorithms.
+
 config CRYPTO_DEV_ATMEL_AES
tristate "Support for Atmel AES hw accelerator"
depends on HAS_DMA
diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
index 0ec04407b533..7694679802b3 100644
--- a/drivers/crypto/atmel-aes-regs.h
+++ b/drivers/crypto/atmel-aes-regs.h
@@ -68,6 +68,22 @@
 #define AES_CTRR   0x98
 #define AES_GCMHR(x)   (0x9c + ((x) * 0x04))
 
+#define AES_EMR0xb0
+#define AES_EMR_APEN   BIT(0)  /* Auto Padding Enable */
+#define AES_EMR_APMBIT(1)  /* Auto Padding Mode */
+#define AES_EMR_APM_IPSEC  0x0
+#define AES_EMR_APM_SSLBIT(1)
+#define AES_EMR_PLIPEN BIT(4)  /* PLIP Enable */
+#define AES_EMR_PLIPD  BIT(5)  /* PLIP Decipher */
+#define AES_EMR_PADLEN_MASK(0xFu << 8)
+#define AES_EMR_PADLEN_OFFSET  8
+#define AES_EMR_PADLEN(padlen) (((padlen) << AES_EMR_PADLEN_OFFSET) &\
+AES_EMR_PADLEN_MASK)
+#define AES_EMR_NHEAD_MASK (0xFu << 16)
+#define AES_EMR_NHEAD_OFFSET   16
+#define AES_EMR_NHEAD(nhead)   (((nhead) << AES_EMR_NHEAD_OFFSET) &\
+AES_EMR_NHEAD_MASK)
+
 #define AES_TWR(x) (0xc0 + ((x) * 0x04))
 #define AES_ALPHAR(x)  (0xd0 + ((x) * 0x04))
 
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 9fd2f63b8bc0..3c651e0c3113 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include "atmel-aes-regs.h"
+#include "atmel-authenc.h"
 
 #define ATMEL_AES_PRIORITY 300
 
@@ -78,6 +79,7 @@
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
 #define AES_FLAGS_DUMP_REG BIT(4)
+#define AES_FLAGS_OWN_SHA  BIT(5)
 
 #define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
 
@@ -92,6 +94,7 @@ struct atmel_aes_caps {
boolhas_ctr32;
boolhas_gcm;
boolhas_xts;
+   boolhas_authenc;
u32 max_burst_size;
 };
 
@@ -144,10 +147,31 @@ struct atmel_aes_xts_ctx {
u32 key2[AES_KEYSIZE_256 / sizeof(u32)];
 };
 
+#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+struct atmel_aes_authenc_ctx {
+   struct atmel_aes_base_ctx   base;
+   struct atmel_sha_authenc_ctx*auth;
+};
+#endif
+
 struct atmel_aes_reqctx {
unsigned long   mode;
 };
 
+#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+struct atmel_aes_authenc_reqctx {
+   struct atmel_aes_reqctx base;
+
+   struct scatterlist  src[2];
+   struct scatterlist  dst[2];
+   size_t  textlen;
+   u32 digest[SHA512_DIGEST_SIZE / sizeof(u32)];
+
+   /* auth_req MUST be place last. */
+   struct ahash_requestauth_req;
+};
+#endif
+
 struct atmel_aes_dma {
struct dma_chan *chan;
struct scatterlis

[PATCH 03/12] crypto: atmel-sha: make atmel_sha_done_task more generic

2016-12-22 Thread Cyrille Pitchen
This patch is a transitional patch. It updates atmel_sha_done_task() to
make it more generic. Indeed, it adds a new .resume() member in the
atmel_sha_dev structure. This hook is called from atmel_sha_done_task()
to resume processing an asynchronous request.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 2dbed8bb8d26..643d79a05dda 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -138,6 +138,7 @@ struct atmel_sha_dev {
struct crypto_queue queue;
struct ahash_request*req;
boolis_async;
+   atmel_sha_fn_t  resume;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -946,6 +947,8 @@ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
return (start_async) ? ret : err;
 }
 
+static int atmel_sha_done(struct atmel_sha_dev *dd);
+
 static int atmel_sha_start(struct atmel_sha_dev *dd)
 {
struct ahash_request *req = dd->req;
@@ -960,6 +963,7 @@ static int atmel_sha_start(struct atmel_sha_dev *dd)
if (err)
goto err1;
 
+   dd->resume = atmel_sha_done;
if (ctx->op == SHA_OP_UPDATE) {
err = atmel_sha_update_req(dd);
if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
@@ -1215,13 +1219,10 @@ static void atmel_sha_queue_task(unsigned long data)
atmel_sha_handle_queue(dd, NULL);
 }
 
-static void atmel_sha_done_task(unsigned long data)
+static int atmel_sha_done(struct atmel_sha_dev *dd)
 {
-   struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
int err = 0;
 
-   dd->is_async = true;
-
if (SHA_FLAGS_CPU & dd->flags) {
if (SHA_FLAGS_OUTPUT_READY & dd->flags) {
dd->flags &= ~SHA_FLAGS_OUTPUT_READY;
@@ -1245,11 +1246,21 @@ static void atmel_sha_done_task(unsigned long data)
goto finish;
}
}
-   return;
+   return err;
 
 finish:
/* finish curent request */
atmel_sha_finish_req(dd->req, err);
+
+   return err;
+}
+
+static void atmel_sha_done_task(unsigned long data)
+{
+   struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
+
+   dd->is_async = true;
+   (void)dd->resume(dd);
 }
 
 static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
-- 
2.7.4

--
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 10/12] crypto: atmel-aes: fix atmel_aes_handle_queue()

2016-12-22 Thread Cyrille Pitchen
This patch fixes the value returned by atmel_aes_handle_queue(), which
could have been wrong previously when the crypto request was started
synchronously but became asynchronous during the ctx->start() call.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 0e3d0d655b96..9fd2f63b8bc0 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -879,6 +879,7 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
struct crypto_async_request *areq, *backlog;
struct atmel_aes_base_ctx *ctx;
unsigned long flags;
+   bool start_async;
int err, ret = 0;
 
spin_lock_irqsave(>lock, flags);
@@ -904,10 +905,12 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev 
*dd,
 
dd->areq = areq;
dd->ctx = ctx;
-   dd->is_async = (areq != new_areq);
+   start_async = (areq != new_areq);
+   dd->is_async = start_async;
 
+   /* WARNING: ctx->start() MAY change dd->is_async. */
err = ctx->start(dd);
-   return (dd->is_async) ? ret : err;
+   return (start_async) ? ret : err;
 }
 
 
-- 
2.7.4

--
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 12/12] crypto: atmel-sha: add verbose debug facilities to print hw register names

2016-12-22 Thread Cyrille Pitchen
When VERBOSE_DEBUG is defined and SHA_FLAGS_DUMP_REG flag is set in
dd->flags, this patch prints the register names and values when performing
IO accesses.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 110 -
 1 file changed, 108 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index cc5294dbead4..22d0c0c118da 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,6 +51,7 @@
 #define SHA_FLAGS_INIT BIT(4)
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
+#define SHA_FLAGS_DUMP_REG BIT(7)
 
 /* bits[11:8] are reserved. */
 
@@ -167,14 +168,118 @@ static struct atmel_sha_drv atmel_sha = {
.lock = __SPIN_LOCK_UNLOCKED(atmel_sha.lock),
 };
 
+#ifdef VERBOSE_DEBUG
+static const char *atmel_sha_reg_name(u32 offset, char *tmp, size_t sz, bool 
wr)
+{
+   switch (offset) {
+   case SHA_CR:
+   return "CR";
+
+   case SHA_MR:
+   return "MR";
+
+   case SHA_IER:
+   return "IER";
+
+   case SHA_IDR:
+   return "IDR";
+
+   case SHA_IMR:
+   return "IMR";
+
+   case SHA_ISR:
+   return "ISR";
+
+   case SHA_MSR:
+   return "MSR";
+
+   case SHA_BCR:
+   return "BCR";
+
+   case SHA_REG_DIN(0):
+   case SHA_REG_DIN(1):
+   case SHA_REG_DIN(2):
+   case SHA_REG_DIN(3):
+   case SHA_REG_DIN(4):
+   case SHA_REG_DIN(5):
+   case SHA_REG_DIN(6):
+   case SHA_REG_DIN(7):
+   case SHA_REG_DIN(8):
+   case SHA_REG_DIN(9):
+   case SHA_REG_DIN(10):
+   case SHA_REG_DIN(11):
+   case SHA_REG_DIN(12):
+   case SHA_REG_DIN(13):
+   case SHA_REG_DIN(14):
+   case SHA_REG_DIN(15):
+   snprintf(tmp, sz, "IDATAR[%u]", (offset - SHA_REG_DIN(0)) >> 2);
+   break;
+
+   case SHA_REG_DIGEST(0):
+   case SHA_REG_DIGEST(1):
+   case SHA_REG_DIGEST(2):
+   case SHA_REG_DIGEST(3):
+   case SHA_REG_DIGEST(4):
+   case SHA_REG_DIGEST(5):
+   case SHA_REG_DIGEST(6):
+   case SHA_REG_DIGEST(7):
+   case SHA_REG_DIGEST(8):
+   case SHA_REG_DIGEST(9):
+   case SHA_REG_DIGEST(10):
+   case SHA_REG_DIGEST(11):
+   case SHA_REG_DIGEST(12):
+   case SHA_REG_DIGEST(13):
+   case SHA_REG_DIGEST(14):
+   case SHA_REG_DIGEST(15):
+   if (wr)
+   snprintf(tmp, sz, "IDATAR[%u]",
+16u + ((offset - SHA_REG_DIGEST(0)) >> 2));
+   else
+   snprintf(tmp, sz, "ODATAR[%u]",
+(offset - SHA_REG_DIGEST(0)) >> 2);
+   break;
+
+   case SHA_HW_VERSION:
+   return "HWVER";
+
+   default:
+   snprintf(tmp, sz, "0x%02x", offset);
+   break;
+   }
+
+   return tmp;
+}
+
+#endif /* VERBOSE_DEBUG */
+
 static inline u32 atmel_sha_read(struct atmel_sha_dev *dd, u32 offset)
 {
-   return readl_relaxed(dd->io_base + offset);
+   u32 value = readl_relaxed(dd->io_base + offset);
+
+#ifdef VERBOSE_DEBUG
+   if (dd->flags & SHA_FLAGS_DUMP_REG) {
+   char tmp[16];
+
+   dev_vdbg(dd->dev, "read 0x%08x from %s\n", value,
+atmel_sha_reg_name(offset, tmp, sizeof(tmp), false));
+   }
+#endif /* VERBOSE_DEBUG */
+
+   return value;
 }
 
 static inline void atmel_sha_write(struct atmel_sha_dev *dd,
u32 offset, u32 value)
 {
+#ifdef VERBOSE_DEBUG
+   if (dd->flags & SHA_FLAGS_DUMP_REG) {
+   char tmp[16];
+
+   dev_vdbg(dd->dev, "write 0x%08x into %s\n", value,
+atmel_sha_reg_name(offset, tmp, sizeof(tmp), true));
+   }
+#endif /* VERBOSE_DEBUG */
+
writel_relaxed(value, dd->io_base + offset);
 }
 
@@ -183,7 +288,8 @@ static inline int atmel_sha_complete(struct atmel_sha_dev 
*dd, int err)
struct ahash_request *req = dd->req;
 
dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
-  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY |
+  SHA_FLAGS_DUMP_REG);
 
clk_disable(dd->iclk);
 
-- 
2.7.4

--
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 07/12] crypto: atmel-sha: add atmel_sha_cpu_start()

2016-12-22 Thread Cyrille Pitchen
This patch adds a simple function to perform data transfer with PIO, hence
handled by the CPU.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 90 ++
 1 file changed, 90 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index be0d72cf4352..58d9ca8ac0f2 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -64,6 +64,8 @@
 #define SHA_FLAGS_ERRORBIT(23)
 #define SHA_FLAGS_PAD  BIT(24)
 #define SHA_FLAGS_RESTORE  BIT(25)
+#define SHA_FLAGS_IDATAR0  BIT(26)
+#define SHA_FLAGS_WAIT_DATARDY BIT(27)
 
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
@@ -141,6 +143,7 @@ struct atmel_sha_dev {
struct ahash_request*req;
boolis_async;
atmel_sha_fn_t  resume;
+   atmel_sha_fn_t  cpu_transfer_complete;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -1317,6 +1320,93 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
return IRQ_NONE;
 }
 
+
+/* CPU transfer functions */
+
+static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   const u32 *words = (const u32 *)ctx->buffer;
+   size_t i, num_words;
+   u32 isr, din, din_inc;
+
+   din_inc = (ctx->flags & SHA_FLAGS_IDATAR0) ? 0 : 1;
+   for (;;) {
+   /* Write data into the Input Data Registers. */
+   num_words = DIV_ROUND_UP(ctx->bufcnt, sizeof(u32));
+   for (i = 0, din = 0; i < num_words; ++i, din += din_inc)
+   atmel_sha_write(dd, SHA_REG_DIN(din), words[i]);
+
+   ctx->offset += ctx->bufcnt;
+   ctx->total -= ctx->bufcnt;
+
+   if (!ctx->total)
+   break;
+
+   /*
+* Prepare next block:
+* Fill ctx->buffer now with the next data to be written into
+* IDATARx: it gives time for the SHA hardware to process
+* the current data so the SHA_INT_DATARDY flag might be set
+* in SHA_ISR when polling this register at the beginning of
+* the next loop.
+*/
+   ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
+   scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
+ctx->offset, ctx->bufcnt, 0);
+
+   /* Wait for hardware to be ready again. */
+   isr = atmel_sha_read(dd, SHA_ISR);
+   if (!(isr & SHA_INT_DATARDY)) {
+   /* Not ready yet. */
+   dd->resume = atmel_sha_cpu_transfer;
+   atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
+   return -EINPROGRESS;
+   }
+   }
+
+   if (unlikely(!(ctx->flags & SHA_FLAGS_WAIT_DATARDY)))
+   return dd->cpu_transfer_complete(dd);
+
+   return atmel_sha_wait_for_data_ready(dd, dd->cpu_transfer_complete);
+}
+
+static int atmel_sha_cpu_start(struct atmel_sha_dev *dd,
+  struct scatterlist *sg,
+  unsigned int len,
+  bool idatar0_only,
+  bool wait_data_ready,
+  atmel_sha_fn_t resume)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+
+   if (!len)
+   return resume(dd);
+
+   ctx->flags &= ~(SHA_FLAGS_IDATAR0 | SHA_FLAGS_WAIT_DATARDY);
+
+   if (idatar0_only)
+   ctx->flags |= SHA_FLAGS_IDATAR0;
+
+   if (wait_data_ready)
+   ctx->flags |= SHA_FLAGS_WAIT_DATARDY;
+
+   ctx->sg = sg;
+   ctx->total = len;
+   ctx->offset = 0;
+
+   /* Prepare the first block to be written. */
+   ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
+   scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
+ctx->offset, ctx->bufcnt, 0);
+
+   dd->cpu_transfer_complete = resume;
+   return atmel_sha_cpu_transfer(dd);
+}
+
+
 static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
 {
int i;
-- 
2.7.4

--
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 04/12] crypto: atmel-sha: redefine SHA_FLAGS_SHA* flags to match SHA_MR_ALGO_SHA*

2016-12-22 Thread Cyrille Pitchen
This patch modifies the SHA_FLAGS_SHA* flags: those algo flags are now
organized as values of a single bitfield instead of individual bits.
This allows to reduce the number of bits needed to encode all possible
values. Also the new values match the SHA_MR_ALGO_SHA* values hence
the algorithm bitfield of the SHA_MR register could simply be set with:

mr = (mr & ~SHA_FLAGS_ALGO_MASK) | (ctx->flags & SHA_FLAGS_ALGO_MASK)

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h |  1 +
 drivers/crypto/atmel-sha.c  | 45 +
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index e08897109cab..deb0b0b15096 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -19,6 +19,7 @@
 #define SHA_MR_PROCDLY (1 << 4)
 #define SHA_MR_UIHV(1 << 5)
 #define SHA_MR_UIEHV   (1 << 6)
+#define SHA_MR_ALGO_MASK   GENMASK(10, 8)
 #define SHA_MR_ALGO_SHA1   (0 << 8)
 #define SHA_MR_ALGO_SHA256 (1 << 8)
 #define SHA_MR_ALGO_SHA384 (2 << 8)
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 643d79a05dda..b29a4e5bc404 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,14 +51,16 @@
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
 
+/* bits[10:8] are reserved. */
+#define SHA_FLAGS_ALGO_MASKSHA_MR_ALGO_MASK
+#define SHA_FLAGS_SHA1 SHA_MR_ALGO_SHA1
+#define SHA_FLAGS_SHA256   SHA_MR_ALGO_SHA256
+#define SHA_FLAGS_SHA384   SHA_MR_ALGO_SHA384
+#define SHA_FLAGS_SHA512   SHA_MR_ALGO_SHA512
+#define SHA_FLAGS_SHA224   SHA_MR_ALGO_SHA224
+
 #define SHA_FLAGS_FINUPBIT(16)
 #define SHA_FLAGS_SG   BIT(17)
-#define SHA_FLAGS_ALGO_MASKGENMASK(22, 18)
-#define SHA_FLAGS_SHA1 BIT(18)
-#define SHA_FLAGS_SHA224   BIT(19)
-#define SHA_FLAGS_SHA256   BIT(20)
-#define SHA_FLAGS_SHA384   BIT(21)
-#define SHA_FLAGS_SHA512   BIT(22)
 #define SHA_FLAGS_ERRORBIT(23)
 #define SHA_FLAGS_PAD  BIT(24)
 #define SHA_FLAGS_RESTORE  BIT(25)
@@ -264,7 +266,9 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
bits[1] = cpu_to_be64(size[0] << 3);
bits[0] = cpu_to_be64(size[1] << 3 | size[0] >> 61);
 
-   if (ctx->flags & (SHA_FLAGS_SHA384 | SHA_FLAGS_SHA512)) {
+   switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+   case SHA_FLAGS_SHA384:
+   case SHA_FLAGS_SHA512:
index = ctx->bufcnt & 0x7f;
padlen = (index < 112) ? (112 - index) : ((128+112) - index);
*(ctx->buffer + ctx->bufcnt) = 0x80;
@@ -272,7 +276,9 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
ctx->bufcnt += padlen + 16;
ctx->flags |= SHA_FLAGS_PAD;
-   } else {
+   break;
+
+   default:
index = ctx->bufcnt & 0x3f;
padlen = (index < 56) ? (56 - index) : ((64+56) - index);
*(ctx->buffer + ctx->bufcnt) = 0x80;
@@ -280,6 +286,7 @@ static void atmel_sha_fill_padding(struct atmel_sha_reqctx 
*ctx, int length)
memcpy(ctx->buffer + ctx->bufcnt + padlen, [1], 8);
ctx->bufcnt += padlen + 8;
ctx->flags |= SHA_FLAGS_PAD;
+   break;
}
 }
 
@@ -828,16 +835,28 @@ static void atmel_sha_copy_ready_hash(struct 
ahash_request *req)
if (!req->result)
return;
 
-   if (ctx->flags & SHA_FLAGS_SHA1)
+   switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+   default:
+   case SHA_FLAGS_SHA1:
memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA224)
+   break;
+
+   case SHA_FLAGS_SHA224:
memcpy(req->result, ctx->digest, SHA224_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA256)
+   break;
+
+   case SHA_FLAGS_SHA256:
memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE);
-   else if (ctx->flags & SHA_FLAGS_SHA384)
+   break;
+
+   case SHA_FLAGS_SHA384:
memcpy(req->result, ctx->digest, SHA384_DIGEST_SIZE);
-   else
+   break;
+
+   case SHA_FLAGS_SHA512:
memcpy(req->result, ctx->digest, SHA512_DIGEST_SIZE);
+   break;
+   }
 }
 
 static int atmel_sha_finish(struct ahash_request *req)
-- 
2.7.4

--
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 06/12] crypto: atmel-sha: add SHA_MR_MODE_IDATAR0

2016-12-22 Thread Cyrille Pitchen
This patch defines an alias macro to SHA_MR_MODE_PDC, which is not suited
for DMA usage.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index deb0b0b15096..8d62d31eda08 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -16,6 +16,7 @@
 #define SHA_MR_MODE_MANUAL 0x0
 #define SHA_MR_MODE_AUTO   0x1
 #define SHA_MR_MODE_PDC0x2
+#define SHA_MR_MODE_IDATAR00x2
 #define SHA_MR_PROCDLY (1 << 4)
 #define SHA_MR_UIHV(1 << 5)
 #define SHA_MR_UIEHV   (1 << 6)
-- 
2.7.4

--
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 09/12] crypto: atmel-sha: add support to hmac(shaX)

2016-12-22 Thread Cyrille Pitchen
This patch adds support to the hmac(shaX) algorithms.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha-regs.h |   4 +
 drivers/crypto/atmel-sha.c  | 598 +++-
 2 files changed, 601 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
index 8d62d31eda08..1b9f3d33079e 100644
--- a/drivers/crypto/atmel-sha-regs.h
+++ b/drivers/crypto/atmel-sha-regs.h
@@ -26,6 +26,7 @@
 #define SHA_MR_ALGO_SHA384 (2 << 8)
 #define SHA_MR_ALGO_SHA512 (3 << 8)
 #define SHA_MR_ALGO_SHA224 (4 << 8)
+#define SHA_MR_HMAC(1 << 11)
 #defineSHA_MR_DUALBUFF (1 << 16)
 
 #define SHA_IER0x10
@@ -42,6 +43,9 @@
 #define SHA_ISR_URAT_MR(0x2 << 12)
 #define SHA_ISR_URAT_WO(0x5 << 12)
 
+#define SHA_MSR0x20
+#define SHA_BCR0x30
+
 #defineSHA_HW_VERSION  0xFC
 
 #define SHA_TPR0x108
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index a4fc60b67099..78c3c02e4483 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -51,13 +51,20 @@
 #define SHA_FLAGS_CPU  BIT(5)
 #define SHA_FLAGS_DMA_READYBIT(6)
 
-/* bits[10:8] are reserved. */
+/* bits[11:8] are reserved. */
 #define SHA_FLAGS_ALGO_MASKSHA_MR_ALGO_MASK
 #define SHA_FLAGS_SHA1 SHA_MR_ALGO_SHA1
 #define SHA_FLAGS_SHA256   SHA_MR_ALGO_SHA256
 #define SHA_FLAGS_SHA384   SHA_MR_ALGO_SHA384
 #define SHA_FLAGS_SHA512   SHA_MR_ALGO_SHA512
 #define SHA_FLAGS_SHA224   SHA_MR_ALGO_SHA224
+#define SHA_FLAGS_HMAC SHA_MR_HMAC
+#define SHA_FLAGS_HMAC_SHA1(SHA_FLAGS_HMAC | SHA_FLAGS_SHA1)
+#define SHA_FLAGS_HMAC_SHA256  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA256)
+#define SHA_FLAGS_HMAC_SHA384  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA384)
+#define SHA_FLAGS_HMAC_SHA512  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA512)
+#define SHA_FLAGS_HMAC_SHA224  (SHA_FLAGS_HMAC | SHA_FLAGS_SHA224)
+#define SHA_FLAGS_MODE_MASK(SHA_FLAGS_HMAC | SHA_FLAGS_ALGO_MASK)
 
 #define SHA_FLAGS_FINUPBIT(16)
 #define SHA_FLAGS_SG   BIT(17)
@@ -67,8 +74,10 @@
 #define SHA_FLAGS_IDATAR0  BIT(26)
 #define SHA_FLAGS_WAIT_DATARDY BIT(27)
 
+#define SHA_OP_INIT0
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
+#define SHA_OP_DIGEST  3
 
 #define SHA_BUFFER_LEN (PAGE_SIZE / 16)
 
@@ -80,6 +89,7 @@ struct atmel_sha_caps {
boolhas_sha224;
boolhas_sha_384_512;
boolhas_uihv;
+   boolhas_hmac;
 };
 
 struct atmel_sha_dev;
@@ -105,6 +115,7 @@ struct atmel_sha_reqctx {
unsigned inttotal;  /* total request */
 
size_t block_size;
+   size_t hash_size;
 
u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
@@ -152,6 +163,8 @@ struct atmel_sha_dev {
 
struct atmel_sha_caps   caps;
 
+   struct scatterlist  tmp;
+
u32 hw_version;
 };
 
@@ -1522,11 +1535,579 @@ static int atmel_sha_cpu_start(struct atmel_sha_dev 
*dd,
return atmel_sha_cpu_transfer(dd);
 }
 
+static int atmel_sha_cpu_hash(struct atmel_sha_dev *dd,
+ const void *data, unsigned int datalen,
+ bool auto_padding,
+ atmel_sha_fn_t resume)
+{
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   u32 msglen = (auto_padding) ? datalen : 0;
+   u32 mr = SHA_MR_MODE_AUTO;
+
+   if (!(IS_ALIGNED(datalen, ctx->block_size) || auto_padding))
+   return atmel_sha_complete(dd, -EINVAL);
+
+   mr |= (ctx->flags & SHA_FLAGS_ALGO_MASK);
+   atmel_sha_write(dd, SHA_MR, mr);
+   atmel_sha_write(dd, SHA_MSR, msglen);
+   atmel_sha_write(dd, SHA_BCR, msglen);
+   atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST);
+
+   sg_init_one(>tmp, data, datalen);
+   return atmel_sha_cpu_start(dd, >tmp, datalen, false, true, resume);
+}
+
+
+/* hmac functions */
+
+struct atmel_sha_hmac_key {
+   boolvalid;
+   unsigned intkeylen;
+   u8  buffer[SHA512_BLOCK_SIZE];
+   u8  *keydup;
+};
+
+static inline void atmel_sha_hmac_key_init(struct atmel_sha_hmac_key *hkey)
+{
+   memset(hkey, 0, sizeof(*hkey));
+}
+
+static inline void atmel_sha_hmac_key_release(struct atmel_sha_hmac_key *hkey)
+{
+   kfree(hkey->keydup);
+   memset(hkey, 0, sizeof(*hkey));
+}
+
+static inline int atmel_sha_hmac_key_set(struct atmel_sha_hmac_key *hkey,
+const u8 *key,
+

[PATCH 08/12] crypto: atmel-sha: add simple DMA transfers

2016-12-22 Thread Cyrille Pitchen
This patch adds a simple function to perform data transfer with the DMA
controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 116 +
 1 file changed, 116 insertions(+)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 58d9ca8ac0f2..a4fc60b67099 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -123,6 +123,9 @@ struct atmel_sha_ctx {
 struct atmel_sha_dma {
struct dma_chan *chan;
struct dma_slave_config dma_conf;
+   struct scatterlist  *sg;
+   int nents;
+   unsigned intlast_sg_length;
 };
 
 struct atmel_sha_dev {
@@ -1321,6 +1324,119 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
 }
 
 
+/* DMA transfer functions */
+
+static bool atmel_sha_dma_check_aligned(struct atmel_sha_dev *dd,
+   struct scatterlist *sg,
+   size_t len)
+{
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct ahash_request *req = dd->req;
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   size_t bs = ctx->block_size;
+   int nents;
+
+   for (nents = 0; sg; sg = sg_next(sg), ++nents) {
+   if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+   return false;
+
+   /*
+* This is the last sg, the only one that is allowed to
+* have an unaligned length.
+*/
+   if (len <= sg->length) {
+   dma->nents = nents + 1;
+   dma->last_sg_length = sg->length;
+   sg->length = ALIGN(len, sizeof(u32));
+   return true;
+   }
+
+   /* All other sg lengths MUST be aligned to the block size. */
+   if (!IS_ALIGNED(sg->length, bs))
+   return false;
+
+   len -= sg->length;
+   }
+
+   return false;
+}
+
+static void atmel_sha_dma_callback2(void *data)
+{
+   struct atmel_sha_dev *dd = data;
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct scatterlist *sg;
+   int nents;
+
+   dmaengine_terminate_all(dma->chan);
+   dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+
+   sg = dma->sg;
+   for (nents = 0; nents < dma->nents - 1; ++nents)
+   sg = sg_next(sg);
+   sg->length = dma->last_sg_length;
+
+   dd->is_async = true;
+   (void)atmel_sha_wait_for_data_ready(dd, dd->resume);
+}
+
+static int atmel_sha_dma_start(struct atmel_sha_dev *dd,
+  struct scatterlist *src,
+  size_t len,
+  atmel_sha_fn_t resume)
+{
+   struct atmel_sha_dma *dma = >dma_lch_in;
+   struct dma_slave_config *config = >dma_conf;
+   struct dma_chan *chan = dma->chan;
+   struct dma_async_tx_descriptor *desc;
+   dma_cookie_t cookie;
+   unsigned int sg_len;
+   int err;
+
+   dd->resume = resume;
+
+   /*
+* dma->nents has already been initialized by
+* atmel_sha_dma_check_aligned().
+*/
+   dma->sg = src;
+   sg_len = dma_map_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+   if (!sg_len) {
+   err = -ENOMEM;
+   goto exit;
+   }
+
+   config->src_maxburst = 16;
+   config->dst_maxburst = 16;
+   err = dmaengine_slave_config(chan, config);
+   if (err)
+   goto unmap_sg;
+
+   desc = dmaengine_prep_slave_sg(chan, dma->sg, sg_len, DMA_MEM_TO_DEV,
+  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc) {
+   err = -ENOMEM;
+   goto unmap_sg;
+   }
+
+   desc->callback = atmel_sha_dma_callback2;
+   desc->callback_param = dd;
+   cookie = dmaengine_submit(desc);
+   err = dma_submit_error(cookie);
+   if (err)
+   goto unmap_sg;
+
+   dma_async_issue_pending(chan);
+
+   return -EINPROGRESS;
+
+unmap_sg:
+   dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
+exit:
+   return atmel_sha_complete(dd, err);
+}
+
+
 /* CPU transfer functions */
 
 static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
-- 
2.7.4

--
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 02/12] crypto: atmel-sha: update request queue management to make it more generic

2016-12-22 Thread Cyrille Pitchen
This patch is a transitional patch. It splits the atmel_sha_handle_queue()
function. Now atmel_sha_handle_queue() only manages the request queue and
calls a new .start() hook from the atmel_sha_ctx structure.
This hook allows to implement different kind of requests still handled by
a single queue.

Also when the req parameter of atmel_sha_handle_queue() refers to the very
same request as the one returned by crypto_dequeue_request(), the queue
management now gives a chance to this crypto request to be handled
synchronously, hence reducing latencies. The .start() hook returns 0 if
the crypto request was handled synchronously and -EINPROGRESS if the
crypto request still need to be handled asynchronously.

Besides, the new .is_async member of the atmel_sha_dev structure helps
tagging this asynchronous state. Indeed, the req->base.complete() callback
should not be called if the crypto request is handled synchronously.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 74 +-
 1 file changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 33a36e667547..2dbed8bb8d26 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -105,8 +105,11 @@ struct atmel_sha_reqctx {
u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
 
+typedef int (*atmel_sha_fn_t)(struct atmel_sha_dev *);
+
 struct atmel_sha_ctx {
struct atmel_sha_dev*dd;
+   atmel_sha_fn_t  start;
 
unsigned long   flags;
 };
@@ -134,6 +137,7 @@ struct atmel_sha_dev {
unsigned long   flags;
struct crypto_queue queue;
struct ahash_request*req;
+   boolis_async;
 
struct atmel_sha_dmadma_lch_in;
 
@@ -163,6 +167,24 @@ static inline void atmel_sha_write(struct atmel_sha_dev 
*dd,
writel_relaxed(value, dd->io_base + offset);
 }
 
+static inline int atmel_sha_complete(struct atmel_sha_dev *dd, int err)
+{
+   struct ahash_request *req = dd->req;
+
+   dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
+  SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+
+   clk_disable(dd->iclk);
+
+   if (dd->is_async && req->base.complete)
+   req->base.complete(>base, err);
+
+   /* handle new request */
+   tasklet_schedule(>queue_task);
+
+   return err;
+}
+
 static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
 {
size_t count;
@@ -474,6 +496,8 @@ static void atmel_sha_dma_callback(void *data)
 {
struct atmel_sha_dev *dd = data;
 
+   dd->is_async = true;
+
/* dma_lch_in - completed - wait DATRDY */
atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
 }
@@ -509,7 +533,7 @@ static int atmel_sha_xmit_dma(struct atmel_sha_dev *dd, 
dma_addr_t dma_addr1,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
if (!in_desc)
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
 
in_desc->callback = atmel_sha_dma_callback;
in_desc->callback_param = dd;
@@ -566,7 +590,7 @@ static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
ctx->block_size);
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags &= ~SHA_FLAGS_SG;
@@ -657,7 +681,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
dev_err(dd->dev, "dma %u bytes error\n",
ctx->buflen + ctx->block_size);
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
if (length == 0) {
@@ -671,7 +695,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
if (!dma_map_sg(dd->dev, ctx->sg, 1,
DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   return -EINVAL;
+   atmel_sha_complete(dd, -EINVAL);
}
 
ctx->flags |= SHA_FLAGS_SG;
@@ -685,7 +709,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev 
*dd)
 
if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
dev_err(dd->dev, "dma_map_sg  error\n");
-   return -EINVAL;
+   atmel_sha_compl

[PATCH 00/12] crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes

2016-12-22 Thread Cyrille Pitchen
Hi all,

this series of patches has been based and tested on next-20161222 with
CRYPTO_MANAGER_DISABLED_TESTS not set.

The series adds support to the hmac(shaX) algorithms first, then combines
both the Atmel SHA and AES hardware accelerators to implement
authenc(hmac(shaX),Y(aes)) algorithms as used by IPSEC/SSL connections.

It has also been tested with strongswan + xl2tpd to create an IPSEC+L2TP
(transport mode) VPN and strongswan only (tunnel mode) for an IPSEC VPN.

Then iperf was used to measure the bandwidth improvement in tunnel mode:

driversAES SHA SPLIP iperf half-duplex
 Mbit/s
authenc(hmac(sha1-generic),cbc(aes))SW   SW  N/A 27.7
authenc(hmac(sha1-generic),atmel-cbc-aes)   HW   SW  N/A 30.2 (mainline)
authenc(atmel-hmac-sha1,atmel-cbc-aes)  HW   HW   no 29.1
atmel-authenc-hmac-sha1-cbc-aes HW   hW  yes 38.8

SPLIP: Secure Protocol Layers Improved Performances (AES+SHA combined).

Some patches of this series are purely transitional: I've split the
modifications into many patches to ease the review.

Best regards,

Cyrille

Cyrille Pitchen (12):
  crypto: atmel-sha: create function to get an Atmel SHA device
  crypto: atmel-sha: update request queue management to make it more
generic
  crypto: atmel-sha: make atmel_sha_done_task more generic
  crypto: atmel-sha: redefine SHA_FLAGS_SHA* flags to match
SHA_MR_ALGO_SHA*
  crypto: atmel-sha: add atmel_sha_wait_for_data_ready()
  crypto: atmel-sha: add SHA_MR_MODE_IDATAR0
  crypto: atmel-sha: add atmel_sha_cpu_start()
  crypto: atmel-sha: add simple DMA transfers
  crypto: atmel-sha: add support to hmac(shaX)
  crypto: atmel-aes: fix atmel_aes_handle_queue()
  crypto: atmel-authenc: add support to authenc(hmac(shaX),Y(aes)) modes
  crypto: atmel-sha: add verbose debug facilities to print hw register
names

 drivers/crypto/Kconfig  |   12 +
 drivers/crypto/atmel-aes-regs.h |   16 +
 drivers/crypto/atmel-aes.c  |  478 -
 drivers/crypto/atmel-sha-regs.h |   20 +
 drivers/crypto/atmel-sha.c  | 1438 +--
 5 files changed, 1896 insertions(+), 68 deletions(-)

-- 
2.7.4

--
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


crypto regression?

2016-12-08 Thread Cyrille Pitchen
Hi Herbert,

Let me report a potential regression I've noticed this morning when testing
linux-next.

I've set CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=n when compiling both kernel
images.


On 4.9.0-rc2-next-20161028, /proc/crypto displays:
driver   : atmel-xts-aes
module   : kernel
priority : 300
refcnt   : 1
selftest : passed
internal : no
type : ablkcipher
async: yes
blocksize: 16
min keysize  : 32
max keysize  : 64
ivsize   : 16
geniv: 

and no output from the test manager in the boot log.


Whereas on 4.9.0-rc8-next-20161208, we get:
driver   : atmel-xts-aes
module   : kernel
priority : 300
refcnt   : 1
selftest : unknown
internal : no
type : ablkcipher
async: yes
blocksize: 16
min keysize  : 32
max keysize  : 64
ivsize   : 16
geniv: 


Also I see the following traces during the boot:

alg: skcipher: Chunk test 1 failed on encryption at page 0 for atmel-xts-aes
: 1c 3b 3a 10 2f 77 03 86 e4 83 6c 99 e3 70 cf 9b
0010: ea 00 80 3f 5e 48 23 57 a4 ae 12 d4 14 a3 e6 3b
0020: 5d 31 e2 76 f8 fe 4a 8d 66 b3 17 f9 ac 68 3f 44
0030: 68 0a 86 ac 35 ad fc 33 45 be fe cb 4b b1 88 fd
0040: 57 76 92 6c 49 a3 09 5e b1 08 fd 10 98 ba ec 70
0050: aa a6 69 99 a7 2a 82 f2 7d 84 8b 21 d4 a7 41 b0
0060: c5 cd 4d 5f ff 9d ac 89 ae ba 12 29 61 d0 3a 75
0070: 71 23 e9 87 0f 8a cf 10 00 02 08 87 89 14 29 ca
0080: 2a 3e 7a 7d 7d f7 b1 03 55 16 5c 8b 9a 6d 0a 7d
0090: e8 b0 62 c4 50 0d c4 cd 12 0c 0f 74 18 da e3 d0
00a0: b5 78 1c 34 80 3f a7 54 21 c7 90 df e1 de 18 34
00b0: f2 80 d7 66 7b 32 7f 6c 8c d7 55 7e 12 ac 3a 0f
00c0: 93 ec 05 c5 2e 04 93 ef 31 a1 2d 3d 92 60 f7 9a
00d0: 28 9d 6a 37 9b c7 0c 50 84 14 73 d1 a8 cc 81 ec
00e0: 58 3e 96 45 e0 7b 8d 96 70 65 5b a5 bb cf ec c6
00f0: dc 39 66 38 0a d8 fe cb 17 b6 ba 02 46 9a 02 0a
0100: 84 e1 8e 8f 84 25 20 70 c1 3e 9f 1f 28 9b e5 4f
0110: bc 48 14 57 77 8f 61 60 15 e1 32 7a 02 b1 40 f1
0120: 50 5e b3 09 32 6d 68 37 8f 83 74 59 5c 84 9d 84
0130: f4 c3 33 ec 44 23 88 51 43 cb 47 bd 71 c5 ed ae
0140: 9b e6 9a 2f fe ce b1 be c9 de 24 4f be 15 99 2b
0150: 11 b7 7c 04 0f 12 bd 8f 6a 97 5a 44 a0 f9 0c 29
0160: a9 ab c3 d4 d8 93 92 72 84 c5 87 54 cc e2 94 52
0170: 9f 86 14 dc d2 ab a9 91 92 5f ed c4 ae 74 ff ac
0180: 6e 33 3b 93 eb 4a ff 04 79 da 9a 41 0e 44 50 e0
0190: dd 7a e4 c6 e2 91 09 00 57 5d a4 01 fc 07 05 9f
01a0: 64 5e 8b 7e 9b fd ef 33 94 30 54 ff 84 01 14 93
01b0: c2 7b 34 29 ea ed b4 ed 53 76 44 1a 77 ed 43 85
01c0: 1a d7 7f 16 f5 41 df d2 69 d5 0d 6a 5f 14 fb 0a
01d0: b5 32 fd 6f 01 77 3d 53 f7 a4 70 83 46 bc 5f c4
01e0: f3 6f fd a9 fc ea 70 b9 c6 e6 93 e1

The output is a little bit long for test 1, isn't it?
When I look at aes_xts_enc_tv_template[] from crypto/testmgr.h
I see .rlen = 32 .


I didn't bisect to find out exactly since when the regression is there. I
wanted to warn you quickly since we are close to the merge window.
Also if you have already been notified about this issue, please, sorry for
the noise!

Best regards,

Cyrille
--
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 1/1] crypto: atmel-aes: add support to the XTS mode

2016-10-03 Thread Cyrille Pitchen
This patch adds the xts(aes) algorithm, which is supported from
hardware version 0x500 and above (sama5d2x).

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
ChangeLog:

v1 -> v2:
- fix typo in comment inside atmel_aes_xts_process_data():
  s/reverted/reversed/
- use xts_check_key() from atmel_aes_xts_setkey() as suggested by
  Stephan Mueller.

 drivers/crypto/atmel-aes-regs.h |   4 +
 drivers/crypto/atmel-aes.c  | 185 ++--
 2 files changed, 183 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
index 6c2951bb70b1..0ec04407b533 100644
--- a/drivers/crypto/atmel-aes-regs.h
+++ b/drivers/crypto/atmel-aes-regs.h
@@ -28,6 +28,7 @@
 #define AES_MR_OPMOD_CFB   (0x3 << 12)
 #define AES_MR_OPMOD_CTR   (0x4 << 12)
 #define AES_MR_OPMOD_GCM   (0x5 << 12)
+#define AES_MR_OPMOD_XTS   (0x6 << 12)
 #define AES_MR_LOD (0x1 << 15)
 #define AES_MR_CFBS_MASK   (0x7 << 16)
 #define AES_MR_CFBS_128b   (0x0 << 16)
@@ -67,6 +68,9 @@
 #define AES_CTRR   0x98
 #define AES_GCMHR(x)   (0x9c + ((x) * 0x04))
 
+#define AES_TWR(x) (0xc0 + ((x) * 0x04))
+#define AES_ALPHAR(x)  (0xd0 + ((x) * 0x04))
+
 #define AES_HW_VERSION 0xFC
 
 #endif /* __ATMEL_AES_REGS_H__ */
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 1d9e7bd3f377..6b656f4a9378 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -68,6 +69,7 @@
 #define AES_FLAGS_CFB8 (AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
 #define AES_FLAGS_CTR  AES_MR_OPMOD_CTR
 #define AES_FLAGS_GCM  AES_MR_OPMOD_GCM
+#define AES_FLAGS_XTS  AES_MR_OPMOD_XTS
 
 #define AES_FLAGS_MODE_MASK(AES_FLAGS_OPMODE_MASK |\
 AES_FLAGS_ENCRYPT |\
@@ -89,6 +91,7 @@ struct atmel_aes_caps {
boolhas_cfb64;
boolhas_ctr32;
boolhas_gcm;
+   boolhas_xts;
u32 max_burst_size;
 };
 
@@ -135,6 +138,12 @@ struct atmel_aes_gcm_ctx {
atmel_aes_fn_t  ghash_resume;
 };
 
+struct atmel_aes_xts_ctx {
+   struct atmel_aes_base_ctx   base;
+
+   u32 key2[AES_KEYSIZE_256 / sizeof(u32)];
+};
+
 struct atmel_aes_reqctx {
unsigned long   mode;
 };
@@ -282,6 +291,20 @@ static const char *atmel_aes_reg_name(u32 offset, char 
*tmp, size_t sz)
snprintf(tmp, sz, "GCMHR[%u]", (offset - AES_GCMHR(0)) >> 2);
break;
 
+   case AES_TWR(0):
+   case AES_TWR(1):
+   case AES_TWR(2):
+   case AES_TWR(3):
+   snprintf(tmp, sz, "TWR[%u]", (offset - AES_TWR(0)) >> 2);
+   break;
+
+   case AES_ALPHAR(0):
+   case AES_ALPHAR(1):
+   case AES_ALPHAR(2):
+   case AES_ALPHAR(3):
+   snprintf(tmp, sz, "ALPHAR[%u]", (offset - AES_ALPHAR(0)) >> 2);
+   break;
+
default:
snprintf(tmp, sz, "0x%02x", offset);
break;
@@ -453,15 +476,15 @@ static inline int atmel_aes_complete(struct atmel_aes_dev 
*dd, int err)
return err;
 }
 
-static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
-const u32 *iv)
+static void atmel_aes_write_ctrl_key(struct atmel_aes_dev *dd, bool use_dma,
+const u32 *iv, const u32 *key, int keylen)
 {
u32 valmr = 0;
 
/* MR register must be set before IV registers */
-   if (dd->ctx->keylen == AES_KEYSIZE_128)
+   if (keylen == AES_KEYSIZE_128)
valmr |= AES_MR_KEYSIZE_128;
-   else if (dd->ctx->keylen == AES_KEYSIZE_192)
+   else if (keylen == AES_KEYSIZE_192)
valmr |= AES_MR_KEYSIZE_192;
else
valmr |= AES_MR_KEYSIZE_256;
@@ -478,13 +501,19 @@ static void atmel_aes_write_ctrl(struct atmel_aes_dev 
*dd, bool use_dma,
 
atmel_aes_write(dd, AES_MR, valmr);
 
-   atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
- SIZE_IN_WORDS(dd->ctx->keylen));
+   atmel_aes_write_n(dd, AES_KEYWR(0), key, SIZE_IN_WORDS(keylen));
 
if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
atmel_aes_write_block(dd, AES_IVR(0), iv);
 }
 
+static inline void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
+   const u32 *iv)
+
+{
+   atmel_aes_write_ctrl_key(dd, use_dma, iv,
+dd->ctx->key, dd->ct

Re: [BUG] crypto: atmel-aes - erro when compiling with VERBOSE_DEBUG enable

2016-10-03 Thread Cyrille Pitchen
Hi all,

Le 02/10/2016 à 16:38, Herbert Xu a écrit :
> On Tue, Sep 27, 2016 at 06:45:18PM +0200, Cyrille Pitchen wrote:
>> Hi Levent,
>>
>> there is a typo in the subject line: erroR.
>> Also it would be better to start the summary phrase of the subject line with 
>> a
>> verb:
>>
>> crypto: atmel-aes: fix compiler error when VERBODE_DEBUG is defined
>>
>> Le 22/09/2016 à 14:45, levent demir a écrit :
>>> Fix debug function call in atmel_aes_write
>>>
>>> Signed-off-by: Levent DEMIR <levent.de...@inria.fr>
>>> ---
>>>  drivers/crypto/atmel-aes.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
>>> index e3d40a8..2b0f926 100644
>>> --- a/drivers/crypto/atmel-aes.c
>>> +++ b/drivers/crypto/atmel-aes.c
>>> @@ -317,7 +317,7 @@ static inline void atmel_aes_write(struct
>>> atmel_aes_dev *dd,
>>> char tmp[16];
>>>  
>>> dev_vdbg(dd->dev, "write 0x%08x into %s\n", value,
>>> -atmel_aes_reg_name(offset, tmp));
>>> +   atmel_aes_reg_name(offset, tmp, sizeof(tmp)));
>> It looks like a space has been removed.
> 
> It's been completely mangled by the mailer and cannot be applied.
> 
I've sent a new version in this thread:
https://lkml.org/lkml/2016/9/29/463

I added a Reported-by tag for Levent but if you want to use a Signed-off-by
tag instead, it's fine with me!

Best regards,

Cyrille
--
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: [BUG] crypto: atmel-aes - erro when compiling with VERBOSE_DEBUG enable

2016-09-27 Thread Cyrille Pitchen
Hi Levent,

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

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

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

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


Best regards,

Cyrille
--
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 1/2] crypto: atmel-sha - fix .import()/.export() implementation

2016-02-08 Thread Cyrille Pitchen
Using only the digest, digcnt[], bufcnt and buffer[] fields of the
struct atmel_sha_reqctx was not enough to import/export the request state,
so now we use the whole structure.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 44 ++--
 1 file changed, 10 insertions(+), 34 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index f8407dc7dd38..7d27f96cdf02 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -81,16 +81,9 @@ struct atmel_sha_caps {
 struct atmel_sha_dev;
 
 /*
- * .statesize = sizeof(struct atmel_sha_state) must be <= PAGE_SIZE / 8 as
+ * .statesize = sizeof(struct atmel_sha_reqctx) must be <= PAGE_SIZE / 8 as
  * tested by the ahash_prepare_alg() function.
  */
-struct atmel_sha_state {
-   u8  digest[SHA512_DIGEST_SIZE];
-   u8  buffer[SHA_BUFFER_LEN];
-   u64 digcnt[2];
-   size_t  bufcnt;
-};
-
 struct atmel_sha_reqctx {
struct atmel_sha_dev*dd;
unsigned long   flags;
@@ -109,7 +102,7 @@ struct atmel_sha_reqctx {
 
size_t block_size;
 
-   u8  buffer[0] __aligned(sizeof(u32));
+   u8 buffer[SHA_BUFFER_LEN + SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
 };
 
 struct atmel_sha_ctx {
@@ -1048,40 +1041,23 @@ static int atmel_sha_digest(struct ahash_request *req)
 static int atmel_sha_export(struct ahash_request *req, void *out)
 {
const struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-   struct atmel_sha_state state;
-
-   memcpy(state.digest, ctx->digest, SHA512_DIGEST_SIZE);
-   memcpy(state.buffer, ctx->buffer, ctx->bufcnt);
-   state.bufcnt = ctx->bufcnt;
-   state.digcnt[0] = ctx->digcnt[0];
-   state.digcnt[1] = ctx->digcnt[1];
 
-   /* out might be unaligned. */
-   memcpy(out, , sizeof(state));
+   memcpy(out, ctx, sizeof(*ctx));
return 0;
 }
 
 static int atmel_sha_import(struct ahash_request *req, const void *in)
 {
struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-   struct atmel_sha_state state;
-
-   /* in might be unaligned. */
-   memcpy(, in, sizeof(state));
 
-   memcpy(ctx->digest, state.digest, SHA512_DIGEST_SIZE);
-   memcpy(ctx->buffer, state.buffer, state.bufcnt);
-   ctx->bufcnt = state.bufcnt;
-   ctx->digcnt[0] = state.digcnt[0];
-   ctx->digcnt[1] = state.digcnt[1];
+   memcpy(ctx, in, sizeof(*ctx));
return 0;
 }
 
 static int atmel_sha_cra_init(struct crypto_tfm *tfm)
 {
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
-sizeof(struct atmel_sha_reqctx) +
-SHA_BUFFER_LEN + SHA512_BLOCK_SIZE);
+sizeof(struct atmel_sha_reqctx));
 
return 0;
 }
@@ -1097,7 +1073,7 @@ static struct ahash_alg sha_1_256_algs[] = {
.import = atmel_sha_import,
.halg = {
.digestsize = SHA1_DIGEST_SIZE,
-   .statesize  = sizeof(struct atmel_sha_state),
+   .statesize  = sizeof(struct atmel_sha_reqctx),
.base   = {
.cra_name   = "sha1",
.cra_driver_name= "atmel-sha1",
@@ -1121,7 +1097,7 @@ static struct ahash_alg sha_1_256_algs[] = {
.import = atmel_sha_import,
.halg = {
.digestsize = SHA256_DIGEST_SIZE,
-   .statesize  = sizeof(struct atmel_sha_state),
+   .statesize  = sizeof(struct atmel_sha_reqctx),
.base   = {
.cra_name   = "sha256",
.cra_driver_name= "atmel-sha256",
@@ -1147,7 +1123,7 @@ static struct ahash_alg sha_224_alg = {
.import = atmel_sha_import,
.halg = {
.digestsize = SHA224_DIGEST_SIZE,
-   .statesize  = sizeof(struct atmel_sha_state),
+   .statesize  = sizeof(struct atmel_sha_reqctx),
.base   = {
.cra_name   = "sha224",
.cra_driver_name= "atmel-sha224",
@@ -1173,7 +1149,7 @@ static struct ahash_alg sha_384_512_algs[] = {
.import = atmel_sha_import,
.halg = {
.digestsize = SHA384_DIGEST_SIZE,
-   .statesize  = sizeof(struct atmel_sha_state),
+   .statesize  = sizeof(struct atmel_sha_reqctx),
.base   = {
.cra_name   = "sha384",
.cra_driver_name= "atmel-sha384",
@@ -1197,7 +1173,7 @@ static struct ahash_alg sha_384_512_algs[] = {
.import = atmel_sha_import,
.h

[PATCH 2/2] crypto: atmel-sha - fix race in atmel_sha_final()

2016-02-08 Thread Cyrille Pitchen
When (!ctx->bufcnt && !(ctx->flags & SHA_FLAGS_PAD)), the former source
code used to set the SHA_FLAGS_BUSY without checking whether this flag was
already set. If so, the hardware is already processing another hash
request so the processing of the req argument of atmel_sha_final() should
be delayed by queueing this request, the same way as done for the
(ctx->bufcnt != 0) case.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-sha.c | 24 ++--
 1 file changed, 2 insertions(+), 22 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 7d27f96cdf02..596e489a4ca9 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -979,37 +979,17 @@ static int atmel_sha_update(struct ahash_request *req)
 static int atmel_sha_final(struct ahash_request *req)
 {
struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-   struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
-   struct atmel_sha_dev *dd = tctx->dd;
-
-   int err = 0;
 
ctx->flags |= SHA_FLAGS_FINUP;
 
if (ctx->flags & SHA_FLAGS_ERROR)
return 0; /* uncompleted hash is not needed */
 
-   if (ctx->bufcnt) {
-   return atmel_sha_enqueue(req, SHA_OP_FINAL);
-   } else if (!(ctx->flags & SHA_FLAGS_PAD)) { /* add padding */
-   err = atmel_sha_hw_init(dd);
-   if (err)
-   goto err1;
-
-   dd->req = req;
-   dd->flags |= SHA_FLAGS_BUSY;
-   err = atmel_sha_final_req(dd);
-   } else {
+   if (ctx->flags & SHA_FLAGS_PAD)
/* copy ready hash (+ finalize hmac) */
return atmel_sha_finish(req);
-   }
-
-err1:
-   if (err != -EINPROGRESS)
-   /* done_task will not finish it, so do it here */
-   atmel_sha_finish_req(req, err);
 
-   return err;
+   return atmel_sha_enqueue(req, SHA_OP_FINAL);
 }
 
 static int atmel_sha_finup(struct ahash_request *req)
-- 
1.8.2.2

--
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 0/2] crypto: atmel-sha - fix .import()/.export() implementation

2016-02-08 Thread Cyrille Pitchen
This series of patches includes two fixes for the atmel-sha.c driver.

The first one fixes the implementation of the import/export hooks, which
did not pass the recent updates in testmgr.c (partial update exercise).
The new implementation now passes the tcrypt tests: tested with
next-20160208.

The second patch fixes a race condition if acquiring the hardware when it
is already busy.

Cyrille Pitchen (2):
  crypto: atmel-sha - fix .import()/.export() implementation
  crypto: atmel-sha - fix race in atmel_sha_final()

 drivers/crypto/atmel-sha.c | 68 --
 1 file changed, 12 insertions(+), 56 deletions(-)

-- 
1.8.2.2

--
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 2/2] crypto: atmel-sha - remove calls of clk_prepare() from atomic contexts

2016-02-05 Thread Cyrille Pitchen
clk_prepare()/clk_unprepare() must not be called within atomic context.

This patch calls clk_prepare() once for all from atmel_sha_probe() and
clk_unprepare() from atmel_sha_remove().

Then calls of clk_prepare_enable()/clk_disable_unprepare() were replaced
by calls of clk_enable()/clk_disable().

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Reported-by: Matthias Mayr <matthias.m...@student.kit.edu>
---
 drivers/crypto/atmel-sha.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index b827c99b17c1..f8407dc7dd38 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -846,7 +846,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, 
int err)
dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
 
-   clk_disable_unprepare(dd->iclk);
+   clk_disable(dd->iclk);
 
if (req->base.complete)
req->base.complete(>base, err);
@@ -859,7 +859,7 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
 {
int err;
 
-   err = clk_prepare_enable(dd->iclk);
+   err = clk_enable(dd->iclk);
if (err)
return err;
 
@@ -886,7 +886,7 @@ static void atmel_sha_hw_version_init(struct atmel_sha_dev 
*dd)
dev_info(dd->dev,
"version: 0x%x\n", dd->hw_version);
 
-   clk_disable_unprepare(dd->iclk);
+   clk_disable(dd->iclk);
 }
 
 static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
@@ -1536,6 +1536,10 @@ static int atmel_sha_probe(struct platform_device *pdev)
goto res_err;
}
 
+   err = clk_prepare(sha_dd->iclk);
+   if (err)
+   goto res_err;
+
atmel_sha_hw_version_init(sha_dd);
 
atmel_sha_get_cap(sha_dd);
@@ -1547,12 +1551,12 @@ static int atmel_sha_probe(struct platform_device *pdev)
if (IS_ERR(pdata)) {
dev_err(>dev, "platform data not 
available\n");
err = PTR_ERR(pdata);
-   goto res_err;
+   goto iclk_unprepare;
}
}
if (!pdata->dma_slave) {
err = -ENXIO;
-   goto res_err;
+   goto iclk_unprepare;
}
err = atmel_sha_dma_init(sha_dd, pdata);
if (err)
@@ -1583,6 +1587,8 @@ err_algs:
if (sha_dd->caps.has_dma)
atmel_sha_dma_cleanup(sha_dd);
 err_sha_dma:
+iclk_unprepare:
+   clk_unprepare(sha_dd->iclk);
 res_err:
tasklet_kill(_dd->queue_task);
tasklet_kill(_dd->done_task);
@@ -1611,6 +1617,8 @@ static int atmel_sha_remove(struct platform_device *pdev)
if (sha_dd->caps.has_dma)
atmel_sha_dma_cleanup(sha_dd);
 
+   clk_unprepare(sha_dd->iclk);
+
return 0;
 }
 
-- 
1.8.2.2

--
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 0/2] crypto: atmel-sha - fix resource management

2016-02-05 Thread Cyrille Pitchen
Hi all,

these two small patches fix resource release and clock management in
atomic context.

Best regards,

Cyrille

Cyrille Pitchen (2):
  crypto: atmel-sha: fix atmel_sha_remove()
  crypto: atmel-sha - remove calls of clk_prepare() from atomic contexts

 drivers/crypto/atmel-sha.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

-- 
1.8.2.2

--
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] crypto: atmel-aes - remove calls of clk_prepare() from atomic contexts

2016-01-29 Thread Cyrille Pitchen
clk_prepare()/clk_unprepare() must not be called within atomic context.

This patch calls clk_prepare() once for all from atmel_aes_probe() and
clk_unprepare() from atmel_aes_remove().

Then calls of clk_prepare_enable()/clk_disable_unprepare() were replaced
by calls of clk_enable()/clk_disable().

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
Reported-by: Matthias Mayr <matthias.m...@student.kit.edu>
---
 drivers/crypto/atmel-aes.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 6dd3317ca365..3eb3f1279fb7 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -400,7 +400,7 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
 {
int err;
 
-   err = clk_prepare_enable(dd->iclk);
+   err = clk_enable(dd->iclk);
if (err)
return err;
 
@@ -430,7 +430,7 @@ static int atmel_aes_hw_version_init(struct atmel_aes_dev 
*dd)
 
dev_info(dd->dev, "version: 0x%x\n", dd->hw_version);
 
-   clk_disable_unprepare(dd->iclk);
+   clk_disable(dd->iclk);
return 0;
 }
 
@@ -448,7 +448,7 @@ static inline bool atmel_aes_is_encrypt(const struct 
atmel_aes_dev *dd)
 
 static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
 {
-   clk_disable_unprepare(dd->iclk);
+   clk_disable(dd->iclk);
dd->flags &= ~AES_FLAGS_BUSY;
 
if (dd->is_async)
@@ -2091,10 +2091,14 @@ static int atmel_aes_probe(struct platform_device *pdev)
goto res_err;
}
 
-   err = atmel_aes_hw_version_init(aes_dd);
+   err = clk_prepare(aes_dd->iclk);
if (err)
goto res_err;
 
+   err = atmel_aes_hw_version_init(aes_dd);
+   if (err)
+   goto iclk_unprepare;
+
atmel_aes_get_cap(aes_dd);
 
err = atmel_aes_buff_init(aes_dd);
@@ -2127,6 +2131,8 @@ err_algs:
 err_aes_dma:
atmel_aes_buff_cleanup(aes_dd);
 err_aes_buff:
+iclk_unprepare:
+   clk_unprepare(aes_dd->iclk);
 res_err:
tasklet_kill(_dd->done_task);
tasklet_kill(_dd->queue_task);
@@ -2155,6 +2161,8 @@ static int atmel_aes_remove(struct platform_device *pdev)
atmel_aes_dma_cleanup(aes_dd);
atmel_aes_buff_cleanup(aes_dd);
 
+   clk_unprepare(aes_dd->iclk);
+
return 0;
 }
 
-- 
1.8.2.2

--
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] crypto: atmel-sha: fix algorihtm registration

2016-01-29 Thread Cyrille Pitchen
This patch implements the missing .import() and .export() mandatory
hooks for asynchronous hash algorithms. It also sets the relevant, non
zero, value for the .statesize field when declaring the supported SHA
algorithms. Indeed a zero value of .statesize prevents the algorithm from
being registered.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
ChangeLog

v2: deal with unaligned in/out pointers in atmel_sha_import/atmel_sha_export

 drivers/crypto/atmel-sha.c | 61 +-
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index da4c3055784f..63b09e01075c 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -66,7 +66,7 @@
 #define SHA_OP_UPDATE  1
 #define SHA_OP_FINAL   2
 
-#define SHA_BUFFER_LEN PAGE_SIZE
+#define SHA_BUFFER_LEN (PAGE_SIZE / 16)
 
 #define ATMEL_SHA_DMA_THRESHOLD56
 
@@ -80,6 +80,17 @@ struct atmel_sha_caps {
 
 struct atmel_sha_dev;
 
+/*
+ * .statesize = sizeof(struct atmel_sha_state) must be <= PAGE_SIZE / 8 as
+ * tested by the ahash_prepare_alg() function.
+ */
+struct atmel_sha_state {
+   u8  digest[SHA512_DIGEST_SIZE];
+   u8  buffer[SHA_BUFFER_LEN];
+   u64 digcnt[2];
+   size_t  bufcnt;
+};
+
 struct atmel_sha_reqctx {
struct atmel_sha_dev*dd;
unsigned long   flags;
@@ -1033,6 +1044,39 @@ static int atmel_sha_digest(struct ahash_request *req)
return atmel_sha_init(req) ?: atmel_sha_finup(req);
 }
 
+
+static int atmel_sha_export(struct ahash_request *req, void *out)
+{
+   const struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   struct atmel_sha_state state;
+
+   memcpy(state.digest, ctx->digest, SHA512_DIGEST_SIZE);
+   memcpy(state.buffer, ctx->buffer, ctx->bufcnt);
+   state.bufcnt = ctx->bufcnt;
+   state.digcnt[0] = ctx->digcnt[0];
+   state.digcnt[1] = ctx->digcnt[1];
+
+   /* out might be unaligned. */
+   memcpy(out, , sizeof(state));
+   return 0;
+}
+
+static int atmel_sha_import(struct ahash_request *req, const void *in)
+{
+   struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
+   struct atmel_sha_state state;
+
+   /* in might be unaligned. */
+   memcpy(, in, sizeof(state));
+
+   memcpy(ctx->digest, state.digest, SHA512_DIGEST_SIZE);
+   memcpy(ctx->buffer, state.buffer, state.bufcnt);
+   ctx->bufcnt = state.bufcnt;
+   ctx->digcnt[0] = state.digcnt[0];
+   ctx->digcnt[1] = state.digcnt[1];
+   return 0;
+}
+
 static int atmel_sha_cra_init(struct crypto_tfm *tfm)
 {
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
@@ -1049,8 +1093,11 @@ static struct ahash_alg sha_1_256_algs[] = {
.final  = atmel_sha_final,
.finup  = atmel_sha_finup,
.digest = atmel_sha_digest,
+   .export = atmel_sha_export,
+   .import = atmel_sha_import,
.halg = {
.digestsize = SHA1_DIGEST_SIZE,
+   .statesize  = sizeof(struct atmel_sha_state),
.base   = {
.cra_name   = "sha1",
.cra_driver_name= "atmel-sha1",
@@ -1070,8 +1117,11 @@ static struct ahash_alg sha_1_256_algs[] = {
.final  = atmel_sha_final,
.finup  = atmel_sha_finup,
.digest = atmel_sha_digest,
+   .export = atmel_sha_export,
+   .import = atmel_sha_import,
.halg = {
.digestsize = SHA256_DIGEST_SIZE,
+   .statesize  = sizeof(struct atmel_sha_state),
.base   = {
.cra_name   = "sha256",
.cra_driver_name= "atmel-sha256",
@@ -1093,8 +1143,11 @@ static struct ahash_alg sha_224_alg = {
.final  = atmel_sha_final,
.finup  = atmel_sha_finup,
.digest = atmel_sha_digest,
+   .export = atmel_sha_export,
+   .import = atmel_sha_import,
.halg = {
.digestsize = SHA224_DIGEST_SIZE,
+   .statesize  = sizeof(struct atmel_sha_state),
.base   = {
.cra_name   = "sha224",
.cra_driver_name= "atmel-sha224",
@@ -1116,8 +1169,11 @@ static struct ahash_alg sha_384_512_algs[] = {
.final  = atmel_sha_final,
.finup  = atmel_sha_finup,
.digest = atmel_sha_digest,
+   .export = atmel_sha_export,
+   .import = atmel_sha_import,
.halg = {
.digestsize = SHA384_DIGEST_SIZE,
+   .statesize  = sizeof(struct a

Re: [PATCH 0/5] crypto: atmel-sha: fix registration issue and other bugs

2016-01-25 Thread Cyrille Pitchen
Hi Herbert,

Le 25/01/2016 15:48, Herbert Xu a écrit :
> On Fri, Jan 15, 2016 at 03:49:30PM +0100, Cyrille Pitchen wrote:
>> Hi all,
>>
>> This series of patches fixes many issues such as the algo registration 
>> failure
>> or the broken support of context switches.
>>
>> This series was applied to linux-next and tested on a sama5d2 xplained
>> ultra board. We now pass the tcrypt tests in the following modes:
>> -  2: sha1
>> -  6: sha256
>> - 11: sha384
>> - 12: sha512
>> - 33: sha224
>>
>> The context switch fix was tested with a userspace program using the 
>> cryptodev
>> module. This single thread program computes the SHA256 hashes of many files
>> by splitting then into fixed size chunks. The chunks of each file are
>> processed by calling 'update' operations using a round robin algorithm.
>>
>> However, the .import() / .export() implementation was NOT tested!
>> Nonetheless the last patch is needed to fix the registration issue, otherwise
>> atmel_sha_probe() would still fail.
> 
> Patch 1-4 applied.  Please fix the alignment issue with patch 5.
> 

OK, I will fix it soon!


Best regards,

Cyrille
--
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 03/24] crypto: atmel-aes: change algorithm priorities

2015-12-17 Thread Cyrille Pitchen
Increase the algorithm priorities so the hardware acceleration is now
preferred to the software computation: the "aes-generice" driver uses 100
as priority.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 1d3997a45610..e545636a7ddc 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -43,6 +43,8 @@
 #include 
 #include "atmel-aes-regs.h"
 
+#define ATMEL_AES_PRIORITY 300
+
 #define CFB8_BLOCK_SIZE1
 #define CFB16_BLOCK_SIZE   2
 #define CFB32_BLOCK_SIZE   4
@@ -960,7 +962,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "ecb(aes)",
.cra_driver_name= "atmel-ecb-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = AES_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -980,7 +982,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "cbc(aes)",
.cra_driver_name= "atmel-cbc-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = AES_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1001,7 +1003,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "ofb(aes)",
.cra_driver_name= "atmel-ofb-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = AES_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1022,7 +1024,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "cfb(aes)",
.cra_driver_name= "atmel-cfb-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = AES_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1043,7 +1045,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "cfb32(aes)",
.cra_driver_name= "atmel-cfb32-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = CFB32_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1064,7 +1066,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "cfb16(aes)",
.cra_driver_name= "atmel-cfb16-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = CFB16_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1085,7 +1087,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "cfb8(aes)",
.cra_driver_name= "atmel-cfb8-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = CFB8_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1106,7 +1108,7 @@ static struct crypto_alg aes_algs[] = {
 {
.cra_name   = "ctr(aes)",
.cra_driver_name= "atmel-ctr-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = AES_BLOCK_SIZE,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
@@ -1129,7 +1131,7 @@ static struct crypto_alg aes_algs[] = {
 static struct crypto_alg aes_cfb64_alg = {
.cra_name   = "cfb64(aes)",
.cra_driver_name= "atmel-cfb64-aes",
-   .cra_priority   = 100,
+   .cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize  = CFB64_BLOCK_SIZE,
.cra_ctxsize

[PATCH 12/24] crypto: atmel-aes: remove unused 'err' member of struct atmel_aes_dev

2015-12-17 Thread Cyrille Pitchen
This 'err' member was initialized to 0 but its value never changed.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index ac551ee2d624..25dc7bd73532 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -127,7 +127,6 @@ struct atmel_aes_dev {
int irq;
 
unsigned long   flags;
-   int err;
 
spinlock_t  lock;
struct crypto_queue queue;
@@ -288,7 +287,6 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET);
dd->flags |= AES_FLAGS_INIT;
-   dd->err = 0;
}
 
return 0;
@@ -1171,9 +1169,6 @@ static int atmel_aes_dma_complete(struct atmel_aes_dev 
*dd)
int err;
 
err = atmel_aes_crypt_dma_stop(dd);
-
-   err = dd->err ? : err;
-
if (dd->total && !err) {
if (dd->flags & AES_FLAGS_FAST) {
dd->in_sg = sg_next(dd->in_sg);
-- 
1.8.2.2

--
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 11/24] crypto: atmel-aes: rework crypto request completion

2015-12-17 Thread Cyrille Pitchen
This patch introduces a new callback 'resume' in the struct atmel_aes_dev.
This callback is run to resume/complete the processing of the crypto
request when woken up by I/O events such as AES interrupts or DMA
completion.

This callback will help implementing the GCM mode support in further
patches.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 74 +-
 1 file changed, 47 insertions(+), 27 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index c10c54ccc606..ac551ee2d624 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -119,6 +119,9 @@ struct atmel_aes_dev {
struct crypto_async_request *areq;
struct atmel_aes_base_ctx   *ctx;
 
+   boolis_async;
+   atmel_aes_fn_t  resume;
+
struct device   *dev;
struct clk  *iclk;
int irq;
@@ -319,14 +322,17 @@ static inline void atmel_aes_set_mode(struct 
atmel_aes_dev *dd,
dd->flags = (dd->flags & AES_FLAGS_PERSISTENT) | rctx->mode;
 }
 
-static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err)
+static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
 {
-   struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
-
clk_disable_unprepare(dd->iclk);
dd->flags &= ~AES_FLAGS_BUSY;
 
-   req->base.complete(>base, err);
+   if (dd->is_async)
+   dd->areq->complete(dd->areq, err);
+
+   tasklet_schedule(>queue_task);
+
+   return err;
 }
 
 static void atmel_aes_dma_callback(void *data)
@@ -423,6 +429,8 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
return 0;
 }
 
+static int atmel_aes_cpu_complete(struct atmel_aes_dev *dd);
+
 static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
 {
struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
@@ -455,9 +463,12 @@ static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev 
*dd)
atmel_aes_write_n(dd, AES_IDATAR(0), (u32 *) dd->buf_in,
dd->bufcnt >> 2);
 
-   return 0;
+   dd->resume = atmel_aes_cpu_complete;
+   return -EINPROGRESS;
 }
 
+static int atmel_aes_dma_complete(struct atmel_aes_dev *dd);
+
 static int atmel_aes_crypt_dma_start(struct atmel_aes_dev *dd)
 {
int err, fast = 0, in, out;
@@ -524,7 +535,8 @@ static int atmel_aes_crypt_dma_start(struct atmel_aes_dev 
*dd)
dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
}
 
-   return err;
+   dd->resume = atmel_aes_dma_complete;
+   return err ? : -EINPROGRESS;
 }
 
 static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
@@ -590,9 +602,10 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
 
dd->areq = areq;
dd->ctx = ctx;
+   dd->is_async = (areq != new_areq);
 
err = ctx->start(dd);
-   return (areq != new_areq) ? ret : err;
+   return (dd->is_async) ? ret : err;
 }
 
 static int atmel_aes_start(struct atmel_aes_dev *dd)
@@ -621,10 +634,9 @@ static int atmel_aes_start(struct atmel_aes_dev *dd)
else
err = atmel_aes_crypt_cpu_start(dd);
}
-   if (err) {
+   if (err && err != -EINPROGRESS) {
/* aes_task will not finish it, so do it here */
-   atmel_aes_finish_req(dd, err);
-   tasklet_schedule(>queue_task);
+   return atmel_aes_complete(dd, err);
}
 
return -EINPROGRESS;
@@ -1149,20 +1161,14 @@ static void atmel_aes_queue_task(unsigned long data)
 static void atmel_aes_done_task(unsigned long data)
 {
struct atmel_aes_dev *dd = (struct atmel_aes_dev *) data;
-   int err;
-
-   if (!(dd->flags & AES_FLAGS_DMA)) {
-   atmel_aes_read_n(dd, AES_ODATAR(0), (u32 *) dd->buf_out,
-   dd->bufcnt >> 2);
 
-   if (sg_copy_from_buffer(dd->out_sg, dd->nb_out_sg,
-   dd->buf_out, dd->bufcnt))
-   err = 0;
-   else
-   err = -EINVAL;
+   dd->is_async = true;
+   (void)dd->resume(dd);
+}
 
-   goto cpu_end;
-   }
+static int atmel_aes_dma_complete(struct atmel_aes_dev *dd)
+{
+   int err;
 
err = atmel_aes_crypt_dma_stop(dd);
 
@@ -1177,13 +1183,27 @@ static void atmel_aes_done_task(unsigned long data)
}
if (!err)
err = atmel_aes_crypt_dma_start(dd);
-   if (!err)
-   return; /* DMA started. Not fininishing. */
+   if (!err || err == -EINPROGRESS)
+   return -EINPROGRESS; /* DMA sta

[PATCH 09/24] crypto: atmel-aes: remove useless write in the Control Register

2015-12-17 Thread Cyrille Pitchen
As claimed by the datasheet, writing 0 into the Control Register has no
effet. So we remove this useless register access.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 48407a7f6f61..f1ea9c893561 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -511,7 +511,7 @@ static int atmel_aes_crypt_dma_start(struct atmel_aes_dev 
*dd)
 static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
 const u32 *iv)
 {
-   u32 valcr = 0, valmr = 0;
+   u32 valmr = 0;
 
/* MR register must be set before IV registers */
if (dd->ctx->keylen == AES_KEYSIZE_128)
@@ -554,7 +554,6 @@ static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, 
bool use_dma,
valmr |= AES_MR_SMOD_AUTO;
}
 
-   atmel_aes_write(dd, AES_CR, valcr);
atmel_aes_write(dd, AES_MR, valmr);
 
atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
-- 
1.8.2.2

--
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 10/24] crypto: atmel-aes: simplify the configuration of the AES IP

2015-12-17 Thread Cyrille Pitchen
This patch reworks the AES_FLAGS_* to simplify the configuration of the
AES IP.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 216 +++--
 1 file changed, 93 insertions(+), 123 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index f1ea9c893561..c10c54ccc606 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -48,22 +48,28 @@
 #define CFB64_BLOCK_SIZE   8
 
 /* AES flags */
-#define AES_FLAGS_MODE_MASK0x03ff
-#define AES_FLAGS_ENCRYPT  BIT(0)
-#define AES_FLAGS_CBC  BIT(1)
-#define AES_FLAGS_CFB  BIT(2)
-#define AES_FLAGS_CFB8 BIT(3)
-#define AES_FLAGS_CFB16BIT(4)
-#define AES_FLAGS_CFB32BIT(5)
-#define AES_FLAGS_CFB64BIT(6)
-#define AES_FLAGS_CFB128   BIT(7)
-#define AES_FLAGS_OFB  BIT(8)
-#define AES_FLAGS_CTR  BIT(9)
-
-#define AES_FLAGS_INIT BIT(16)
-#define AES_FLAGS_DMA  BIT(17)
-#define AES_FLAGS_BUSY BIT(18)
-#define AES_FLAGS_FAST BIT(19)
+/* Reserve bits [18:16] [14:12] [0] for mode (same as for AES_MR) */
+#define AES_FLAGS_ENCRYPT  AES_MR_CYPHER_ENC
+#define AES_FLAGS_OPMODE_MASK  (AES_MR_OPMOD_MASK | AES_MR_CFBS_MASK)
+#define AES_FLAGS_ECB  AES_MR_OPMOD_ECB
+#define AES_FLAGS_CBC  AES_MR_OPMOD_CBC
+#define AES_FLAGS_OFB  AES_MR_OPMOD_OFB
+#define AES_FLAGS_CFB128   (AES_MR_OPMOD_CFB | AES_MR_CFBS_128b)
+#define AES_FLAGS_CFB64(AES_MR_OPMOD_CFB | AES_MR_CFBS_64b)
+#define AES_FLAGS_CFB32(AES_MR_OPMOD_CFB | AES_MR_CFBS_32b)
+#define AES_FLAGS_CFB16(AES_MR_OPMOD_CFB | AES_MR_CFBS_16b)
+#define AES_FLAGS_CFB8 (AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
+#define AES_FLAGS_CTR  AES_MR_OPMOD_CTR
+
+#define AES_FLAGS_MODE_MASK(AES_FLAGS_OPMODE_MASK |\
+AES_FLAGS_ENCRYPT)
+
+#define AES_FLAGS_INIT BIT(2)
+#define AES_FLAGS_BUSY BIT(3)
+#define AES_FLAGS_DMA  BIT(4)
+#define AES_FLAGS_FAST BIT(5)
+
+#define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
 
 #define ATMEL_AES_QUEUE_LENGTH 50
 
@@ -306,6 +312,13 @@ static int atmel_aes_hw_version_init(struct atmel_aes_dev 
*dd)
return 0;
 }
 
+static inline void atmel_aes_set_mode(struct atmel_aes_dev *dd,
+ const struct atmel_aes_reqctx *rctx)
+{
+   /* Clear all but persistent flags and set request flags. */
+   dd->flags = (dd->flags & AES_FLAGS_PERSISTENT) | rctx->mode;
+}
+
 static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err)
 {
struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
@@ -329,6 +342,34 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
 {
struct scatterlist sg[2];
struct dma_async_tx_descriptor  *in_desc, *out_desc;
+   enum dma_slave_buswidth addr_width;
+   u32 maxburst;
+
+   switch (dd->ctx->block_size) {
+   case CFB8_BLOCK_SIZE:
+   addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   maxburst = 1;
+   break;
+
+   case CFB16_BLOCK_SIZE:
+   addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   maxburst = 1;
+   break;
+
+   case CFB32_BLOCK_SIZE:
+   case CFB64_BLOCK_SIZE:
+   addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   maxburst = 1;
+   break;
+
+   case AES_BLOCK_SIZE:
+   addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   maxburst = dd->caps.max_burst_size;
+   break;
+
+   default:
+   return -EINVAL;
+   }
 
dd->dma_size = length;
 
@@ -337,35 +378,13 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
dma_sync_single_for_device(dd->dev, dma_addr_out, length,
   DMA_FROM_DEVICE);
 
-   if (dd->flags & AES_FLAGS_CFB8) {
-   dd->dma_lch_in.dma_conf.dst_addr_width =
-   DMA_SLAVE_BUSWIDTH_1_BYTE;
-   dd->dma_lch_out.dma_conf.src_addr_width =
-   DMA_SLAVE_BUSWIDTH_1_BYTE;
-   } else if (dd->flags & AES_FLAGS_CFB16) {
-   dd->dma_lch_in.dma_conf.dst_addr_width =
-   DMA_SLAVE_BUSWIDTH_2_BYTES;
-   dd->dma_lch_out.dma_conf.src_addr_width =
-   DMA_SLAVE_BUSWIDTH_2_BYTES;
-   } else {
-   dd->dma_lch_in.dma_conf.dst_addr_width =
-   DMA_SLAVE_BUSWIDTH_4_BYTES;
-   dd->dma_lch_out.dma_conf.src_addr_width =
-   DMA_SLAVE_BUSWIDTH_4_BYTES;
-   }
+   dd->dma_lch_in.dma_conf.dst_addr_width = addr_width;
+   dd->dma_lch_in.dma_conf.src_maxburst = maxburst;
+

[PATCH 07/24] crypto: atmel-aes: change atmel_aes_write_ctrl() signature

2015-12-17 Thread Cyrille Pitchen
This patch changes the signature of atmel_aes_write_ctrl() to make it more
generic. This will be used by future patches when implementing new block
cipher modes such as GCM.

Especially atmel_aes_hw_init() is now called outside
atmel_aes_write_ctrl(): this allows to call atmel_aes_write_ctrl() many
times, still initializing the hardware only once.

Indeed, the support of GCM will require to update the Mode Register and
the IV when processing a single request.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 24 ++--
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 9a9e1b88a384..ccb8a8322bf7 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -496,16 +496,11 @@ static int atmel_aes_crypt_dma_start(struct atmel_aes_dev 
*dd)
return err;
 }
 
-static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
+static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
+const u32 *iv)
 {
-   int err;
u32 valcr = 0, valmr = 0;
 
-   err = atmel_aes_hw_init(dd);
-
-   if (err)
-   return err;
-
/* MR register must be set before IV registers */
if (dd->ctx->keylen == AES_KEYSIZE_128)
valmr |= AES_MR_KEYSIZE_128;
@@ -539,7 +534,7 @@ static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
if (dd->flags & AES_FLAGS_ENCRYPT)
valmr |= AES_MR_CYPHER_ENC;
 
-   if (dd->total > ATMEL_AES_DMA_THRESHOLD) {
+   if (use_dma) {
valmr |= AES_MR_SMOD_IDATAR0;
if (dd->caps.has_dualbuff)
valmr |= AES_MR_DUALBUFF;
@@ -555,11 +550,9 @@ static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
 
if (((dd->flags & AES_FLAGS_CBC) || (dd->flags & AES_FLAGS_CFB) ||
   (dd->flags & AES_FLAGS_OFB) || (dd->flags & AES_FLAGS_CTR)) &&
-  dd->req->info) {
-   atmel_aes_write_n(dd, AES_IVR(0), dd->req->info, 4);
+  iv) {
+   atmel_aes_write_n(dd, AES_IVR(0), iv, 4);
}
-
-   return 0;
 }
 
 static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
@@ -570,6 +563,7 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
struct atmel_aes_reqctx *rctx;
unsigned long flags;
int err, ret = 0;
+   bool use_dma;
 
spin_lock_irqsave(>lock, flags);
if (req)
@@ -607,9 +601,11 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
dd->ctx = ctx;
ctx->dd = dd;
 
-   err = atmel_aes_write_ctrl(dd);
+   err = atmel_aes_hw_init(dd);
if (!err) {
-   if (dd->total > ATMEL_AES_DMA_THRESHOLD)
+   use_dma = (dd->total > ATMEL_AES_DMA_THRESHOLD);
+   atmel_aes_write_ctrl(dd, use_dma, req->info);
+   if (use_dma)
err = atmel_aes_crypt_dma_start(dd);
else
err = atmel_aes_crypt_cpu_start(dd);
-- 
1.8.2.2

--
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 08/24] crypto: atmel-aes: make crypto request queue management more generic

2015-12-17 Thread Cyrille Pitchen
This patch changes atmel_aes_handle_queue() to make it more generic.
The function argument is now a pointer to struct crypto_async_request,
which is the common base of struct ablkcipher_request and
struct aead_request.

Also this patch introduces struct atmel_aes_base_ctx which will be the
common base of all the transformation contexts.

Hence the very same queue will be used to manage both block cipher and
AEAD requests (such as gcm and authenc implemented in further patches).

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 75 ++
 1 file changed, 49 insertions(+), 26 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index ccb8a8322bf7..48407a7f6f61 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -78,8 +78,13 @@ struct atmel_aes_caps {
 
 struct atmel_aes_dev;
 
-struct atmel_aes_ctx {
+
+typedef int (*atmel_aes_fn_t)(struct atmel_aes_dev *);
+
+
+struct atmel_aes_base_ctx {
struct atmel_aes_dev *dd;
+   atmel_aes_fn_t  start;
 
int keylen;
u32 key[AES_KEYSIZE_256 / sizeof(u32)];
@@ -87,6 +92,10 @@ struct atmel_aes_ctx {
u16 block_size;
 };
 
+struct atmel_aes_ctx {
+   struct atmel_aes_base_ctx   base;
+};
+
 struct atmel_aes_reqctx {
unsigned long mode;
 };
@@ -101,7 +110,9 @@ struct atmel_aes_dev {
unsigned long   phys_base;
void __iomem*io_base;
 
-   struct atmel_aes_ctx*ctx;
+   struct crypto_async_request *areq;
+   struct atmel_aes_base_ctx   *ctx;
+
struct device   *dev;
struct clk  *iclk;
int irq;
@@ -115,7 +126,6 @@ struct atmel_aes_dev {
struct tasklet_struct   done_task;
struct tasklet_struct   queue_task;
 
-   struct ablkcipher_request   *req;
size_t  total;
 
struct scatterlist  *in_sg;
@@ -236,7 +246,7 @@ static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 
offset,
atmel_aes_write(dd, offset, *value);
 }
 
-static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
+static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_base_ctx *ctx)
 {
struct atmel_aes_dev *aes_dd = NULL;
struct atmel_aes_dev *tmp;
@@ -298,7 +308,7 @@ static int atmel_aes_hw_version_init(struct atmel_aes_dev 
*dd)
 
 static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err)
 {
-   struct ablkcipher_request *req = dd->req;
+   struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
 
clk_disable_unprepare(dd->iclk);
dd->flags &= ~AES_FLAGS_BUSY;
@@ -396,6 +406,8 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
 
 static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
 {
+   struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+
dd->flags &= ~AES_FLAGS_DMA;
 
dma_sync_single_for_cpu(dd->dev, dd->dma_addr_in,
@@ -404,11 +416,11 @@ static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev 
*dd)
dd->dma_size, DMA_FROM_DEVICE);
 
/* use cache buffers */
-   dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg);
+   dd->nb_in_sg = atmel_aes_sg_length(req, dd->in_sg);
if (!dd->nb_in_sg)
return -EINVAL;
 
-   dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg);
+   dd->nb_out_sg = atmel_aes_sg_length(req, dd->out_sg);
if (!dd->nb_out_sg)
return -EINVAL;
 
@@ -556,38 +568,49 @@ static void atmel_aes_write_ctrl(struct atmel_aes_dev 
*dd, bool use_dma,
 }
 
 static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
-  struct ablkcipher_request *req)
+ struct crypto_async_request *new_areq)
 {
-   struct crypto_async_request *async_req, *backlog;
-   struct atmel_aes_ctx *ctx;
-   struct atmel_aes_reqctx *rctx;
+   struct crypto_async_request *areq, *backlog;
+   struct atmel_aes_base_ctx *ctx;
unsigned long flags;
int err, ret = 0;
-   bool use_dma;
 
spin_lock_irqsave(>lock, flags);
-   if (req)
-   ret = ablkcipher_enqueue_request(>queue, req);
+   if (new_areq)
+   ret = crypto_enqueue_request(>queue, new_areq);
if (dd->flags & AES_FLAGS_BUSY) {
spin_unlock_irqrestore(>lock, flags);
return ret;
}
backlog = crypto_get_backlog(>queue);
-   async_req = crypto_dequeue_request(>queue);
-   if (async_req)
+   areq = crypto_dequeue_request(>queue);
+   if (areq)
dd->flags |= AES_FLAGS_BUSY;
spin_unlock_irqrestore(>lock, flags);
 
- 

[PATCH 05/24] crypto: atmel-aes: remove unused header includes

2015-12-17 Thread Cyrille Pitchen
Hash headers have nothing to do with AES block ciphers.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index e948bf2b8a8e..7d1b055811c4 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -33,12 +33,9 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include "atmel-aes-regs.h"
-- 
1.8.2.2

--
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 04/24] crypto: atmel-aes: fix unregistration order of crypto algorithms

2015-12-17 Thread Cyrille Pitchen
This dummy patch fixes atmel_aes_unregister_algs() so crypto algorithms
are unregistered in the reverse order they were registered by
atmel_aes_register_algs().

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index e545636a7ddc..e948bf2b8a8e 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -1219,10 +1219,11 @@ static void atmel_aes_unregister_algs(struct 
atmel_aes_dev *dd)
 {
int i;
 
-   for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
-   crypto_unregister_alg(_algs[i]);
if (dd->caps.has_cfb64)
crypto_unregister_alg(_cfb64_alg);
+
+   for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
+   crypto_unregister_alg(_algs[i]);
 }
 
 static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
-- 
1.8.2.2

--
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 13/24] crypto: atmel-aes: reduce latency of DMA completion

2015-12-17 Thread Cyrille Pitchen
atmel_aes_dma_callback() now directly calls the 'resume' callback instead
of scheduling the done task, which in turn only calls the very same
'resume' callback.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 25dc7bd73532..8a2b3e81c087 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -337,8 +337,8 @@ static void atmel_aes_dma_callback(void *data)
 {
struct atmel_aes_dev *dd = data;
 
-   /* dma_lch_out - completed */
-   tasklet_schedule(>done_task);
+   dd->is_async = true;
+   (void)dd->resume(dd);
 }
 
 static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
-- 
1.8.2.2

--
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 01/24] crypto: atmel-aes: add new version

2015-12-17 Thread Cyrille Pitchen
From: Leilei Zhao 

Add new version of atmel-aes available with SAMA5D2 devices.

Signed-off-by: Leilei Zhao 
---
 drivers/crypto/atmel-aes.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index bfb1f799bf56..854e2813b2bb 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -1258,6 +1258,11 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
 
/* keep only major version number */
switch (dd->hw_version & 0xff0) {
+   case 0x500:
+   dd->caps.has_dualbuff = 1;
+   dd->caps.has_cfb64 = 1;
+   dd->caps.max_burst_size = 4;
+   break;
case 0x200:
dd->caps.has_dualbuff = 1;
dd->caps.has_cfb64 = 1;
-- 
1.8.2.2

--
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 02/24] crypto: atmel-aes: constify value argument of atmel_aes_write_n()

2015-12-17 Thread Cyrille Pitchen
atmel_aes_write_n() should not modify its value argument.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 854e2813b2bb..1d3997a45610 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -231,7 +231,7 @@ static void atmel_aes_read_n(struct atmel_aes_dev *dd, u32 
offset,
 }
 
 static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset,
-   u32 *value, int count)
+ const u32 *value, int count)
 {
for (; count--; value++, offset += 4)
atmel_aes_write(dd, offset, *value);
-- 
1.8.2.2

--
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 15/24] crypto: atmel-aes: fix atmel_aes_remove()

2015-12-17 Thread Cyrille Pitchen
Add missing call to atmel_aes_buff_cleanup().

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 68e4177ad61b..343199cfed23 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -1469,6 +1469,7 @@ static int atmel_aes_remove(struct platform_device *pdev)
tasklet_kill(_dd->queue_task);
 
atmel_aes_dma_cleanup(aes_dd);
+   atmel_aes_buff_cleanup(aes_dd);
 
return 0;
 }
-- 
1.8.2.2

--
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 14/24] crypto: atmel-aes: remove useless AES_FLAGS_DMA flag

2015-12-17 Thread Cyrille Pitchen
Since the 'done' task code was split into atmel_aes_cpu_complete() and
atmel_aes_dma_complete(), the AES_FLAGS_DMA flag has become useless.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 37 +++--
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 8a2b3e81c087..68e4177ad61b 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -66,7 +66,6 @@
 
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
-#define AES_FLAGS_DMA  BIT(4)
 #define AES_FLAGS_FAST BIT(5)
 
 #define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
@@ -393,8 +392,6 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
dmaengine_slave_config(dd->dma_lch_in.chan, >dma_lch_in.dma_conf);
dmaengine_slave_config(dd->dma_lch_out.chan, >dma_lch_out.dma_conf);
 
-   dd->flags |= AES_FLAGS_DMA;
-
sg_init_table([0], 1);
sg_dma_address([0]) = dma_addr_in;
sg_dma_len([0]) = length;
@@ -433,8 +430,6 @@ static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev 
*dd)
 {
struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
 
-   dd->flags &= ~AES_FLAGS_DMA;
-
dma_sync_single_for_cpu(dd->dev, dd->dma_addr_in,
dd->dma_size, DMA_TO_DEVICE);
dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
@@ -642,25 +637,23 @@ static int atmel_aes_start(struct atmel_aes_dev *dd)
 
 static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev *dd)
 {
-   int err = -EINVAL;
+   int err = 0;
size_t count;
 
-   if (dd->flags & AES_FLAGS_DMA) {
-   err = 0;
-   if  (dd->flags & AES_FLAGS_FAST) {
-   dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
-   dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-   } else {
-   dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
-   dd->dma_size, DMA_FROM_DEVICE);
-
-   /* copy data */
-   count = atmel_aes_sg_copy(>out_sg, >out_offset,
-   dd->buf_out, dd->buflen, dd->dma_size, 1);
-   if (count != dd->dma_size) {
-   err = -EINVAL;
-   pr_err("not all data converted: %zu\n", count);
-   }
+   if  (dd->flags & AES_FLAGS_FAST) {
+   dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
+   dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+   } else {
+   dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
+   dd->dma_size, DMA_FROM_DEVICE);
+
+   /* copy data */
+   count = atmel_aes_sg_copy(>out_sg, >out_offset,
+ dd->buf_out, dd->buflen,
+ dd->dma_size, 1);
+   if (count != dd->dma_size) {
+   err = -EINVAL;
+   pr_err("not all data converted: %zu\n", count);
}
}
 
-- 
1.8.2.2

--
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 00/24] crypto: atmel-aes: global rework of the driver

2015-12-17 Thread Cyrille Pitchen
Hi all,

this series of patches is a global rework of the Atmel driver. Some
patches improve the performances whereas others fix some bugs like
the counter overflow in CTR mode.

It also updates some part of the code to make them more generic. For
instance the crypto request queue management supports both async block
cipher and AEAD requests, which allows us to add support the the GCM
mode. The support of the GCM mode is only available on sama5d4 and later.

This series is based on linux-next and was tested on sama5d2, sama5d3 and
sama5d4 boards. The driver implementation was validated using the tcrypt
module running modes:
- 10: ecb(aes), cbc(aes), ctr(aes), rfc3686(ctr(aes))
- 35: gcm(aes)

tcrypt speed test was run with modes:
- 211: rfc4106(gcm(aes)), gcm(aes)
- 500: ecb(aes), cbc(aes), ctr(aes), cfb(aes), ofc(aes), rfc3686(ctr(aes))

Finally iperf was run for at least 5 mins over an IPSEC/L2TP tunnel using
the rfc4106(gcm(aes)) cipher suite.


Changelog:

v1: initial version


Cyrille Pitchen (23):
  crypto: atmel-aes: constify value argument of atmel_aes_write_n()
  crypto: atmel-aes: change algorithm priorities
  crypto: atmel-aes: fix unregistration order of crypto algorithms
  crypto: atmel-aes: remove unused header includes
  crypto: atmel-aes: propagate error from atmel_aes_hw_version_init()
  crypto: atmel-aes: change atmel_aes_write_ctrl() signature
  crypto: atmel-aes: make crypto request queue management more generic
  crypto: atmel-aes: remove useless write in the Control Register
  crypto: atmel-aes: simplify the configuration of the AES IP
  crypto: atmel-aes: rework crypto request completion
  crypto: atmel-aes: remove unused 'err' member of struct atmel_aes_dev
  crypto: atmel-aes: reduce latency of DMA completion
  crypto: atmel-aes: remove useless AES_FLAGS_DMA flag
  crypto: atmel-aes: fix atmel_aes_remove()
  crypto: atmel-aes: improve performances of data transfer
  crypto: atmel-aes: use SIZE_IN_WORDS() helper macro
  crypto: atmel-aes: fix typo and indentation
  crypto: atmel-aes: create sections to regroup functions by usage
  crypto: atmel-aes: fix atmel-ctr-aes driver for RFC 3686
  crypto: atmel-aes: fix the counter overflow in CTR mode
  crypto: atmel-aes: change the DMA threshold
  crypto: atmel-aes: add support to GCM mode
  crypto: atmel-aes: add debug facilities to monitor register accesses.

Leilei Zhao (1):
  crypto: atmel-aes: add new version

 drivers/crypto/Kconfig  |1 +
 drivers/crypto/atmel-aes-regs.h |   10 +
 drivers/crypto/atmel-aes.c  | 1843 +++
 3 files changed, 1278 insertions(+), 576 deletions(-)

-- 
1.8.2.2

--
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 16/24] crypto: atmel-aes: improve performances of data transfer

2015-12-17 Thread Cyrille Pitchen
This patch totally reworks data transfer.

1 - DMA

The new code now fully supports scatter-gather lists hence reducing the
number of interrupts in some cases. Also buffer alignments are better
managed to avoid useless copies.

2 - CPU

The new code allows to use PIO accesses even when transferring more than
one AES block, so futher patches could tune the DMA threshold
(ATMEL_AES_DMA_THRESHOLD).
Moreover, CPU transfers now have a chance to be processed synchronously,
hence reducing the latency by avoiding context switches when possible
(less interrupts to process, less scheduling of the 'done' task).
Indeed the 'DATA READY' bit is polled only one time in the Interrupt
Status Register before enabling then waiting for the associated interrupt.
In some condition, this single poll is enough as the data have already
been processed by the AES hardware and so are ready.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 764 +++--
 1 file changed, 386 insertions(+), 378 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 343199cfed23..9ef38eca4ae7 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -42,11 +42,16 @@
 
 #define ATMEL_AES_PRIORITY 300
 
+#define ATMEL_AES_BUFFER_ORDER 2
+#define ATMEL_AES_BUFFER_SIZE  (PAGE_SIZE << ATMEL_AES_BUFFER_ORDER)
+
 #define CFB8_BLOCK_SIZE1
 #define CFB16_BLOCK_SIZE   2
 #define CFB32_BLOCK_SIZE   4
 #define CFB64_BLOCK_SIZE   8
 
+#define SIZE_IN_WORDS(x)   ((x) >> 2)
+
 /* AES flags */
 /* Reserve bits [18:16] [14:12] [0] for mode (same as for AES_MR) */
 #define AES_FLAGS_ENCRYPT  AES_MR_CYPHER_ENC
@@ -66,7 +71,6 @@
 
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
-#define AES_FLAGS_FAST BIT(5)
 
 #define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
 
@@ -106,8 +110,11 @@ struct atmel_aes_reqctx {
 };
 
 struct atmel_aes_dma {
-   struct dma_chan *chan;
-   struct dma_slave_config dma_conf;
+   struct dma_chan *chan;
+   struct scatterlist  *sg;
+   int nents;
+   unsigned intremainder;
+   unsigned intsg_len;
 };
 
 struct atmel_aes_dev {
@@ -120,6 +127,7 @@ struct atmel_aes_dev {
 
boolis_async;
atmel_aes_fn_t  resume;
+   atmel_aes_fn_t  cpu_transfer_complete;
 
struct device   *dev;
struct clk  *iclk;
@@ -133,28 +141,17 @@ struct atmel_aes_dev {
struct tasklet_struct   done_task;
struct tasklet_struct   queue_task;
 
-   size_t  total;
-
-   struct scatterlist  *in_sg;
-   unsigned intnb_in_sg;
-   size_t  in_offset;
-   struct scatterlist  *out_sg;
-   unsigned intnb_out_sg;
-   size_t  out_offset;
-
-   size_t  bufcnt;
-   size_t  buflen;
-   size_t  dma_size;
+   size_t  total;
+   size_t  datalen;
+   u32 *data;
 
-   void*buf_in;
-   int dma_in;
-   dma_addr_t  dma_addr_in;
-   struct atmel_aes_dmadma_lch_in;
+   struct atmel_aes_dmasrc;
+   struct atmel_aes_dmadst;
 
-   void*buf_out;
-   int dma_out;
-   dma_addr_t  dma_addr_out;
-   struct atmel_aes_dmadma_lch_out;
+   size_t  buflen;
+   void*buf;
+   struct scatterlist  aligned_sg;
+   struct scatterlist  *real_dst;
 
struct atmel_aes_caps   caps;
 
@@ -171,62 +168,6 @@ static struct atmel_aes_drv atmel_aes = {
.lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock),
 };
 
-static int atmel_aes_sg_length(struct ablkcipher_request *req,
-   struct scatterlist *sg)
-{
-   unsigned int total = req->nbytes;
-   int sg_nb;
-   unsigned int len;
-   struct scatterlist *sg_list;
-
-   sg_nb = 0;
-   sg_list = sg;
-   total = req->nbytes;
-
-   while (total) {
-   len = min(sg_list->length, total);
-
-   sg_nb++;
-   total -= len;
-
-   sg_list = sg_next(sg_list);
-   if (!sg_list)
-   total = 0;
-   }
-
-   return sg_nb;
-}
-
-static int atmel_aes_sg_copy(struct scatterlist **sg, size_t *offset,
-   void *buf, size_t buflen, size_t total, int out)
-{
-   size_t count, off = 0;
-
-   while (buflen && total) {
-   count = min((*sg)->length - *offset, total);
-   count = min(count, buflen);
-
-   if (!count)
-   return off;
-
-   scatterwalk_map_and_copy(buf + off, *sg, *offs

[PATCH 17/24] crypto: atmel-aes: use SIZE_IN_WORDS() helper macro

2015-12-17 Thread Cyrille Pitchen
This is a dummy cosmetic patch.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 9ef38eca4ae7..176ab3878583 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -689,10 +689,10 @@ static void atmel_aes_write_ctrl(struct atmel_aes_dev 
*dd, bool use_dma,
atmel_aes_write(dd, AES_MR, valmr);
 
atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
-   dd->ctx->keylen >> 2);
+ SIZE_IN_WORDS(dd->ctx->keylen));
 
if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
-   atmel_aes_write_n(dd, AES_IVR(0), iv, 4);
+   atmel_aes_write_block(dd, AES_IVR(0), iv);
 }
 
 static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
-- 
1.8.2.2

--
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 06/24] crypto: atmel-aes: propagate error from atmel_aes_hw_version_init()

2015-12-17 Thread Cyrille Pitchen
Before this patch atmel_aes_hw_version_init() had no returned value.
However it calls atmel_aes_hw_init(), which may fail. So check the
returned code of atmel_aes_hw_init() and propagate error if needed.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 7d1b055811c4..9a9e1b88a384 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -280,16 +280,20 @@ static inline unsigned int atmel_aes_get_version(struct 
atmel_aes_dev *dd)
return atmel_aes_read(dd, AES_HW_VERSION) & 0x0fff;
 }
 
-static void atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
+static int atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
 {
-   atmel_aes_hw_init(dd);
+   int err;
+
+   err = atmel_aes_hw_init(dd);
+   if (err)
+   return err;
 
dd->hw_version = atmel_aes_get_version(dd);
 
-   dev_info(dd->dev,
-   "version: 0x%x\n", dd->hw_version);
+   dev_info(dd->dev, "version: 0x%x\n", dd->hw_version);
 
clk_disable_unprepare(dd->iclk);
+   return 0;
 }
 
 static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err)
@@ -1407,7 +1411,9 @@ static int atmel_aes_probe(struct platform_device *pdev)
goto res_err;
}
 
-   atmel_aes_hw_version_init(aes_dd);
+   err = atmel_aes_hw_version_init(aes_dd);
+   if (err)
+   goto res_err;
 
atmel_aes_get_cap(aes_dd);
 
-- 
1.8.2.2

--
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 22/24] crypto: atmel-aes: change the DMA threshold

2015-12-17 Thread Cyrille Pitchen
Increase the DMA threshold to 256: PIO accesses offer better performances
than the DMA when processing small amounts of data.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index a34919f6b7d7..ea645b4ee997 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -76,7 +76,7 @@
 
 #define ATMEL_AES_QUEUE_LENGTH 50
 
-#define ATMEL_AES_DMA_THRESHOLD16
+#define ATMEL_AES_DMA_THRESHOLD256
 
 
 struct atmel_aes_caps {
-- 
1.8.2.2

--
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 21/24] crypto: atmel-aes: fix the counter overflow in CTR mode

2015-12-17 Thread Cyrille Pitchen
Depending on its hardware version, the AES IP provides either a 16 or a
32 bit counter. However the CTR mode expects the size of the counter to be
the same as the size of the cipher block, ie 128 bits for AES.
This patch detects and handles counter overflows.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 117 -
 1 file changed, 115 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 5f6dc48616c0..a34919f6b7d7 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -82,6 +82,7 @@
 struct atmel_aes_caps {
boolhas_dualbuff;
boolhas_cfb64;
+   boolhas_ctr32;
u32 max_burst_size;
 };
 
@@ -103,6 +104,15 @@ struct atmel_aes_ctx {
struct atmel_aes_base_ctx   base;
 };
 
+struct atmel_aes_ctr_ctx {
+   struct atmel_aes_base_ctx   base;
+
+   u32 iv[AES_BLOCK_SIZE / sizeof(u32)];
+   size_t  offset;
+   struct scatterlist  src[2];
+   struct scatterlist  dst[2];
+};
+
 struct atmel_aes_reqctx {
unsigned long   mode;
 };
@@ -762,6 +772,96 @@ static int atmel_aes_start(struct atmel_aes_dev *dd)
   atmel_aes_transfer_complete);
 }
 
+static inline struct atmel_aes_ctr_ctx *
+atmel_aes_ctr_ctx_cast(struct atmel_aes_base_ctx *ctx)
+{
+   return container_of(ctx, struct atmel_aes_ctr_ctx, base);
+}
+
+static int atmel_aes_ctr_transfer(struct atmel_aes_dev *dd)
+{
+   struct atmel_aes_ctr_ctx *ctx = atmel_aes_ctr_ctx_cast(dd->ctx);
+   struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+   struct scatterlist *src, *dst;
+   u32 ctr, blocks;
+   size_t datalen;
+   bool use_dma, fragmented = false;
+
+   /* Check for transfer completion. */
+   ctx->offset += dd->total;
+   if (ctx->offset >= req->nbytes)
+   return atmel_aes_transfer_complete(dd);
+
+   /* Compute data length. */
+   datalen = req->nbytes - ctx->offset;
+   blocks = DIV_ROUND_UP(datalen, AES_BLOCK_SIZE);
+   ctr = be32_to_cpu(ctx->iv[3]);
+   if (dd->caps.has_ctr32) {
+   /* Check 32bit counter overflow. */
+   u32 start = ctr;
+   u32 end = start + blocks - 1;
+
+   if (end < start) {
+   ctr |= 0x;
+   datalen = AES_BLOCK_SIZE * -start;
+   fragmented = true;
+   }
+   } else {
+   /* Check 16bit counter overflow. */
+   u16 start = ctr & 0x;
+   u16 end = start + (u16)blocks - 1;
+
+   if (blocks >> 16 || end < start) {
+   ctr |= 0x;
+   datalen = AES_BLOCK_SIZE * (0x1-start);
+   fragmented = true;
+   }
+   }
+   use_dma = (datalen >= ATMEL_AES_DMA_THRESHOLD);
+
+   /* Jump to offset. */
+   src = scatterwalk_ffwd(ctx->src, req->src, ctx->offset);
+   dst = ((req->src == req->dst) ? src :
+  scatterwalk_ffwd(ctx->dst, req->dst, ctx->offset));
+
+   /* Configure hardware. */
+   atmel_aes_write_ctrl(dd, use_dma, ctx->iv);
+   if (unlikely(fragmented)) {
+   /*
+* Increment the counter manually to cope with the hardware
+* counter overflow.
+*/
+   ctx->iv[3] = cpu_to_be32(ctr);
+   crypto_inc((u8 *)ctx->iv, AES_BLOCK_SIZE);
+   }
+
+   if (use_dma)
+   return atmel_aes_dma_start(dd, src, dst, datalen,
+  atmel_aes_ctr_transfer);
+
+   return atmel_aes_cpu_start(dd, src, dst, datalen,
+  atmel_aes_ctr_transfer);
+}
+
+static int atmel_aes_ctr_start(struct atmel_aes_dev *dd)
+{
+   struct atmel_aes_ctr_ctx *ctx = atmel_aes_ctr_ctx_cast(dd->ctx);
+   struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+   struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+   int err;
+
+   atmel_aes_set_mode(dd, rctx);
+
+   err = atmel_aes_hw_init(dd);
+   if (err)
+   return atmel_aes_complete(dd, err);
+
+   memcpy(ctx->iv, req->info, AES_BLOCK_SIZE);
+   ctx->offset = 0;
+   dd->total = 0;
+   return atmel_aes_ctr_transfer(dd);
+}
+
 static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
struct atmel_aes_base_ctx *ctx;
@@ -919,6 +1019,16 @@ static int atmel_aes_cra_init(struct crypto_tfm *tfm)
return 0;
 }
 
+static int atmel_aes_ctr_cra_init(struct crypto_tfm *tfm)
+{
+

[PATCH 23/24] crypto: atmel-aes: add support to GCM mode

2015-12-17 Thread Cyrille Pitchen
This patch adds support to the GCM mode.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/Kconfig  |   1 +
 drivers/crypto/atmel-aes-regs.h |  10 +
 drivers/crypto/atmel-aes.c  | 453 +++-
 3 files changed, 462 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 95dccdea4dd1..da9ab9649a14 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -380,6 +380,7 @@ config CRYPTO_DEV_ATMEL_AES
tristate "Support for Atmel AES hw accelerator"
depends on AT_XDMAC || AT_HDMAC || COMPILE_TEST
select CRYPTO_AES
+   select CRYPTO_AEAD
select CRYPTO_BLKCIPHER
help
  Some Atmel processors have AES hw accelerator.
diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
index 2786bb1a5aa0..6c2951bb70b1 100644
--- a/drivers/crypto/atmel-aes-regs.h
+++ b/drivers/crypto/atmel-aes-regs.h
@@ -9,6 +9,7 @@
 #defineAES_MR  0x04
 #define AES_MR_CYPHER_DEC  (0 << 0)
 #define AES_MR_CYPHER_ENC  (1 << 0)
+#define AES_MR_GTAGEN  (1 << 1)
 #defineAES_MR_DUALBUFF (1 << 3)
 #define AES_MR_PROCDLY_MASK(0xF << 4)
 #define AES_MR_PROCDLY_OFFSET  4
@@ -26,6 +27,7 @@
 #define AES_MR_OPMOD_OFB   (0x2 << 12)
 #define AES_MR_OPMOD_CFB   (0x3 << 12)
 #define AES_MR_OPMOD_CTR   (0x4 << 12)
+#define AES_MR_OPMOD_GCM   (0x5 << 12)
 #define AES_MR_LOD (0x1 << 15)
 #define AES_MR_CFBS_MASK   (0x7 << 16)
 #define AES_MR_CFBS_128b   (0x0 << 16)
@@ -44,6 +46,7 @@
 #defineAES_ISR 0x1C
 #define AES_INT_DATARDY(1 << 0)
 #define AES_INT_URAD   (1 << 8)
+#define AES_INT_TAGRDY (1 << 16)
 #define AES_ISR_URAT_MASK  (0xF << 12)
 #define AES_ISR_URAT_IDR_WR_PROC   (0x0 << 12)
 #define AES_ISR_URAT_ODR_RD_PROC   (0x1 << 12)
@@ -57,6 +60,13 @@
 #define AES_ODATAR(x)  (0x50 + ((x) * 0x04))
 #define AES_IVR(x) (0x60 + ((x) * 0x04))
 
+#define AES_AADLENR0x70
+#define AES_CLENR  0x74
+#define AES_GHASHR(x)  (0x78 + ((x) * 0x04))
+#define AES_TAGR(x)(0x88 + ((x) * 0x04))
+#define AES_CTRR   0x98
+#define AES_GCMHR(x)   (0x9c + ((x) * 0x04))
+
 #define AES_HW_VERSION 0xFC
 
 #endif /* __ATMEL_AES_REGS_H__ */
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index ea645b4ee997..0a37e5683c80 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "atmel-aes-regs.h"
@@ -53,8 +54,9 @@
 #define SIZE_IN_WORDS(x)   ((x) >> 2)
 
 /* AES flags */
-/* Reserve bits [18:16] [14:12] [0] for mode (same as for AES_MR) */
+/* Reserve bits [18:16] [14:12] [1:0] for mode (same as for AES_MR) */
 #define AES_FLAGS_ENCRYPT  AES_MR_CYPHER_ENC
+#define AES_FLAGS_GTAGEN   AES_MR_GTAGEN
 #define AES_FLAGS_OPMODE_MASK  (AES_MR_OPMOD_MASK | AES_MR_CFBS_MASK)
 #define AES_FLAGS_ECB  AES_MR_OPMOD_ECB
 #define AES_FLAGS_CBC  AES_MR_OPMOD_CBC
@@ -65,9 +67,11 @@
 #define AES_FLAGS_CFB16(AES_MR_OPMOD_CFB | AES_MR_CFBS_16b)
 #define AES_FLAGS_CFB8 (AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
 #define AES_FLAGS_CTR  AES_MR_OPMOD_CTR
+#define AES_FLAGS_GCM  AES_MR_OPMOD_GCM
 
 #define AES_FLAGS_MODE_MASK(AES_FLAGS_OPMODE_MASK |\
-AES_FLAGS_ENCRYPT)
+AES_FLAGS_ENCRYPT |\
+AES_FLAGS_GTAGEN)
 
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
@@ -83,6 +87,7 @@ struct atmel_aes_caps {
boolhas_dualbuff;
boolhas_cfb64;
boolhas_ctr32;
+   boolhas_gcm;
u32 max_burst_size;
 };
 
@@ -113,6 +118,22 @@ struct atmel_aes_ctr_ctx {
struct scatterlist  dst[2];
 };
 
+struct atmel_aes_gcm_ctx {
+   struct atmel_aes_base_ctx   base;
+
+   struct scatterlist  src[2];
+   struct scatterlist  dst[2];
+
+   u32 j0[AES_BLOCK_SIZE / sizeof(u32)];
+   u32 tag[AES_BLOCK_SIZE / sizeof(u32)];
+   u32 ghash[AES_BLOCK_SIZE / sizeof(u32)];
+   size_t  textlen;
+
+   const u32   *ghash_in;
+   u32 *ghash_out;
+   atmel_aes_fn_t  ghash_resume;
+};
+
 struct atmel_aes_reqctx {
unsigned long   mode;
 };
@@ -234,6 +255,12 @@ static inlin

[PATCH 20/24] crypto: atmel-aes: fix atmel-ctr-aes driver for RFC 3686

2015-12-17 Thread Cyrille Pitchen
crypto_rfc3686_alloc() in crypto/ctr.c expects to be used with a stream
cipher (alg->cra_blocksize == 1).

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index e964cb03cca5..5f6dc48616c0 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -1075,7 +1075,7 @@ static struct crypto_alg aes_algs[] = {
.cra_driver_name= "atmel-ctr-aes",
.cra_priority   = ATMEL_AES_PRIORITY,
.cra_flags  = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-   .cra_blocksize  = AES_BLOCK_SIZE,
+   .cra_blocksize  = 1,
.cra_ctxsize= sizeof(struct atmel_aes_ctx),
.cra_alignmask  = 0xf,
.cra_type   = _ablkcipher_type,
-- 
1.8.2.2

--
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 24/24] crypto: atmel-aes: add debug facilities to monitor register accesses.

2015-12-17 Thread Cyrille Pitchen
This feature should not be enabled in release but can be usefull for
developers who need to monitor register accesses at some specific places.
Set the AES_FLAGS_DUMP_REG flag inside dd->flags to start monitoring the
I/O accesses, clear it to stop monitoring.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 115 -
 1 file changed, 114 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 0a37e5683c80..5621612ee921 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -75,6 +75,7 @@
 
 #define AES_FLAGS_INIT BIT(2)
 #define AES_FLAGS_BUSY BIT(3)
+#define AES_FLAGS_DUMP_REG BIT(4)
 
 #define AES_FLAGS_PERSISTENT   (AES_FLAGS_INIT | AES_FLAGS_BUSY)
 
@@ -197,16 +198,128 @@ static struct atmel_aes_drv atmel_aes = {
.lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock),
 };
 
+#ifdef VERBOSE_DEBUG
+static const char *atmel_aes_reg_name(u32 offset, char *tmp, size_t sz)
+{
+   switch (offset) {
+   case AES_CR:
+   return "CR";
+
+   case AES_MR:
+   return "MR";
+
+   case AES_ISR:
+   return "ISR";
+
+   case AES_IMR:
+   return "IMR";
+
+   case AES_IER:
+   return "IER";
+
+   case AES_IDR:
+   return "IDR";
+
+   case AES_KEYWR(0):
+   case AES_KEYWR(1):
+   case AES_KEYWR(2):
+   case AES_KEYWR(3):
+   case AES_KEYWR(4):
+   case AES_KEYWR(5):
+   case AES_KEYWR(6):
+   case AES_KEYWR(7):
+   snprintf(tmp, sz, "KEYWR[%u]", (offset - AES_KEYWR(0)) >> 2);
+   break;
+
+   case AES_IDATAR(0):
+   case AES_IDATAR(1):
+   case AES_IDATAR(2):
+   case AES_IDATAR(3):
+   snprintf(tmp, sz, "IDATAR[%u]", (offset - AES_IDATAR(0)) >> 2);
+   break;
+
+   case AES_ODATAR(0):
+   case AES_ODATAR(1):
+   case AES_ODATAR(2):
+   case AES_ODATAR(3):
+   snprintf(tmp, sz, "ODATAR[%u]", (offset - AES_ODATAR(0)) >> 2);
+   break;
+
+   case AES_IVR(0):
+   case AES_IVR(1):
+   case AES_IVR(2):
+   case AES_IVR(3):
+   snprintf(tmp, sz, "IVR[%u]", (offset - AES_IVR(0)) >> 2);
+   break;
+
+   case AES_AADLENR:
+   return "AADLENR";
+
+   case AES_CLENR:
+   return "CLENR";
+
+   case AES_GHASHR(0):
+   case AES_GHASHR(1):
+   case AES_GHASHR(2):
+   case AES_GHASHR(3):
+   snprintf(tmp, sz, "GHASHR[%u]", (offset - AES_GHASHR(0)) >> 2);
+   break;
+
+   case AES_TAGR(0):
+   case AES_TAGR(1):
+   case AES_TAGR(2):
+   case AES_TAGR(3):
+   snprintf(tmp, sz, "TAGR[%u]", (offset - AES_TAGR(0)) >> 2);
+   break;
+
+   case AES_CTRR:
+   return "CTRR";
+
+   case AES_GCMHR(0):
+   case AES_GCMHR(1):
+   case AES_GCMHR(2):
+   case AES_GCMHR(3):
+   snprintf(tmp, sz, "GCMHR[%u]", (offset - AES_GCMHR(0)) >> 2);
+
+   default:
+   snprintf(tmp, sz, "0x%02x", offset);
+   break;
+   }
+
+   return tmp;
+}
+#endif /* VERBOSE_DEBUG */
+
 /* Shared functions */
 
 static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
 {
-   return readl_relaxed(dd->io_base + offset);
+   u32 value = readl_relaxed(dd->io_base + offset);
+
+#ifdef VERBOSE_DEBUG
+   if (dd->flags & AES_FLAGS_DUMP_REG) {
+   char tmp[16];
+
+   dev_vdbg(dd->dev, "read 0x%08x from %s\n", value,
+atmel_aes_reg_name(offset, tmp, sizeof(tmp)));
+   }
+#endif /* VERBOSE_DEBUG */
+
+   return value;
 }
 
 static inline void atmel_aes_write(struct atmel_aes_dev *dd,
u32 offset, u32 value)
 {
+#ifdef VERBOSE_DEBUG
+   if (dd->flags & AES_FLAGS_DUMP_REG) {
+   char tmp[16];
+
+   dev_vdbg(dd->dev, "write 0x%08x into %s\n", value,
+atmel_aes_reg_name(offset, tmp));
+   }
+#endif /* VERBOSE_DEBUG */
+
writel_relaxed(value, dd->io_base + offset);
 }
 
-- 
1.8.2.2

--
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 19/24] crypto: atmel-aes: create sections to regroup functions by usage

2015-12-17 Thread Cyrille Pitchen
This patch only creates sections to regroup functions by usage.
This will help to integrate the GCM support patch later by making the
difference between shared/common and specific code. Hence current
sections are:

- Shared functions: common code which will be reused by the GCM support.
- CPU transfer: handles transfers monitored by the CPU (PIO accesses).
- DMA transfer: handles transfers monitored by the DMA controller.
- AES async block ciphers: dedicated to the already supported block ciphers
- Probe functions: used to register all crypto algorithms.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 210 +++--
 1 file changed, 108 insertions(+), 102 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 208fa8dce7f7..e964cb03cca5 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -166,6 +166,7 @@ static struct atmel_aes_drv atmel_aes = {
.lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock),
 };
 
+/* Shared functions */
 
 static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
 {
@@ -302,6 +303,38 @@ static inline int atmel_aes_complete(struct atmel_aes_dev 
*dd, int err)
return err;
 }
 
+static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
+const u32 *iv)
+{
+   u32 valmr = 0;
+
+   /* MR register must be set before IV registers */
+   if (dd->ctx->keylen == AES_KEYSIZE_128)
+   valmr |= AES_MR_KEYSIZE_128;
+   else if (dd->ctx->keylen == AES_KEYSIZE_192)
+   valmr |= AES_MR_KEYSIZE_192;
+   else
+   valmr |= AES_MR_KEYSIZE_256;
+
+   valmr |= dd->flags & AES_FLAGS_MODE_MASK;
+
+   if (use_dma) {
+   valmr |= AES_MR_SMOD_IDATAR0;
+   if (dd->caps.has_dualbuff)
+   valmr |= AES_MR_DUALBUFF;
+   } else {
+   valmr |= AES_MR_SMOD_AUTO;
+   }
+
+   atmel_aes_write(dd, AES_MR, valmr);
+
+   atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
+ SIZE_IN_WORDS(dd->ctx->keylen));
+
+   if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
+   atmel_aes_write_block(dd, AES_IVR(0), iv);
+}
+
 
 /* CPU transfer */
 
@@ -661,38 +694,6 @@ static void atmel_aes_dma_callback(void *data)
(void)dd->resume(dd);
 }
 
-static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
-const u32 *iv)
-{
-   u32 valmr = 0;
-
-   /* MR register must be set before IV registers */
-   if (dd->ctx->keylen == AES_KEYSIZE_128)
-   valmr |= AES_MR_KEYSIZE_128;
-   else if (dd->ctx->keylen == AES_KEYSIZE_192)
-   valmr |= AES_MR_KEYSIZE_192;
-   else
-   valmr |= AES_MR_KEYSIZE_256;
-
-   valmr |= dd->flags & AES_FLAGS_MODE_MASK;
-
-   if (use_dma) {
-   valmr |= AES_MR_SMOD_IDATAR0;
-   if (dd->caps.has_dualbuff)
-   valmr |= AES_MR_DUALBUFF;
-   } else {
-   valmr |= AES_MR_SMOD_AUTO;
-   }
-
-   atmel_aes_write(dd, AES_MR, valmr);
-
-   atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
- SIZE_IN_WORDS(dd->ctx->keylen));
-
-   if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
-   atmel_aes_write_block(dd, AES_IVR(0), iv);
-}
-
 static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
  struct crypto_async_request *new_areq)
 {
@@ -730,6 +731,9 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
return (dd->is_async) ? ret : err;
 }
 
+
+/* AES async block ciphers */
+
 static int atmel_aes_transfer_complete(struct atmel_aes_dev *dd)
 {
return atmel_aes_complete(dd, 0);
@@ -758,26 +762,6 @@ static int atmel_aes_start(struct atmel_aes_dev *dd)
   atmel_aes_transfer_complete);
 }
 
-
-static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
-{
-   dd->buf = (void *)__get_free_pages(GFP_KERNEL, ATMEL_AES_BUFFER_ORDER);
-   dd->buflen = ATMEL_AES_BUFFER_SIZE;
-   dd->buflen &= ~(AES_BLOCK_SIZE - 1);
-
-   if (!dd->buf) {
-   dev_err(dd->dev, "unable to alloc pages.\n");
-   return -ENOMEM;
-   }
-
-   return 0;
-}
-
-static void atmel_aes_buff_cleanup(struct atmel_aes_dev *dd)
-{
-   free_page((unsigned long)dd->buf);
-}
-
 static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
struct atmel_aes_base_ctx *ctx;
@@ -817,56 +801,6 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, 
unsigned long mode)
return atmel_aes_handle_queue(dd, >base);
 }
 
-static bool atmel_aes_filt

[PATCH 18/24] crypto: atmel-aes: fix typo and indentation

2015-12-17 Thread Cyrille Pitchen
Dummy patch to fix typo and indentation.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/crypto/atmel-aes.c | 56 +-
 1 file changed, 25 insertions(+), 31 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 176ab3878583..208fa8dce7f7 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -80,9 +80,9 @@
 
 
 struct atmel_aes_caps {
-   boolhas_dualbuff;
-   boolhas_cfb64;
-   u32 max_burst_size;
+   boolhas_dualbuff;
+   boolhas_cfb64;
+   u32 max_burst_size;
 };
 
 struct atmel_aes_dev;
@@ -92,13 +92,11 @@ typedef int (*atmel_aes_fn_t)(struct atmel_aes_dev *);
 
 
 struct atmel_aes_base_ctx {
-   struct atmel_aes_dev *dd;
-   atmel_aes_fn_t  start;
-
-   int keylen;
-   u32 key[AES_KEYSIZE_256 / sizeof(u32)];
-
-   u16 block_size;
+   struct atmel_aes_dev*dd;
+   atmel_aes_fn_t  start;
+   int keylen;
+   u32 key[AES_KEYSIZE_256 / sizeof(u32)];
+   u16 block_size;
 };
 
 struct atmel_aes_ctx {
@@ -106,7 +104,7 @@ struct atmel_aes_ctx {
 };
 
 struct atmel_aes_reqctx {
-   unsigned long mode;
+   unsigned long   mode;
 };
 
 struct atmel_aes_dma {
@@ -131,7 +129,7 @@ struct atmel_aes_dev {
 
struct device   *dev;
struct clk  *iclk;
-   int irq;
+   int irq;
 
unsigned long   flags;
 
@@ -155,7 +153,7 @@ struct atmel_aes_dev {
 
struct atmel_aes_caps   caps;
 
-   u32 hw_version;
+   u32 hw_version;
 };
 
 struct atmel_aes_drv {
@@ -782,11 +780,11 @@ static void atmel_aes_buff_cleanup(struct atmel_aes_dev 
*dd)
 
 static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
-   struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx(
-   crypto_ablkcipher_reqtfm(req));
-   struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+   struct atmel_aes_base_ctx *ctx;
+   struct atmel_aes_reqctx *rctx;
struct atmel_aes_dev *dd;
 
+   ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
switch (mode & AES_FLAGS_OPMODE_MASK) {
case AES_FLAGS_CFB8:
ctx->block_size = CFB8_BLOCK_SIZE;
@@ -813,6 +811,7 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, 
unsigned long mode)
if (!dd)
return -ENODEV;
 
+   rctx = ablkcipher_request_ctx(req);
rctx->mode = mode;
 
return atmel_aes_handle_queue(dd, >base);
@@ -873,8 +872,9 @@ static int atmel_aes_setkey(struct crypto_ablkcipher *tfm, 
const u8 *key,
 {
struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx(tfm);
 
-   if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
-  keylen != AES_KEYSIZE_256) {
+   if (keylen != AES_KEYSIZE_128 &&
+   keylen != AES_KEYSIZE_192 &&
+   keylen != AES_KEYSIZE_256) {
crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
}
@@ -897,26 +897,22 @@ static int atmel_aes_ecb_decrypt(struct 
ablkcipher_request *req)
 
 static int atmel_aes_cbc_encrypt(struct ablkcipher_request *req)
 {
-   return atmel_aes_crypt(req,
-   AES_FLAGS_ENCRYPT | AES_FLAGS_CBC);
+   return atmel_aes_crypt(req, AES_FLAGS_CBC | AES_FLAGS_ENCRYPT);
 }
 
 static int atmel_aes_cbc_decrypt(struct ablkcipher_request *req)
 {
-   return atmel_aes_crypt(req,
-   AES_FLAGS_CBC);
+   return atmel_aes_crypt(req, AES_FLAGS_CBC);
 }
 
 static int atmel_aes_ofb_encrypt(struct ablkcipher_request *req)
 {
-   return atmel_aes_crypt(req,
-   AES_FLAGS_ENCRYPT | AES_FLAGS_OFB);
+   return atmel_aes_crypt(req, AES_FLAGS_OFB | AES_FLAGS_ENCRYPT);
 }
 
 static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req)
 {
-   return atmel_aes_crypt(req,
-   AES_FLAGS_OFB);
+   return atmel_aes_crypt(req, AES_FLAGS_OFB);
 }
 
 static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req)
@@ -971,14 +967,12 @@ static int atmel_aes_cfb8_decrypt(struct 
ablkcipher_request *req)
 
 static int atmel_aes_ctr_encrypt(struct ablkcipher_request *req)
 {
-   return atmel_aes_crypt(req,
-   AES_FLAGS_ENCRYPT | AES_FLAGS_CTR);
+   return atmel_aes_crypt(req, AES_FLAGS_CTR | AES_FLAGS_ENCRYPT);
 }
 
 static int atmel_aes_ctr_decrypt(struct ablkcipher_request *req)
 {
-   return atmel_aes_crypt(req,
-   AES_FLAGS_CTR);
+   return atmel_aes_crypt(req, AES_FLAGS_CTR);
 }
 
 static int atmel_aes_cra_init(struct crypto_tfm *tfm)
@@ -1196,7 +1190,

[PATCH 1/1] crypto: tcrypt: fix keysize argument of test_aead_speed for gcm(aes)

2015-11-17 Thread Cyrille Pitchen
The key sizes used by AES in GCM mode should be 128, 192 or 256 bits (16,
24 or 32 bytes).
There is no additional 4byte nonce as for RFC 4106.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 crypto/tcrypt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 46a4a757d478..270bc4b82bd9 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1789,7 +1789,7 @@ static int do_test(const char *alg, u32 type, u32 mask, 
int m)
test_aead_speed("rfc4106(gcm(aes))", ENCRYPT, sec,
NULL, 0, 16, 16, aead_speed_template_20);
test_aead_speed("gcm(aes)", ENCRYPT, sec,
-   NULL, 0, 16, 8, aead_speed_template_20);
+   NULL, 0, 16, 8, speed_template_16_24_32);
break;
 
case 212:
-- 
1.8.2.2

--
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] crypto: atmel: fix 64-bit warnings

2015-11-17 Thread Cyrille Pitchen
Hi Arnd,

I add my Acked-by to your patch.
By the way, I'm currently reworking this whole driver. So I take your
modifications into account for the new version as many parts of the source code
such as the part dealing with DMA transfers have changed a lot.

The new version fixes the 16 or 32bit counter overflow for the CTR mode,
adds support to the GCM mode and should increase the global performances
(the work is still in progress). For the GCM mode, it relies on the latest
updates from Herbert in linux-next to AEAD algorithms.
The tcrypt module was used to validate the new implementation of CTR and GCM
modes.


Updates in the Atmel SHA driver are also likely to follow.

Thanks for your contribution!

Best regards,

Cyrille

Le 17/11/2015 10:22, Arnd Bergmann a écrit :
> The atmel AES driver assumes that 'int' and 'size_t' are the same
> type in multiple locations, which the compiler warns about when
> building it for 64-bit systems:
> 
> In file included from ../drivers/crypto/atmel-aes.c:17:0:
> drivers/crypto/atmel-aes.c: In function 'atmel_aes_sg_copy':
> include/linux/kernel.h:724:17: warning: comparison of distinct pointer types 
> lacks a cast
> drivers/crypto/atmel-aes.c:448:11: note: in expansion of macro 'min'
> 
> drivers/crypto/atmel-aes.c: In function 'atmel_aes_crypt_dma_stop':
> include/linux/kern_levels.h:4:18: warning: format '%u' expects argument of 
> type 'unsigned int', but argument 2 has type 'size_t {aka long unsigned int}' 
> [-Wformat=]
> 
> This changes the format strings to use the %z modifier when printing
> a size_t, and makes sure that we use the correct size_t type where
> needed. In case of sg_dma_len(), the type of the result depends
> on CONFIG_NEED_SG_DMA_LENGTH, so we have to use min_t to get it to
> work in all configurations.
> 
> Signed-off-by: Arnd Bergmann <a...@arndb.de>
Acked-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
> 
> diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
> index fb16d812c8f5..bfb1f799bf56 100644
> --- a/drivers/crypto/atmel-aes.c
> +++ b/drivers/crypto/atmel-aes.c
> @@ -184,7 +184,7 @@ static int atmel_aes_sg_length(struct ablkcipher_request 
> *req,
>  static int atmel_aes_sg_copy(struct scatterlist **sg, size_t *offset,
>   void *buf, size_t buflen, size_t total, int out)
>  {
> - unsigned int count, off = 0;
> + size_t count, off = 0;
>  
>   while (buflen && total) {
>   count = min((*sg)->length - *offset, total);
> @@ -444,8 +444,8 @@ static int atmel_aes_crypt_dma_start(struct atmel_aes_dev 
> *dd)
>  
>  
>   if (fast)  {
> - count = min(dd->total, sg_dma_len(dd->in_sg));
> - count = min(count, sg_dma_len(dd->out_sg));
> + count = min_t(size_t, dd->total, sg_dma_len(dd->in_sg));
> + count = min_t(size_t, count, sg_dma_len(dd->out_sg));
>  
>   err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
>   if (!err) {
> @@ -639,7 +639,7 @@ static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev 
> *dd)
>   dd->buf_out, dd->buflen, dd->dma_size, 1);
>   if (count != dd->dma_size) {
>   err = -EINVAL;
> - pr_err("not all data converted: %u\n", count);
> + pr_err("not all data converted: %zu\n", count);
>   }
>   }
>   }
> @@ -666,7 +666,7 @@ static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
>   dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
>   dd->buflen, DMA_TO_DEVICE);
>   if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
> - dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
> + dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen);
>   err = -EINVAL;
>   goto err_map_in;
>   }
> @@ -674,7 +674,7 @@ static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
>   dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
>   dd->buflen, DMA_FROM_DEVICE);
>   if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
> - dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
> + dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen);
>   err = -EINVAL;
>   goto err_map_out;
>   }
> 
> --
> 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
> 

--
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