crypto: ccp - Add SHA-2 384- and 512-bit support
authorGary R Hook <gary.hook@amd.com>
Wed, 15 Mar 2017 18:20:43 +0000 (13:20 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 24 Mar 2017 14:02:54 +0000 (22:02 +0800)
Incorporate 384-bit and 512-bit hashing for a version 5 CCP
device

Signed-off-by: Gary R Hook <gary.hook@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/ccp/ccp-crypto-sha.c
drivers/crypto/ccp/ccp-crypto.h
drivers/crypto/ccp/ccp-ops.c
include/linux/ccp.h

index 84a652be42749f365dd81cff133917ebf1689c71..6b46eea94932e1e5e518d571748698ce3b9bd05b 100644 (file)
@@ -146,6 +146,12 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
        case CCP_SHA_TYPE_256:
                rctx->cmd.u.sha.ctx_len = SHA256_DIGEST_SIZE;
                break;
+       case CCP_SHA_TYPE_384:
+               rctx->cmd.u.sha.ctx_len = SHA384_DIGEST_SIZE;
+               break;
+       case CCP_SHA_TYPE_512:
+               rctx->cmd.u.sha.ctx_len = SHA512_DIGEST_SIZE;
+               break;
        default:
                /* Should never get here */
                break;
@@ -393,6 +399,22 @@ static struct ccp_sha_def sha_algs[] = {
                .digest_size    = SHA256_DIGEST_SIZE,
                .block_size     = SHA256_BLOCK_SIZE,
        },
+       {
+               .version        = CCP_VERSION(5, 0),
+               .name           = "sha384",
+               .drv_name       = "sha384-ccp",
+               .type           = CCP_SHA_TYPE_384,
+               .digest_size    = SHA384_DIGEST_SIZE,
+               .block_size     = SHA384_BLOCK_SIZE,
+       },
+       {
+               .version        = CCP_VERSION(5, 0),
+               .name           = "sha512",
+               .drv_name       = "sha512-ccp",
+               .type           = CCP_SHA_TYPE_512,
+               .digest_size    = SHA512_DIGEST_SIZE,
+               .block_size     = SHA512_BLOCK_SIZE,
+       },
 };
 
 static int ccp_register_hmac_alg(struct list_head *head,
index 8335b32e815e4203c67e2c06643a7fe023485809..95cce276413989caccd7d0b9acceece38367e9d1 100644 (file)
@@ -137,9 +137,11 @@ struct ccp_aes_cmac_exp_ctx {
        u8 buf[AES_BLOCK_SIZE];
 };
 
-/***** SHA related defines *****/
-#define MAX_SHA_CONTEXT_SIZE   SHA256_DIGEST_SIZE
-#define MAX_SHA_BLOCK_SIZE     SHA256_BLOCK_SIZE
+/* SHA-related defines
+ * These values must be large enough to accommodate any variant
+ */
+#define MAX_SHA_CONTEXT_SIZE   SHA512_DIGEST_SIZE
+#define MAX_SHA_BLOCK_SIZE     SHA512_BLOCK_SIZE
 
 struct ccp_sha_ctx {
        struct scatterlist opad_sg;
index f1396c3aedacc388b360ab5f789ab2604579df74..0d820802cd92a4087c7e3646a6a98b1f1b0af7c3 100644 (file)
@@ -41,6 +41,20 @@ static const __be32 ccp_sha256_init[SHA256_DIGEST_SIZE / sizeof(__be32)] = {
        cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
 };
 
+static const __be64 ccp_sha384_init[SHA512_DIGEST_SIZE / sizeof(__be64)] = {
+       cpu_to_be64(SHA384_H0), cpu_to_be64(SHA384_H1),
+       cpu_to_be64(SHA384_H2), cpu_to_be64(SHA384_H3),
+       cpu_to_be64(SHA384_H4), cpu_to_be64(SHA384_H5),
+       cpu_to_be64(SHA384_H6), cpu_to_be64(SHA384_H7),
+};
+
+static const __be64 ccp_sha512_init[SHA512_DIGEST_SIZE / sizeof(__be64)] = {
+       cpu_to_be64(SHA512_H0), cpu_to_be64(SHA512_H1),
+       cpu_to_be64(SHA512_H2), cpu_to_be64(SHA512_H3),
+       cpu_to_be64(SHA512_H4), cpu_to_be64(SHA512_H5),
+       cpu_to_be64(SHA512_H6), cpu_to_be64(SHA512_H7),
+};
+
 #define        CCP_NEW_JOBID(ccp)      ((ccp->vdata->version == CCP_VERSION(3, 0)) ? \
                                        ccp_gen_jobid(ccp) : 0)
 
@@ -955,6 +969,18 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
                        return -EINVAL;
                block_size = SHA256_BLOCK_SIZE;
                break;
+       case CCP_SHA_TYPE_384:
+               if (cmd_q->ccp->vdata->version < CCP_VERSION(4, 0)
+                   || sha->ctx_len < SHA384_DIGEST_SIZE)
+                       return -EINVAL;
+               block_size = SHA384_BLOCK_SIZE;
+               break;
+       case CCP_SHA_TYPE_512:
+               if (cmd_q->ccp->vdata->version < CCP_VERSION(4, 0)
+                   || sha->ctx_len < SHA512_DIGEST_SIZE)
+                       return -EINVAL;
+               block_size = SHA512_BLOCK_SIZE;
+               break;
        default:
                return -EINVAL;
        }
