mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
crypto: rockchip - add crypto v2 sha1/sha256/sha512/md5 support
Change-Id: I1db69026a7b66642abc80d45f7e6ce22445c36a5 Signed-off-by: Lin Jinhan <troy.lin@rock-chips.com>
This commit is contained in:
@@ -3,4 +3,5 @@ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rk_crypto.o
|
||||
rk_crypto-objs := rk_crypto_core.o \
|
||||
rk_crypto_v1_ahash.o \
|
||||
rk_crypto_v1_ablkcipher.o \
|
||||
rk_crypto_v2_ablkcipher.o
|
||||
rk_crypto_v2_ablkcipher.o \
|
||||
rk_crypto_v2_ahash.o
|
||||
|
||||
@@ -373,17 +373,24 @@ static struct rk_crypto_tmp *crypto_v2_algs[] = {
|
||||
|
||||
&rk_v2_ecb_des3_ede_alg, /* ecb(des3_ede) */
|
||||
&rk_v2_cbc_des3_ede_alg, /* cbc(des3_ede) */
|
||||
|
||||
&rk_v2_ahash_sha1, /* sha1 */
|
||||
&rk_v2_ahash_sha256, /* sha256 */
|
||||
&rk_v2_ahash_sha512, /* sha512 */
|
||||
&rk_v2_ahash_md5, /* md5 */
|
||||
};
|
||||
|
||||
static char *px30_algs_name[] = {
|
||||
"ecb(aes)", "cbc(aes)", "xts(aes)",
|
||||
"ecb(des)", "cbc(des)",
|
||||
"ecb(des3_ede)", "cbc(des3_ede)",
|
||||
"sha1", "sha256", "sha512", "md5",
|
||||
};
|
||||
|
||||
static char *rv1126_algs_name[] = {
|
||||
"ecb(des)", "cbc(des)",
|
||||
"ecb(des3_ede)", "cbc(des3_ede)",
|
||||
"sha1", "sha256", "sha512", "md5",
|
||||
};
|
||||
|
||||
static const struct rk_crypto_soc_data px30_soc_data =
|
||||
|
||||
@@ -33,6 +33,11 @@ extern struct rk_crypto_tmp rk_v2_cbc_des_alg;
|
||||
extern struct rk_crypto_tmp rk_v2_ecb_des3_ede_alg;
|
||||
extern struct rk_crypto_tmp rk_v2_cbc_des3_ede_alg;
|
||||
|
||||
extern struct rk_crypto_tmp rk_v2_ahash_sha1;
|
||||
extern struct rk_crypto_tmp rk_v2_ahash_sha256;
|
||||
extern struct rk_crypto_tmp rk_v2_ahash_sha512;
|
||||
extern struct rk_crypto_tmp rk_v2_ahash_md5;
|
||||
|
||||
int rk_hw_crypto_v2_init(struct device *dev, void *hw_info);
|
||||
void rk_hw_crypto_v2_deinit(struct device *dev, void *hw_info);
|
||||
#endif
|
||||
|
||||
480
drivers/crypto/rockchip/rk_crypto_v2_ahash.c
Normal file
480
drivers/crypto/rockchip/rk_crypto_v2_ahash.c
Normal file
@@ -0,0 +1,480 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Hash acceleration support for Rockchip Crypto v2
|
||||
*
|
||||
* Copyright (c) 2020, Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* Author: Lin Jinhan <troy.lin@rock-chips.com>
|
||||
*
|
||||
* Some ideas are from marvell/cesa.c and s5p-sss.c driver.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "rk_crypto_core.h"
|
||||
#include "rk_crypto_v2.h"
|
||||
#include "rk_crypto_v2_reg.h"
|
||||
|
||||
struct rk_hash_ctx {
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
#define RK_HASH_CTX_MAGIC 0x1A1A1A1A
|
||||
#define RK_POLL_PERIOD_US 100
|
||||
#define RK_POLL_TIMEOUT_US 50000
|
||||
#define HASH_MAX_SIZE PAGE_SIZE
|
||||
|
||||
static const u8 null_hash_md5_value[] = {
|
||||
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
|
||||
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
|
||||
};
|
||||
|
||||
static const u8 null_hash_sha1_value[] = {
|
||||
0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
|
||||
0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
|
||||
0xaf, 0xd8, 0x07, 0x09
|
||||
};
|
||||
|
||||
static const u8 null_hash_sha256_value[] = {
|
||||
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
|
||||
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
|
||||
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
|
||||
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
|
||||
};
|
||||
|
||||
static const u8 null_hash_sha512_value[] = {
|
||||
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
|
||||
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
|
||||
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
|
||||
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
|
||||
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
|
||||
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
|
||||
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
|
||||
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
|
||||
};
|
||||
|
||||
static const u32 hash_algo2bc[] = {
|
||||
[HASH_ALGO_MD5] = CRYPTO_MD5,
|
||||
[HASH_ALGO_SHA1] = CRYPTO_SHA1,
|
||||
[HASH_ALGO_SHA256] = CRYPTO_SHA256,
|
||||
[HASH_ALGO_SHA512] = CRYPTO_SHA512,
|
||||
};
|
||||
|
||||
static void word2byte(u32 word, u8 *ch, u32 endian)
|
||||
{
|
||||
/* 0: Big-Endian 1: Little-Endian */
|
||||
if (endian == BIG_ENDIAN) {
|
||||
ch[0] = (word >> 24) & 0xff;
|
||||
ch[1] = (word >> 16) & 0xff;
|
||||
ch[2] = (word >> 8) & 0xff;
|
||||
ch[3] = (word >> 0) & 0xff;
|
||||
} else if (endian == LITTLE_ENDIAN) {
|
||||
ch[0] = (word >> 0) & 0xff;
|
||||
ch[1] = (word >> 8) & 0xff;
|
||||
ch[2] = (word >> 16) & 0xff;
|
||||
ch[3] = (word >> 24) & 0xff;
|
||||
} else {
|
||||
ch[0] = 0;
|
||||
ch[1] = 0;
|
||||
ch[2] = 0;
|
||||
ch[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct rk_crypto_tmp *rk_ahash_get_algt(struct crypto_ahash *tfm)
|
||||
{
|
||||
struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg);
|
||||
|
||||
return container_of(alg, struct rk_crypto_tmp, alg.hash);
|
||||
}
|
||||
|
||||
static int zero_message_process(struct ahash_request *req)
|
||||
{
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
int rk_digest_size = crypto_ahash_digestsize(tfm);
|
||||
struct rk_crypto_tmp *algt = rk_ahash_get_algt(tfm);
|
||||
|
||||
switch (algt->algo) {
|
||||
case HASH_ALGO_MD5:
|
||||
memcpy(req->result, null_hash_md5_value, rk_digest_size);
|
||||
break;
|
||||
case HASH_ALGO_SHA1:
|
||||
memcpy(req->result, null_hash_sha1_value, rk_digest_size);
|
||||
break;
|
||||
case HASH_ALGO_SHA256:
|
||||
memcpy(req->result, null_hash_sha256_value, rk_digest_size);
|
||||
break;
|
||||
case HASH_ALGO_SHA512:
|
||||
memcpy(req->result, null_hash_sha512_value, rk_digest_size);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_crypto_irq_handle(int irq, void *dev_id)
|
||||
{
|
||||
struct rk_crypto_info *dev = platform_get_drvdata(dev_id);
|
||||
u32 interrupt_status;
|
||||
struct rk_hw_crypto_v2_info *hw_info =
|
||||
(struct rk_hw_crypto_v2_info *)dev->hw_info;
|
||||
|
||||
interrupt_status = CRYPTO_READ(dev, CRYPTO_DMA_INT_ST);
|
||||
CRYPTO_WRITE(dev, CRYPTO_DMA_INT_ST, interrupt_status);
|
||||
|
||||
if (interrupt_status != CRYPTO_SRC_ITEM_DONE_INT_ST) {
|
||||
dev_err(dev->dev, "DMA desc = %p\n", hw_info->desc);
|
||||
dev_err(dev->dev, "DMA addr_in = %08x\n",
|
||||
(u32)dev->addr_in);
|
||||
dev_err(dev->dev, "DMA addr_out = %08x\n",
|
||||
(u32)dev->addr_out);
|
||||
dev_err(dev->dev, "DMA count = %08x\n", dev->count);
|
||||
dev_err(dev->dev, "DMA desc_dma = %08x\n",
|
||||
(u32)hw_info->desc_dma);
|
||||
dev_err(dev->dev, "DMA Error status = %08x\n",
|
||||
interrupt_status);
|
||||
dev_err(dev->dev, "DMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
|
||||
CRYPTO_READ(dev, CRYPTO_DMA_LLI_ADDR));
|
||||
dev_err(dev->dev, "DMA CRYPTO_DMA_ST status = %08x\n",
|
||||
CRYPTO_READ(dev, CRYPTO_DMA_ST));
|
||||
dev_err(dev->dev, "DMA CRYPTO_DMA_STATE status = %08x\n",
|
||||
CRYPTO_READ(dev, CRYPTO_DMA_STATE));
|
||||
dev_err(dev->dev, "DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
|
||||
CRYPTO_READ(dev, CRYPTO_DMA_LLI_RADDR));
|
||||
dev_err(dev->dev, "DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
|
||||
CRYPTO_READ(dev, CRYPTO_DMA_SRC_RADDR));
|
||||
dev_err(dev->dev, "DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
|
||||
CRYPTO_READ(dev, CRYPTO_DMA_DST_RADDR));
|
||||
dev->err = -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk_ahash_crypto_complete(struct crypto_async_request *base, int err)
|
||||
{
|
||||
if (base->complete)
|
||||
base->complete(base, err);
|
||||
}
|
||||
|
||||
static inline void clear_hash_out_reg(struct rk_crypto_info *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*clear out register*/
|
||||
for (i = 0; i < 16; i++)
|
||||
CRYPTO_WRITE(dev, CRYPTO_HASH_DOUT_0 + 4 * i, 0);
|
||||
}
|
||||
|
||||
static int rk_ahash_init(struct ahash_request *req)
|
||||
{
|
||||
struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
|
||||
rctx->fallback_req.base.flags = req->base.flags &
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
return crypto_ahash_init(&rctx->fallback_req);
|
||||
}
|
||||
|
||||
static int rk_ahash_update(struct ahash_request *req)
|
||||
{
|
||||
struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
|
||||
rctx->fallback_req.base.flags = req->base.flags &
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
rctx->fallback_req.nbytes = req->nbytes;
|
||||
rctx->fallback_req.src = req->src;
|
||||
|
||||
return crypto_ahash_update(&rctx->fallback_req);
|
||||
}
|
||||
|
||||
static int rk_ahash_final(struct ahash_request *req)
|
||||
{
|
||||
struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
|
||||
rctx->fallback_req.base.flags = req->base.flags &
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
rctx->fallback_req.result = req->result;
|
||||
|
||||
return crypto_ahash_final(&rctx->fallback_req);
|
||||
}
|
||||
|
||||
static int rk_ahash_finup(struct ahash_request *req)
|
||||
{
|
||||
struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
|
||||
rctx->fallback_req.base.flags = req->base.flags &
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
rctx->fallback_req.nbytes = req->nbytes;
|
||||
rctx->fallback_req.src = req->src;
|
||||
rctx->fallback_req.result = req->result;
|
||||
|
||||
return crypto_ahash_finup(&rctx->fallback_req);
|
||||
}
|
||||
|
||||
static int rk_ahash_import(struct ahash_request *req, const void *in)
|
||||
{
|
||||
struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
|
||||
rctx->fallback_req.base.flags = req->base.flags &
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
return crypto_ahash_import(&rctx->fallback_req, in);
|
||||
}
|
||||
|
||||
static int rk_ahash_export(struct ahash_request *req, void *out)
|
||||
{
|
||||
struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
|
||||
rctx->fallback_req.base.flags = req->base.flags &
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
return crypto_ahash_export(&rctx->fallback_req, out);
|
||||
}
|
||||
|
||||
static int rk_ahash_digest(struct ahash_request *req)
|
||||
{
|
||||
struct rk_ahash_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
|
||||
struct rk_crypto_info *dev = tctx->dev;
|
||||
|
||||
CRYPTO_TRACE("calc data %u bytes.", req->nbytes);
|
||||
|
||||
if (!req->nbytes)
|
||||
return zero_message_process(req);
|
||||
else
|
||||
return dev->enqueue(dev, &req->base);
|
||||
}
|
||||
|
||||
static void rk_ahash_dma_start(struct rk_crypto_info *dev)
|
||||
{
|
||||
struct rk_hw_crypto_v2_info *hw_info =
|
||||
(struct rk_hw_crypto_v2_info *)dev->hw_info;
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
memset(hw_info->desc, 0x00, sizeof(*hw_info->desc));
|
||||
|
||||
hw_info->desc->src_addr = dev->addr_in;
|
||||
hw_info->desc->src_len = dev->count;
|
||||
hw_info->desc->next_addr = 0;
|
||||
hw_info->desc->dma_ctrl = 0x00000401;
|
||||
hw_info->desc->user_define = 0x7;
|
||||
|
||||
dma_sync_single_for_device(dev->dev, hw_info->desc_dma,
|
||||
sizeof(*hw_info->desc), DMA_TO_DEVICE);
|
||||
CRYPTO_WRITE(dev, CRYPTO_DMA_LLI_ADDR, hw_info->desc_dma);
|
||||
CRYPTO_WRITE(dev, CRYPTO_HASH_CTL,
|
||||
(CRYPTO_HASH_ENABLE <<
|
||||
CRYPTO_WRITE_MASK_SHIFT) |
|
||||
CRYPTO_HASH_ENABLE);
|
||||
|
||||
CRYPTO_WRITE(dev, CRYPTO_DMA_CTL, 0x00010001);/* start */
|
||||
}
|
||||
|
||||
static int rk_ahash_set_data_start(struct rk_crypto_info *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
err = dev->load_data(dev, dev->sg_src, dev->sg_dst);
|
||||
if (!err)
|
||||
rk_ahash_dma_start(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rk_ahash_start(struct rk_crypto_info *dev)
|
||||
{
|
||||
struct ahash_request *req = ahash_request_cast(dev->async_req);
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
struct rk_crypto_tmp *algt = rk_ahash_get_algt(tfm);
|
||||
u32 reg_ctrl = 0;
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
dev->total = req->nbytes;
|
||||
dev->left_bytes = req->nbytes;
|
||||
dev->aligned = 0;
|
||||
dev->align_size = 4;
|
||||
dev->sg_dst = NULL;
|
||||
dev->sg_src = req->src;
|
||||
dev->first = req->src;
|
||||
dev->src_nents = sg_nents(req->src);
|
||||
|
||||
if (algt->algo >= ARRAY_SIZE(hash_algo2bc))
|
||||
goto exit;
|
||||
|
||||
reg_ctrl |= hash_algo2bc[algt->algo];
|
||||
clear_hash_out_reg(dev);
|
||||
|
||||
reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
|
||||
CRYPTO_WRITE(dev, CRYPTO_HASH_CTL, reg_ctrl | CRYPTO_WRITE_MASK_ALL);
|
||||
|
||||
CRYPTO_WRITE(dev, CRYPTO_FIFO_CTL, 0x00030003);
|
||||
CRYPTO_WRITE(dev, CRYPTO_DMA_INT_EN, 0x7f);
|
||||
|
||||
return rk_ahash_set_data_start(dev);
|
||||
exit:
|
||||
CRYPTO_WRITE(dev, CRYPTO_HASH_CTL, CRYPTO_WRITE_MASK_ALL | 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rk_ahash_get_result(struct rk_crypto_info *dev, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
int ret;
|
||||
u32 i, offset;
|
||||
u32 reg_ctrl = 0;
|
||||
|
||||
ret = readl_poll_timeout_atomic(dev->reg + CRYPTO_HASH_VALID, reg_ctrl,
|
||||
reg_ctrl & CRYPTO_HASH_IS_VALID,
|
||||
RK_POLL_PERIOD_US,
|
||||
RK_POLL_TIMEOUT_US);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
offset = CRYPTO_HASH_DOUT_0;
|
||||
for (i = 0; i < data_len / 4; i++, offset += 4)
|
||||
word2byte(CRYPTO_READ(dev, offset),
|
||||
data + i * 4, BIG_ENDIAN);
|
||||
|
||||
if (data_len % 4) {
|
||||
uint8_t tmp_buf[4];
|
||||
|
||||
word2byte(CRYPTO_READ(dev, offset), tmp_buf, BIG_ENDIAN);
|
||||
memcpy(data + i * 4, tmp_buf, data_len % 4);
|
||||
}
|
||||
|
||||
CRYPTO_WRITE(dev, CRYPTO_HASH_VALID, CRYPTO_HASH_IS_VALID);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk_ahash_crypto_rx(struct rk_crypto_info *dev)
|
||||
{
|
||||
int err = 0;
|
||||
struct ahash_request *req = ahash_request_cast(dev->async_req);
|
||||
struct crypto_ahash *tfm;
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
dev->unload_data(dev);
|
||||
CRYPTO_TRACE("left bytes = %u", dev->left_bytes);
|
||||
if (dev->left_bytes) {
|
||||
if (dev->aligned) {
|
||||
if (sg_is_last(dev->sg_src)) {
|
||||
dev_warn(dev->dev, "[%s:%d], Lack of data\n",
|
||||
__func__, __LINE__);
|
||||
err = -ENOMEM;
|
||||
goto out_rx;
|
||||
}
|
||||
dev->sg_src = sg_next(dev->sg_src);
|
||||
}
|
||||
err = rk_ahash_set_data_start(dev);
|
||||
} else {
|
||||
/*
|
||||
* it will take some time to process date after last dma
|
||||
* transmission.
|
||||
*/
|
||||
|
||||
tfm = crypto_ahash_reqtfm(req);
|
||||
|
||||
err = rk_ahash_get_result(dev, req->result, crypto_ahash_digestsize(tfm));
|
||||
|
||||
dev->complete(dev->async_req, err);
|
||||
tasklet_schedule(&dev->queue_task);
|
||||
}
|
||||
|
||||
out_rx:
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static int rk_cra_hash_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct rk_crypto_tmp *algt = rk_ahash_get_algt(__crypto_ahash_cast(tfm));
|
||||
const char *alg_name = crypto_tfm_alg_name(tfm);
|
||||
struct rk_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
memset(ctx, 0x00, sizeof(*ctx));
|
||||
|
||||
ctx->dev = algt->dev;
|
||||
ctx->dev->start = rk_ahash_start;
|
||||
ctx->dev->update = rk_ahash_crypto_rx;
|
||||
ctx->dev->complete = rk_ahash_crypto_complete;
|
||||
ctx->dev->irq_handle = rk_crypto_irq_handle;
|
||||
|
||||
/* for fallback */
|
||||
ctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0,
|
||||
CRYPTO_ALG_NEED_FALLBACK);
|
||||
if (IS_ERR(ctx->fallback_tfm)) {
|
||||
dev_err(ctx->dev->dev, "Could not load fallback driver.\n");
|
||||
return PTR_ERR(ctx->fallback_tfm);
|
||||
}
|
||||
|
||||
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
|
||||
sizeof(struct rk_ahash_rctx) +
|
||||
crypto_ahash_reqsize(ctx->fallback_tfm));
|
||||
|
||||
ctx->dev->enable_clk(ctx->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk_cra_hash_exit(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct rk_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
CRYPTO_TRACE();
|
||||
|
||||
/* clear HASH_CTL */
|
||||
CRYPTO_WRITE(ctx->dev, CRYPTO_HASH_CTL, CRYPTO_WRITE_MASK_ALL | 0);
|
||||
|
||||
ctx->dev->disable_clk(ctx->dev);
|
||||
|
||||
if (ctx->fallback_tfm)
|
||||
crypto_free_ahash(ctx->fallback_tfm);
|
||||
}
|
||||
|
||||
struct rk_crypto_tmp rk_v2_ahash_md5 = RK_HASH_ALGO_INIT(MD5, md5);
|
||||
struct rk_crypto_tmp rk_v2_ahash_sha1 = RK_HASH_ALGO_INIT(SHA1, sha1);
|
||||
struct rk_crypto_tmp rk_v2_ahash_sha256 = RK_HASH_ALGO_INIT(SHA256, sha256);
|
||||
struct rk_crypto_tmp rk_v2_ahash_sha512 = RK_HASH_ALGO_INIT(SHA512, sha512);
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
#define CRYPTO_MD5 _SBF(4, 0x01)
|
||||
#define CRYPTO_SHA256 _SBF(4, 0x02)
|
||||
#define CRYPTO_SHA224 _SBF(4, 0x03)
|
||||
#define CRYPTO_SM3 _SBF(4, 0x06)
|
||||
#define CRYPTO_SHA512 _SBF(4, 0x08)
|
||||
#define CRYPTO_SHA384 _SBF(4, 0x09)
|
||||
#define CRYPTO_SHA512_224 _SBF(4, 0x0A)
|
||||
|
||||
Reference in New Issue
Block a user