diff mbox

[1/6] crypto: ccp - Add SHA-2 support

Message ID 20161013145248.19759.23166.stgit@taos (mailing list archive)
State Changes Requested
Delegated to: Herbert Xu
Headers show

Commit Message

Gary R Hook Oct. 13, 2016, 2:52 p.m. UTC
Incorporate 384-bit and 512-bit hashing for a version 5 CCP
device


Signed-off-by: Gary R Hook <gary.hook@amd.com>
---
 drivers/crypto/ccp/ccp-crypto-sha.c |   22 +++++++++++
 drivers/crypto/ccp/ccp-crypto.h     |    9 +++--
 drivers/crypto/ccp/ccp-ops.c        |   70 +++++++++++++++++++++++++++++++++++
 include/linux/ccp.h                 |    3 ++
 4 files changed, 101 insertions(+), 3 deletions(-)


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

Comments

Tom Lendacky Oct. 13, 2016, 7:35 p.m. UTC | #1
On 10/13/2016 09:52 AM, Gary R Hook wrote:
> Incorporate 384-bit and 512-bit hashing for a version 5 CCP
> device
> 
> 
> Signed-off-by: Gary R Hook <gary.hook@amd.com>
> ---
>  drivers/crypto/ccp/ccp-crypto-sha.c |   22 +++++++++++
>  drivers/crypto/ccp/ccp-crypto.h     |    9 +++--
>  drivers/crypto/ccp/ccp-ops.c        |   70 +++++++++++++++++++++++++++++++++++
>  include/linux/ccp.h                 |    3 ++
>  4 files changed, 101 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
> index 84a652b..6b46eea 100644
> --- a/drivers/crypto/ccp/ccp-crypto-sha.c
> +++ b/drivers/crypto/ccp/ccp-crypto-sha.c
> @@ -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,
> diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h
> index 8335b32..ae442ac 100644
> --- a/drivers/crypto/ccp/ccp-crypto.h
> +++ b/drivers/crypto/ccp/ccp-crypto.h
> @@ -137,9 +137,12 @@ 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;
> diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
> index 50fae44..8fedb14 100644
> --- a/drivers/crypto/ccp/ccp-ops.c
> +++ b/drivers/crypto/ccp/ccp-ops.c
> @@ -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)
>  
> @@ -963,6 +977,16 @@ 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 (sha->ctx_len < SHA384_DIGEST_SIZE)
> +			return -EINVAL;
> +		block_size = SHA384_BLOCK_SIZE;
> +		break;
> +	case CCP_SHA_TYPE_512:
> +		if (sha->ctx_len < SHA512_DIGEST_SIZE)
> +			return -EINVAL;
> +		block_size = SHA512_BLOCK_SIZE;
> +		break;

A version 3 CCP won't support these new sizes.  You should add a version
check and return an error if v3.

>  	default:
>  		return -EINVAL;
>  	}
> @@ -1050,6 +1074,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;
> @@ -1068,6 +1107,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)
> @@ -1079,6 +1123,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;
> @@ -1145,6 +1196,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;
> @@ -1182,6 +1242,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;
> diff --git a/include/linux/ccp.h b/include/linux/ccp.h
> index a765333..1a3e0b5 100644
> --- a/include/linux/ccp.h
> +++ b/include/linux/ccp.h
> @@ -249,8 +249,11 @@ 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,
>  };
> +#define	CCP_SHA_CTXSIZE		SHA512_DIGEST_SIZE

This doesn't appear to be used anywhere.

Thanks,
Tom

>  
>  /**
>   * struct ccp_sha_engine - CCP SHA operation
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
index 84a652b..6b46eea 100644
--- a/drivers/crypto/ccp/ccp-crypto-sha.c
+++ b/drivers/crypto/ccp/ccp-crypto-sha.c
@@ -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,
diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h
index 8335b32..ae442ac 100644
--- a/drivers/crypto/ccp/ccp-crypto.h
+++ b/drivers/crypto/ccp/ccp-crypto.h
@@ -137,9 +137,12 @@  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;
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index 50fae44..8fedb14 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -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)
 
@@ -963,6 +977,16 @@  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 (sha->ctx_len < SHA384_DIGEST_SIZE)
+			return -EINVAL;
+		block_size = SHA384_BLOCK_SIZE;
+		break;
+	case CCP_SHA_TYPE_512:
+		if (sha->ctx_len < SHA512_DIGEST_SIZE)
+			return -EINVAL;
+		block_size = SHA512_BLOCK_SIZE;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1050,6 +1074,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;
@@ -1068,6 +1107,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)
@@ -1079,6 +1123,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;
@@ -1145,6 +1196,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;
@@ -1182,6 +1242,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;
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
index a765333..1a3e0b5 100644
--- a/include/linux/ccp.h
+++ b/include/linux/ccp.h
@@ -249,8 +249,11 @@  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,
 };
+#define	CCP_SHA_CTXSIZE		SHA512_DIGEST_SIZE
 
 /**
  * struct ccp_sha_engine - CCP SHA operation