@@ -1042,6 +1068,21 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
                sb_count = 1;
                ooffset = ioffset = 0;
                break;
+       case CCP_SHA_TYPE_384:
+               digest_size = SHA384_DIGEST_SIZE;
+               init = (void *) ccp_sha384_init;
+               ctx_size = SHA512_DIGEST_SIZE;
+               sb_count = 2;
+               ioffset = 0;
+               ooffset = 2 * CCP_SB_BYTES - SHA384_DIGEST_SIZE;
+               break;
+       case CCP_SHA_TYPE_512:
+               digest_size = SHA512_DIGEST_SIZE;
+               init = (void *) ccp_sha512_init;
+               ctx_size = SHA512_DIGEST_SIZE;
+               sb_count = 2;
+               ooffset = ioffset = 0;
+               break;
        default:
                ret = -EINVAL;
                goto e_data;
@@ -1060,6 +1101,11 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
        op.u.sha.type = sha->type;
        op.u.sha.msg_bits = sha->msg_bits;
 
+       /* For SHA1/224/256 the context fits in a single (32-byte) SB entry;
+        * SHA384/512 require 2 adjacent SB slots, with the right half in the
+        * first slot, and the left half in the second. Each portion must then
+        * be in little endian format: use the 256-bit byte swap option.
+        */
        ret = ccp_init_dm_workarea(&ctx, cmd_q, sb_count * CCP_SB_BYTES,
                                   DMA_BIDIRECTIONAL);
        if (ret)
@@ -1071,6 +1117,13 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
                case CCP_SHA_TYPE_256:
                        memcpy(ctx.address + ioffset, init, ctx_size);
                        break;
+               case CCP_SHA_TYPE_384:
+               case CCP_SHA_TYPE_512:
+                       memcpy(ctx.address + ctx_size / 2, init,
+                              ctx_size / 2);
+                       memcpy(ctx.address, init + ctx_size / 2,
+                              ctx_size / 2);
+                       break;
                default:
                        ret = -EINVAL;
                        goto e_ctx;
@@ -1137,6 +1190,15 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
                                        sha->ctx, 0,
                                        digest_size);
                        break;
+               case CCP_SHA_TYPE_384:
+               case CCP_SHA_TYPE_512:
+                       ccp_get_dm_area(&ctx, 0,
+                                       sha->ctx, LSB_ITEM_SIZE - ooffset,
+                                       LSB_ITEM_SIZE);
+                       ccp_get_dm_area(&ctx, LSB_ITEM_SIZE + ooffset,
+                                       sha->ctx, 0,
+                                       LSB_ITEM_SIZE - ooffset);
+                       break;
                default:
                        ret = -EINVAL;
                        goto e_ctx;
@@ -1174,6 +1236,16 @@ static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
                               ctx.address + ooffset,
                               digest_size);
                        break;
+               case CCP_SHA_TYPE_384:
+               case CCP_SHA_TYPE_512:
+                       memcpy(hmac_buf + block_size,
+                              ctx.address + LSB_ITEM_SIZE + ooffset,
+                              LSB_ITEM_SIZE);
+                       memcpy(hmac_buf + block_size +
+                              (LSB_ITEM_SIZE - ooffset),
+                              ctx.address,
+                              LSB_ITEM_SIZE);
+                       break;
                default:
                        ret = -EINVAL;
                        goto e_ctx;
index c71dd8fa57640eab059ca21b2847609340b6b506..90a1fbe842193ee82aa30e15e648150af6c8ec49 100644 (file)
@@ -249,6 +249,8 @@ enum ccp_sha_type {
        CCP_SHA_TYPE_1 = 1,
        CCP_SHA_TYPE_224,
        CCP_SHA_TYPE_256,
+       CCP_SHA_TYPE_384,
+       CCP_SHA_TYPE_512,
        CCP_SHA_TYPE__LAST,
 };