[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20260121132408.743777-4-t-pratham@ti.com>
Date: Wed, 21 Jan 2026 18:54:07 +0530
From: T Pratham <t-pratham@...com>
To: T Pratham <t-pratham@...com>, Herbert Xu <herbert@...dor.apana.org.au>,
"David S. Miller" <davem@...emloft.net>
CC: Manorit Chawdhry <m-chawdhry@...com>, Kamlesh Gurudasani <kamlesh@...com>,
Shiva Tripathi <s-tripathi1@...com>, Kavitha Malarvizhi
<k-malarvizhi@...com>, Vishal Mahaveer <vishalm@...com>, Praneeth Bajjuri
<praneeth@...com>, <linux-crypto@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH v2 3/3] crypto: ti - Add support for HMAC in DTHEv2 Hashing Engine driver
Add support for HMAC-SHA512/384/256/224 and HMAC-MD5 algorithms in the
hashing engine of the DTHEv2 hardware cryptographic engine.
Signed-off-by: T Pratham <t-pratham@...com>
---
drivers/crypto/ti/Kconfig | 1 +
drivers/crypto/ti/dthev2-common.h | 10 +-
drivers/crypto/ti/dthev2-hash.c | 290 +++++++++++++++++++++++++++++-
3 files changed, 296 insertions(+), 5 deletions(-)
diff --git a/drivers/crypto/ti/Kconfig b/drivers/crypto/ti/Kconfig
index 9c2aa50cfbfbe..68dccf92f5382 100644
--- a/drivers/crypto/ti/Kconfig
+++ b/drivers/crypto/ti/Kconfig
@@ -13,6 +13,7 @@ config CRYPTO_DEV_TI_DTHEV2
select CRYPTO_SHA256
select CRYPTO_SHA512
select CRYPTO_MD5
+ select CRYPTO_HMAC
select SG_SPLIT
help
This enables support for the TI DTHE V2 hw cryptography engine
diff --git a/drivers/crypto/ti/dthev2-common.h b/drivers/crypto/ti/dthev2-common.h
index c305eca26ce82..2027dda0b5bdb 100644
--- a/drivers/crypto/ti/dthev2-common.h
+++ b/drivers/crypto/ti/dthev2-common.h
@@ -31,9 +31,9 @@
#define DTHE_DMA_TIMEOUT_MS 2000
/*
* Size of largest possible key (of all algorithms) to be stored in dthe_tfm_ctx
- * This is currently the keysize of XTS-AES-256 which is 512 bits (64 bytes)
+ * This is currently the keysize of HMAC-SHA512 which is 1024 bits (128 bytes)
*/
-#define DTHE_MAX_KEYSIZE (AES_MAX_KEY_SIZE * 2)
+#define DTHE_MAX_KEYSIZE (SHA512_BLOCK_SIZE)
enum dthe_hash_alg_sel {
DTHE_HASH_MD5 = 0,
@@ -93,9 +93,9 @@ struct dthe_list {
/**
* struct dthe_tfm_ctx - Transform ctx struct containing ctx for all sub-components of DTHE V2
* @dev_data: Device data struct pointer
- * @keylen: AES key length
+ * @keylen: Key length for algorithms that use a key
* @authsize: Authentication size for modes with authentication
- * @key: AES key
+ * @key: Buffer storing the key
* @aes_mode: AES mode
* @hash_mode: Hashing Engine mode
* @phash_size: partial hash size of the hash algorithm selected
@@ -135,6 +135,7 @@ struct dthe_aes_req_ctx {
* @phash: buffer to store a partial hash from a previous operation
* @digestcnt: stores the digest count from a previous operation; currently hardware only provides
* a single 32-bit value even for SHA384/512
+ * @odigest: buffer to store the outer digest from a previous operation
* @phash_available: flag indicating if a partial hash from a previous operation is available
* @flags: flags for internal use
* @padding: padding buffer for handling unaligned data
@@ -143,6 +144,7 @@ struct dthe_aes_req_ctx {
struct dthe_hash_req_ctx {
u32 phash[SHA512_DIGEST_SIZE / sizeof(u32)];
u64 digestcnt[2];
+ u32 odigest[SHA512_DIGEST_SIZE / sizeof(u32)];
u8 phash_available;
u8 flags;
u8 padding[SHA512_BLOCK_SIZE];
diff --git a/drivers/crypto/ti/dthev2-hash.c b/drivers/crypto/ti/dthev2-hash.c
index e4efcad375bf9..ca4a0a724b4d9 100644
--- a/drivers/crypto/ti/dthev2-hash.c
+++ b/drivers/crypto/ti/dthev2-hash.c
@@ -23,6 +23,7 @@
/* Registers */
#define DTHE_P_HASH_BASE 0x5000
+#define DTHE_P_HASH512_ODIGEST_A 0x0200
#define DTHE_P_HASH512_IDIGEST_A 0x0240
#define DTHE_P_HASH512_DIGEST_COUNT 0x0280
#define DTHE_P_HASH512_MODE 0x0284
@@ -45,6 +46,13 @@
#define DTHE_HASH_MODE_USE_ALG_CONST BIT(3)
#define DTHE_HASH_MODE_CLOSE_HASH BIT(4)
+#define DTHE_HASH_MODE_HMAC_KEY_PROCESSING BIT(5)
+#define DTHE_HASH_MODE_HMAC_OUTER_HASH BIT(7)
+
+/* Misc */
+#define DTHE_HMAC_SHA512_MAX_KEYSIZE (SHA512_BLOCK_SIZE)
+#define DTHE_HMAC_SHA256_MAX_KEYSIZE (SHA256_BLOCK_SIZE)
+#define DTHE_HMAC_MD5_MAX_KEYSIZE (MD5_BLOCK_SIZE)
enum dthe_hash_op {
DTHE_HASH_OP_UPDATE = 0,
@@ -74,6 +82,19 @@ static void dthe_hash_write_zero_message(enum dthe_hash_alg_sel mode, void *dst)
}
}
+static int dthe_hmac_write_zero_message(struct ahash_request *req)
+{
+ HASH_FBREQ_ON_STACK(fbreq, req);
+ int ret;
+
+ ahash_request_set_crypt(fbreq, req->src, req->result,
+ req->nbytes);
+
+ ret = crypto_ahash_digest(fbreq);
+ HASH_REQUEST_ZERO(fbreq);
+ return ret;
+}
+
static enum dthe_hash_alg_sel dthe_hash_get_hash_mode(struct crypto_ahash *tfm)
{
unsigned int ds = crypto_ahash_digestsize(tfm);
@@ -184,6 +205,7 @@ static int dthe_hash_dma_start(struct ahash_request *req, struct scatterlist *sr
enum dma_data_direction src_dir = DMA_TO_DEVICE;
u32 hash_mode;
int ds = crypto_ahash_digestsize(tfm);
+ bool is_hmac = (ctx->keylen > 0);
int ret = 0;
u32 *dst;
u32 dst_len;
@@ -229,8 +251,11 @@ static int dthe_hash_dma_start(struct ahash_request *req, struct scatterlist *sr
hash_mode = ctx->hash_mode;
- if (rctx->flags == DTHE_HASH_OP_FINUP)
+ if (rctx->flags == DTHE_HASH_OP_FINUP) {
hash_mode |= DTHE_HASH_MODE_CLOSE_HASH;
+ if (is_hmac)
+ hash_mode |= DTHE_HASH_MODE_HMAC_OUTER_HASH;
+ }
if (rctx->phash_available) {
for (int i = 0; i < ctx->phash_size / sizeof(u32); ++i)
@@ -238,9 +263,28 @@ static int dthe_hash_dma_start(struct ahash_request *req, struct scatterlist *sr
sha_base_reg +
DTHE_P_HASH512_IDIGEST_A +
(DTHE_REG_SIZE * i));
+ if (is_hmac) {
+ for (int i = 0; i < ctx->phash_size / sizeof(u32); ++i)
+ writel_relaxed(rctx->odigest[i],
+ sha_base_reg +
+ DTHE_P_HASH512_ODIGEST_A +
+ (DTHE_REG_SIZE * i));
+ }
writel_relaxed(rctx->digestcnt[0],
sha_base_reg + DTHE_P_HASH512_DIGEST_COUNT);
+ } else if (is_hmac) {
+ hash_mode |= DTHE_HASH_MODE_HMAC_KEY_PROCESSING;
+
+ for (int i = 0; i < (ctx->keylen / 2) / sizeof(u32); ++i)
+ writel_relaxed(ctx->key[i], sha_base_reg +
+ DTHE_P_HASH512_ODIGEST_A +
+ (DTHE_REG_SIZE * i));
+ for (int i = 0; i < (ctx->keylen / 2) / sizeof(u32); ++i)
+ writel_relaxed(ctx->key[i + (ctx->keylen / 2) / sizeof(u32)],
+ sha_base_reg +
+ DTHE_P_HASH512_IDIGEST_A +
+ (DTHE_REG_SIZE * i));
} else {
hash_mode |= DTHE_HASH_MODE_USE_ALG_CONST;
}
@@ -275,6 +319,12 @@ static int dthe_hash_dma_start(struct ahash_request *req, struct scatterlist *sr
dst[i] = readl_relaxed(sha_base_reg +
DTHE_P_HASH512_IDIGEST_A +
(DTHE_REG_SIZE * i));
+ if (is_hmac) {
+ for (int i = 0; i < dst_len; ++i)
+ rctx->odigest[i] = readl_relaxed(sha_base_reg +
+ DTHE_P_HASH512_ODIGEST_A +
+ (DTHE_REG_SIZE * i));
+ }
rctx->digestcnt[0] = readl_relaxed(sha_base_reg + DTHE_P_HASH512_DIGEST_COUNT);
rctx->phash_available = 1;
@@ -399,6 +449,10 @@ static int dthe_hash_final(struct ahash_request *req)
return crypto_transfer_hash_request_to_engine(engine, req);
}
+ if (ctx->keylen > 0)
+ /* HMAC with zero-length message */
+ return dthe_hmac_write_zero_message(req);
+
dthe_hash_write_zero_message(ctx->hash_mode, req->result);
return 0;
@@ -432,6 +486,11 @@ static int dthe_hash_export(struct ahash_request *req, void *out)
if (ctx->phash_size >= SHA512_DIGEST_SIZE)
put_unaligned(rctx->digestcnt[1], p.u64++);
+ if (ctx->keylen > 0) {
+ memcpy(p.u8, rctx->odigest, ctx->phash_size);
+ p.u8 += ctx->phash_size;
+ }
+
return 0;
}
@@ -452,9 +511,68 @@ static int dthe_hash_import(struct ahash_request *req, const void *in)
rctx->digestcnt[1] = get_unaligned(p.u64++);
rctx->phash_available = ((rctx->digestcnt[0]) ? 1 : 0);
+ if (ctx->keylen > 0) {
+ memcpy(rctx->odigest, p.u8, ctx->phash_size);
+ p.u8 += ctx->phash_size;
+ }
+
return 0;
}
+static int dthe_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct dthe_tfm_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct crypto_ahash *fb = crypto_ahash_fb(tfm);
+ unsigned int max_keysize;
+ const char *hash_alg_name;
+
+ memzero_explicit(ctx->key, sizeof(ctx->key));
+
+ switch (ctx->hash_mode) {
+ case DTHE_HASH_SHA512:
+ hash_alg_name = "sha512";
+ max_keysize = DTHE_HMAC_SHA512_MAX_KEYSIZE;
+ break;
+ case DTHE_HASH_SHA384:
+ hash_alg_name = "sha384";
+ max_keysize = DTHE_HMAC_SHA512_MAX_KEYSIZE;
+ break;
+ case DTHE_HASH_SHA256:
+ hash_alg_name = "sha256";
+ max_keysize = DTHE_HMAC_SHA256_MAX_KEYSIZE;
+ break;
+ case DTHE_HASH_SHA224:
+ hash_alg_name = "sha224";
+ max_keysize = DTHE_HMAC_SHA256_MAX_KEYSIZE;
+ break;
+ case DTHE_HASH_MD5:
+ hash_alg_name = "md5";
+ max_keysize = DTHE_HMAC_MD5_MAX_KEYSIZE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (keylen > max_keysize) {
+ struct crypto_shash *ktfm = crypto_alloc_shash(hash_alg_name, 0, 0);
+ SHASH_DESC_ON_STACK(desc, ktfm);
+ int err;
+
+ desc->tfm = ktfm;
+ err = crypto_shash_digest(desc, key, keylen, (u8 *)ctx->key);
+ crypto_free_shash(ktfm);
+ if (err)
+ return err;
+ } else {
+ memcpy(ctx->key, key, keylen);
+ }
+
+ ctx->keylen = max_keysize;
+
+ return crypto_ahash_setkey(fb, key, keylen);
+}
+
static struct ahash_engine_alg hash_algs[] = {
{
.base.init_tfm = dthe_hash_init_tfm,
@@ -621,6 +739,176 @@ static struct ahash_engine_alg hash_algs[] = {
},
.op.do_one_request = dthe_hash_run,
},
+ {
+ .base.init_tfm = dthe_hash_init_tfm,
+ .base.init = dthe_hash_init,
+ .base.update = dthe_hash_update,
+ .base.final = dthe_hash_final,
+ .base.finup = dthe_hash_finup,
+ .base.digest = dthe_hash_digest,
+ .base.export = dthe_hash_export,
+ .base.import = dthe_hash_import,
+ .base.setkey = dthe_hmac_setkey,
+ .base.halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .statesize = sizeof(struct dthe_hash_req_ctx),
+ .base = {
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac-sha512-dthev2",
+ .cra_priority = 299,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY |
+ CRYPTO_ALG_ALLOCATES_MEMORY |
+ CRYPTO_AHASH_ALG_BLOCK_ONLY |
+ CRYPTO_AHASH_ALG_FINAL_NONZERO |
+ CRYPTO_AHASH_ALG_FINUP_MAX |
+ CRYPTO_AHASH_ALG_NO_EXPORT_CORE,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dthe_tfm_ctx),
+ .cra_reqsize = sizeof(struct dthe_hash_req_ctx),
+ .cra_module = THIS_MODULE,
+ }
+ },
+ .op.do_one_request = dthe_hash_run,
+ },
+ {
+ .base.init_tfm = dthe_hash_init_tfm,
+ .base.init = dthe_hash_init,
+ .base.update = dthe_hash_update,
+ .base.final = dthe_hash_final,
+ .base.finup = dthe_hash_finup,
+ .base.digest = dthe_hash_digest,
+ .base.export = dthe_hash_export,
+ .base.import = dthe_hash_import,
+ .base.setkey = dthe_hmac_setkey,
+ .base.halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .statesize = sizeof(struct dthe_hash_req_ctx),
+ .base = {
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac-sha384-dthev2",
+ .cra_priority = 299,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY |
+ CRYPTO_ALG_ALLOCATES_MEMORY |
+ CRYPTO_AHASH_ALG_BLOCK_ONLY |
+ CRYPTO_AHASH_ALG_FINAL_NONZERO |
+ CRYPTO_AHASH_ALG_FINUP_MAX |
+ CRYPTO_AHASH_ALG_NO_EXPORT_CORE,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dthe_tfm_ctx),
+ .cra_reqsize = sizeof(struct dthe_hash_req_ctx),
+ .cra_module = THIS_MODULE,
+ }
+ },
+ .op.do_one_request = dthe_hash_run,
+ },
+ {
+ .base.init_tfm = dthe_hash_init_tfm,
+ .base.init = dthe_hash_init,
+ .base.update = dthe_hash_update,
+ .base.final = dthe_hash_final,
+ .base.finup = dthe_hash_finup,
+ .base.digest = dthe_hash_digest,
+ .base.export = dthe_hash_export,
+ .base.import = dthe_hash_import,
+ .base.setkey = dthe_hmac_setkey,
+ .base.halg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .statesize = sizeof(struct dthe_hash_req_ctx),
+ .base = {
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac-sha256-dthev2",
+ .cra_priority = 299,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY |
+ CRYPTO_ALG_ALLOCATES_MEMORY |
+ CRYPTO_AHASH_ALG_BLOCK_ONLY |
+ CRYPTO_AHASH_ALG_FINAL_NONZERO |
+ CRYPTO_AHASH_ALG_FINUP_MAX |
+ CRYPTO_AHASH_ALG_NO_EXPORT_CORE,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dthe_tfm_ctx),
+ .cra_reqsize = sizeof(struct dthe_hash_req_ctx),
+ .cra_module = THIS_MODULE,
+ }
+ },
+ .op.do_one_request = dthe_hash_run,
+ },
+ {
+ .base.init_tfm = dthe_hash_init_tfm,
+ .base.init = dthe_hash_init,
+ .base.update = dthe_hash_update,
+ .base.final = dthe_hash_final,
+ .base.finup = dthe_hash_finup,
+ .base.digest = dthe_hash_digest,
+ .base.export = dthe_hash_export,
+ .base.import = dthe_hash_import,
+ .base.setkey = dthe_hmac_setkey,
+ .base.halg = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .statesize = sizeof(struct dthe_hash_req_ctx),
+ .base = {
+ .cra_name = "hmac(sha224)",
+ .cra_driver_name = "hmac-sha224-dthev2",
+ .cra_priority = 299,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY |
+ CRYPTO_ALG_ALLOCATES_MEMORY |
+ CRYPTO_AHASH_ALG_BLOCK_ONLY |
+ CRYPTO_AHASH_ALG_FINAL_NONZERO |
+ CRYPTO_AHASH_ALG_FINUP_MAX |
+ CRYPTO_AHASH_ALG_NO_EXPORT_CORE,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dthe_tfm_ctx),
+ .cra_reqsize = sizeof(struct dthe_hash_req_ctx),
+ .cra_module = THIS_MODULE,
+ }
+ },
+ .op.do_one_request = dthe_hash_run,
+ },
+ {
+ .base.init_tfm = dthe_hash_init_tfm,
+ .base.init = dthe_hash_init,
+ .base.update = dthe_hash_update,
+ .base.final = dthe_hash_final,
+ .base.finup = dthe_hash_finup,
+ .base.digest = dthe_hash_digest,
+ .base.export = dthe_hash_export,
+ .base.import = dthe_hash_import,
+ .base.setkey = dthe_hmac_setkey,
+ .base.halg = {
+ .digestsize = MD5_DIGEST_SIZE,
+ .statesize = sizeof(struct dthe_hash_req_ctx),
+ .base = {
+ .cra_name = "hmac(md5)",
+ .cra_driver_name = "hmac-md5-dthev2",
+ .cra_priority = 299,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY |
+ CRYPTO_ALG_ALLOCATES_MEMORY |
+ CRYPTO_AHASH_ALG_BLOCK_ONLY |
+ CRYPTO_AHASH_ALG_FINAL_NONZERO |
+ CRYPTO_AHASH_ALG_FINUP_MAX |
+ CRYPTO_AHASH_ALG_NO_EXPORT_CORE,
+ .cra_blocksize = MD5_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct dthe_tfm_ctx),
+ .cra_reqsize = sizeof(struct dthe_hash_req_ctx),
+ .cra_module = THIS_MODULE,
+ }
+ },
+ .op.do_one_request = dthe_hash_run,
+ },
};
int dthe_register_hash_algs(void)
--
2.34.1
Powered by blists - more mailing lists