[RESEND PATCH v4 08/14] crypto: marvell/CESA: add MD5 support

2015-06-12 Thread Boris Brezillon
From: Arnaud Ebalard 

Add support for MD5 operations.

Signed-off-by: Arnaud Ebalard 
Signed-off-by: Boris Brezillon 
---
 drivers/crypto/marvell/cesa.c |   2 +
 drivers/crypto/marvell/cesa.h |   2 +
 drivers/crypto/marvell/hash.c | 170 +-
 3 files changed, 172 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index b9f4d26..b9da0df 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -174,7 +174,9 @@ static struct crypto_alg *armada_370_cipher_algs[] = {
 };
 
 static struct ahash_alg *armada_370_ahash_algs[] = {
+   &mv_md5_alg,
&mv_sha1_alg,
+   &mv_ahmac_md5_alg,
&mv_ahmac_sha1_alg,
 };
 
diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h
index d886280..23c4603 100644
--- a/drivers/crypto/marvell/cesa.h
+++ b/drivers/crypto/marvell/cesa.h
@@ -787,7 +787,9 @@ int mv_cesa_dma_add_op_transfers(struct mv_cesa_tdma_chain 
*chain,
 
 /* Algorithm definitions */
 
+extern struct ahash_alg mv_md5_alg;
 extern struct ahash_alg mv_sha1_alg;
+extern struct ahash_alg mv_ahmac_md5_alg;
 extern struct ahash_alg mv_ahmac_sha1_alg;
 
 extern struct crypto_alg mv_cesa_ecb_des_alg;
diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
index f9c6d47..63fa493 100644
--- a/drivers/crypto/marvell/hash.c
+++ b/drivers/crypto/marvell/hash.c
@@ -12,6 +12,7 @@
  * by the Free Software Foundation.
  */
 
+#include 
 #include 
 
 #include "cesa.h"
@@ -346,8 +347,16 @@ static int mv_cesa_ahash_process(struct 
crypto_async_request *req, u32 status)
   ahashreq->nbytes - creq->cache_ptr);
 
if (creq->last_req) {
-   for (i = 0; i < digsize / 4; i++)
-   creq->state[i] = cpu_to_be32(creq->state[i]);
+   for (i = 0; i < digsize / 4; i++) {
+   /*
+* Hardware provides MD5 digest in a different
+* endianness than SHA-1 and SHA-256 ones.
+*/
+   if (digsize == MD5_DIGEST_SIZE)
+   creq->state[i] = cpu_to_le32(creq->state[i]);
+   else
+   creq->state[i] = cpu_to_be32(creq->state[i]);
+   }
 
memcpy(ahashreq->result, creq->state, digsize);
}
@@ -786,6 +795,95 @@ static int mv_cesa_ahash_finup(struct ahash_request *req)
return ret;
 }
 
