Commit a7cf8658 authored by Pascal van Leeuwen's avatar Pascal van Leeuwen Committed by Herbert Xu
Browse files

crypto: inside-secure - Added support for CRC32



This patch adds support for the CRC32 "hash" algorithm

Signed-off-by: default avatarPascal van Leeuwen <pvanleeuwen@verimatrix.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 54ecb8f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1169,6 +1169,7 @@ static struct safexcel_alg_template *safexcel_algs[] = {
	&safexcel_alg_xts_aes,
	&safexcel_alg_gcm,
	&safexcel_alg_ccm,
	&safexcel_alg_crc32,
};

static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv)
+2 −0
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ struct safexcel_context_record {
#define CONTEXT_CONTROL_DIGEST_XCM		(0x2 << 21)
#define CONTEXT_CONTROL_DIGEST_HMAC		(0x3 << 21)
#define CONTEXT_CONTROL_CRYPTO_ALG_MD5		(0x0 << 23)
#define CONTEXT_CONTROL_CRYPTO_ALG_CRC32	(0x0 << 23)
#define CONTEXT_CONTROL_CRYPTO_ALG_SHA1		(0x2 << 23)
#define CONTEXT_CONTROL_CRYPTO_ALG_SHA224	(0x4 << 23)
#define CONTEXT_CONTROL_CRYPTO_ALG_SHA256	(0x3 << 23)
@@ -853,5 +854,6 @@ extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes;
extern struct safexcel_alg_template safexcel_alg_xts_aes;
extern struct safexcel_alg_template safexcel_alg_gcm;
extern struct safexcel_alg_template safexcel_alg_ccm;
extern struct safexcel_alg_template safexcel_alg_crc32;

#endif
+108 −7
Original line number Diff line number Diff line
@@ -82,23 +82,31 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
	struct safexcel_crypto_priv *priv = ctx->priv;
	u64 count = 0;

	cdesc->control_data.control0 |= ctx->alg;
	cdesc->control_data.control0 = ctx->alg;

	/*
	 * Copy the input digest if needed, and setup the context
	 * fields. Do this now as we need it to setup the first command
	 * descriptor.
	 */
	if (!req->processed) {
	if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
		ctx->base.ctxr->data[0] = req->state[0];

		cdesc->control_data.control0 |= req->digest |
			CONTEXT_CONTROL_TYPE_HASH_OUT  |
			CONTEXT_CONTROL_SIZE(4);

		return;
	} else if (!req->processed) {
		/* First - and possibly only - block of basic hash only */
		if (req->finish) {
			cdesc->control_data.control0 |=
			cdesc->control_data.control0 |= req->digest |
				CONTEXT_CONTROL_TYPE_HASH_OUT |
				CONTEXT_CONTROL_RESTART_HASH  |
				/* ensure its not 0! */
				CONTEXT_CONTROL_SIZE(1);
		} else {
			cdesc->control_data.control0 |=
			cdesc->control_data.control0 |= req->digest |
				CONTEXT_CONTROL_TYPE_HASH_OUT  |
				CONTEXT_CONTROL_RESTART_HASH   |
				CONTEXT_CONTROL_NO_FINISH_HASH |
@@ -238,9 +246,14 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
			return 1;
		}

		if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
			/* Undo final XOR with 0xffffffff ...*/
			*(u32 *)areq->result = ~sreq->state[0];
		} else {
			memcpy(areq->result, sreq->state,
			       crypto_ahash_digestsize(ahash));
		}
	}

	cache_len = safexcel_queued_len(sreq);
	if (cache_len)
@@ -599,7 +612,7 @@ static int safexcel_ahash_enqueue(struct ahash_request *areq)
		     /* invalidate for HMAC continuation finish */
		     (req->finish && (req->processed != req->block_sz)) ||
		     /* invalidate for HMAC finish with odigest changed */
		     (req->finish &&
		     (req->finish && req->hmac &&
		      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
			     ctx->opad, req->state_sz))))
			/*
@@ -692,6 +705,12 @@ static int safexcel_ahash_final(struct ahash_request *areq)
			memcpy(areq->result, sha512_zero_message_hash,
			       SHA512_DIGEST_SIZE);

		return 0;
	} else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
			    ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
			    req->len == sizeof(u32) && !areq->nbytes)) {
		/* Zero length CRC32 */
		memcpy(areq->result, ctx->ipad, sizeof(u32));
		return 0;
	} else if (unlikely(req->hmac &&
			    (req->len == req->block_sz) &&
@@ -1740,3 +1759,85 @@ struct safexcel_alg_template safexcel_alg_hmac_md5 = {
		},
	},
};

static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
{
	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
	int ret = safexcel_ahash_cra_init(tfm);

	/* Default 'key' is all zeroes */
	memset(ctx->ipad, 0, sizeof(u32));
	return ret;
}

static int safexcel_crc32_init(struct ahash_request *areq)
{
	struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
	struct safexcel_ahash_req *req = ahash_request_ctx(areq);

	memset(req, 0, sizeof(*req));

	/* Start from loaded key */
	req->state[0]	= cpu_to_le32(~ctx->ipad[0]);
	/* Set processed to non-zero to enable invalidation detection */
	req->len	= sizeof(u32);
	req->processed	= sizeof(u32);

	ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
	req->digest = CONTEXT_CONTROL_DIGEST_XCM;
	req->state_sz = sizeof(u32);
	req->block_sz = sizeof(u32);

	return 0;
}

static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
				 unsigned int keylen)
{
	struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));

	if (keylen != sizeof(u32)) {
		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
		return -EINVAL;
	}

	memcpy(ctx->ipad, key, sizeof(u32));
	return 0;
}

static int safexcel_crc32_digest(struct ahash_request *areq)
{
	return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
}

struct safexcel_alg_template safexcel_alg_crc32 = {
	.type = SAFEXCEL_ALG_TYPE_AHASH,
	.algo_mask = 0,
	.alg.ahash = {
		.init = safexcel_crc32_init,
		.update = safexcel_ahash_update,
		.final = safexcel_ahash_final,
		.finup = safexcel_ahash_finup,
		.digest = safexcel_crc32_digest,
		.setkey = safexcel_crc32_setkey,
		.export = safexcel_ahash_export,
		.import = safexcel_ahash_import,
		.halg = {
			.digestsize = sizeof(u32),
			.statesize = sizeof(struct safexcel_ahash_export_state),
			.base = {
				.cra_name = "crc32",
				.cra_driver_name = "safexcel-crc32",
				.cra_priority = SAFEXCEL_CRA_PRIORITY,
				.cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
					     CRYPTO_ALG_ASYNC |
					     CRYPTO_ALG_KERN_DRIVER_ONLY,
				.cra_blocksize = 1,
				.cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
				.cra_init = safexcel_crc32_cra_init,
				.cra_exit = safexcel_ahash_cra_exit,
				.cra_module = THIS_MODULE,
			},
		},
	},
};