+static int mv_cesa_md5_init(struct ahash_request *req)
+{
+   struct mv_cesa_op_ctx tmpl;
+
+   mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
+
+   mv_cesa_ahash_init(req, &tmpl);
+
+   return 0;
+}
+
+static int mv_cesa_md5_export(struct ahash_request *req, void *out)
+{
+   struct md5_state *out_state = out;
+   struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+   struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+   unsigned int digsize = crypto_ahash_digestsize(ahash);
+
+   out_state->byte_count = creq->len;
+   memcpy(out_state->hash, creq->state, digsize);
+   memset(out_state->block, 0, sizeof(out_state->block));
+   if (creq->cache)
+   memcpy(out_state->block, creq->cache, creq->cache_ptr);
+
+   return 0;
+}
+
+static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+{
+   const struct md5_state *in_state = in;
+   struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+   struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+   unsigned int digsize = crypto_ahash_digestsize(ahash);
+   unsigned int cache_ptr;
+   int ret;
+
+   creq->len = in_state->byte_count;
+   memcpy(creq->state, in_state->hash, digsize);
+   creq->cache_ptr = 0;
+
+   cache_ptr = creq->len % sizeof(in_state->block);
+   if (!cache_ptr)
+   return 0;
+
+   ret = mv_cesa_ahash_alloc_cache(req);
+   if (ret)
+   return ret;
+
+   memcpy(creq->cache, in_state->block, cache_ptr);
+   creq->cache_ptr = cache_ptr;
+
+   return 0;
+}
+
+static int mv_cesa_md5_digest(struct ahash_request *req)
+{
+   int ret;
+
+   ret = mv_cesa_md5_init(req);
+   if (ret)
+   return ret;
+
+   return mv_cesa_ahash_finup(req);
+}
+
+struct ahash_alg mv_md5_alg = {
+   .init = mv_cesa_md5_init,
+   .update = mv_cesa_ahash_update,
+   .final = mv_cesa_ahash_final,
+   .finup = mv_cesa_ahash_finup,
+   .digest = mv_cesa_md5_digest,
+   .export = mv_cesa_md5_export,
+   .import = mv_cesa_md5_import,
+   .halg = {
+   .digestsize = MD5_DIGEST_SIZE,
+   .base = {
+   .cra_name = "md5",
+   .cra_driver_name = "mv-md5",
+   .cra_priority = 300,
+   .cra_flags = CRYPTO_ALG_ASYNC |
+  

[PATCH v4 08/14] crypto: marvell/CESA: add MD5 support

2015-06-11 Thread Boris Brezillon
From: Arnaud Ebalard 

Add support for MD5 operations.

Signed-off-by: Arnaud Ebalard 
Signed-off-by: Boris Brezillon 
---
 drivers/crypto/marvell/cesa.c |   2 +
 drivers/crypto/marvell/cesa.h |   2 +
 drivers/crypto/marvell/hash.c | 170 +-
 3 files changed, 172 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index b9f4d26..b9da0df 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -174,7 +174,9 @@ static struct crypto_alg *armada_370_cipher_algs[] = {
 };
 
 static struct ahash_alg *armada_370_ahash_algs[] = {
+   &mv_md5_alg,
&mv_sha1_alg,
+   &mv_ahmac_md5_alg,
&mv_ahmac_sha1_alg,
 };
 
diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h
index d886280..23c4603 100644
--- a/drivers/crypto/marvell/cesa.h
+++ b/drivers/crypto/marvell/cesa.h
@@ -787,7 +787,9 @@ int mv_cesa_dma_add_op_transfers(struct mv_cesa_tdma_chain 
*chain,
 
 /* Algorithm definitions */
 
+extern struct ahash_alg mv_md5_alg;
 extern struct ahash_alg mv_sha1_alg;
+extern struct ahash_alg mv_ahmac_md5_alg;
 extern struct ahash_alg mv_ahmac_sha1_alg;
 
 extern struct crypto_alg mv_cesa_ecb_des_alg;
diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
index f9c6d47..63fa493 100644
--- a/drivers/crypto/marvell/hash.c
+++ b/drivers/crypto/marvell/hash.c
@@ -12,6 +12,7 @@
  * by the Free Software Foundation.
  */
 
+#include 
 #include 
 
 #include "cesa.h"
@@ -346,8 +347,16 @@ static int mv_cesa_ahash_process(struct 
crypto_async_request *req, u32 status)
   ahashreq->nbytes - creq->cache_ptr);
 
if (creq->last_req) {
-   for (i = 0; i < digsize / 4; i++)
-   creq->state[i] = cpu_to_be32(creq->state[i]);
+   for (i = 0; i < digsize / 4; i++) {
+   /*
+* Hardware provides MD5 digest in a different
+* endianness than SHA-1 and SHA-256 ones.
+*/
+   if (digsize == MD5_DIGEST_SIZE)
+   creq->state[i] = cpu_to_le32(creq->state[i]);
+   else
+   creq->state[i] = cpu_to_be32(creq->state[i]);
+   }
 
memcpy(ahashreq->result, creq->state, digsize);
}
@@ -786,6 +795,95 @@ static int mv_cesa_ahash_finup(struct ahash_request *req)
return ret;
 }
 
+static int mv_cesa_md5_init(struct ahash_request *req)
+{
+   struct mv_cesa_op_ctx tmpl;
+
+   mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
+
+   mv_cesa_ahash_init(req, &tmpl);
+
+   return 0;
+}
+
+static int mv_cesa_md5_export(struct ahash_request *req, void *out)
+{
+   struct md5_state *out_state = out;
+   struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+   struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+   unsigned int digsize = crypto_ahash_digestsize(ahash);
+
+   out_state->byte_count = creq->len;
+   memcpy(out_state->hash, creq->state, digsize);
+   memset(out_state->block, 0, sizeof(out_state->block));
+   if (creq->cache)
+   memcpy(out_state->block, creq->cache, creq->cache_ptr);
+
+   return 0;
+}
+
+static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+{
+   const struct md5_state *in_state = in;
+   struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+   struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+   unsigned int digsize = crypto_ahash_digestsize(ahash);
+   unsigned int cache_ptr;
+   int ret;
+
+   creq->len = in_state->byte_count;
+   memcpy(creq->state, in_state->hash, digsize);
+   creq->cache_ptr = 0;
+
+   cache_ptr = creq->len % sizeof(in_state->block);
+   if (!cache_ptr)
+   return 0;
+
+   ret = mv_cesa_ahash_alloc_cache(req);
+   if (ret)
+   return ret;
+
+   memcpy(creq->cache, in_state->block, cache_ptr);
+   creq->cache_ptr = cache_ptr;
+
+   return 0;
+}
+
+static int mv_cesa_md5_digest(struct ahash_request *req)
+{
+   int ret;
+
+   ret = mv_cesa_md5_init(req);
+   if (ret)
+   return ret;
+
+   return mv_cesa_ahash_finup(req);
+}
+
+struct ahash_alg mv_md5_alg = {
+   .init = mv_cesa_md5_init,
+   .update = mv_cesa_ahash_update,
+   .final = mv_cesa_ahash_final,
+   .finup = mv_cesa_ahash_finup,
+   .digest = mv_cesa_md5_digest,
+   .export = mv_cesa_md5_export,
+   .import = mv_cesa_md5_import,
+   .halg = {
+   .digestsize = MD5_DIGEST_SIZE,
+   .base = {
+   .cra_name = "md5",
+   .cra_driver_name = "mv-md5",
+   .cra_priority = 300,
+   .cra_flags = CRYPTO_ALG_ASYNC |
+