xref: /optee_os/core/drivers/crypto/hisilicon/sec_hash.c (revision e885351c3cb51de60ae7dfbf282fc0f1ceb7e654)
194c8a339Sleisen // SPDX-License-Identifier: BSD-2-Clause
294c8a339Sleisen /*
394c8a339Sleisen  * Copyright 2022-2024 HiSilicon Limited.
494c8a339Sleisen  * Kunpeng hardware accelerator sec hash algorithm implementation.
594c8a339Sleisen  */
694c8a339Sleisen 
794c8a339Sleisen #include <drvcrypt_hash.h>
894c8a339Sleisen #include <initcall.h>
9b6a44cc5Sleisen 
10b6a44cc5Sleisen #include "sec_hash.h"
11b6a44cc5Sleisen #include "sec_main.h"
1294c8a339Sleisen 
sec_digest_set_hmac_key(struct hashctx * ctx,struct hisi_sec_sqe * sqe)1394c8a339Sleisen static enum hisi_drv_status sec_digest_set_hmac_key(struct hashctx *ctx,
1494c8a339Sleisen 						    struct hisi_sec_sqe *sqe)
1594c8a339Sleisen {
1694c8a339Sleisen 	if (ctx->key_len > SEC_DIGEST_MAX_KEY_SIZE || !ctx->key_len) {
1794c8a339Sleisen 		EMSG("Invalid digest key len(%ld)", ctx->key_len);
1894c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
1994c8a339Sleisen 	}
2094c8a339Sleisen 
2194c8a339Sleisen 	/* If the length of key is not word-aligned, increment by 1 */
2294c8a339Sleisen 	sqe->type2.mac_key_alg |= SHIFT_U64(DIV_ROUND_UP(ctx->key_len,
2394c8a339Sleisen 							 SEC_ENCODE_BYTES),
2494c8a339Sleisen 					    SEC_AKEY_OFFSET);
2594c8a339Sleisen 	sqe->type2.a_key_addr = ctx->key_dma;
2694c8a339Sleisen 
2794c8a339Sleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
2894c8a339Sleisen }
2994c8a339Sleisen 
sec_digest_fill_long_bd2(struct hashctx * ctx,struct hisi_sec_sqe * sqe)3094c8a339Sleisen static void sec_digest_fill_long_bd2(struct hashctx *ctx,
3194c8a339Sleisen 				     struct hisi_sec_sqe *sqe)
3294c8a339Sleisen {
3394c8a339Sleisen 	uint64_t total_bits = 0;
3494c8a339Sleisen 
3594c8a339Sleisen 	if (ctx->has_next && !ctx->iv_len) {
3694c8a339Sleisen 		/* LONG BD FIRST */
3794c8a339Sleisen 		sqe->ai_apd_cs |= AI_GEN_INNER;
3894c8a339Sleisen 		sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_NOPAD, SEC_APAD_OFFSET);
3994c8a339Sleisen 		ctx->iv_len = ctx->mac_len;
4094c8a339Sleisen 	} else if (ctx->has_next && ctx->iv_len) {
4194c8a339Sleisen 		/* LONG BD MIDDLE */
4294c8a339Sleisen 		sqe->ai_apd_cs |= AI_GEN_IVIN_ADDR;
4394c8a339Sleisen 		sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_NOPAD, SEC_APAD_OFFSET);
4494c8a339Sleisen 		sqe->type2.a_ivin_addr = sqe->type2.mac_addr;
4594c8a339Sleisen 		ctx->iv_len = ctx->mac_len;
4694c8a339Sleisen 	} else if (!ctx->has_next && ctx->iv_len) {
4794c8a339Sleisen 		/* LONG BD END */
4894c8a339Sleisen 		sqe->ai_apd_cs |= AI_GEN_IVIN_ADDR;
4994c8a339Sleisen 		sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_PAD, SEC_APAD_OFFSET);
5094c8a339Sleisen 		sqe->type2.a_ivin_addr = sqe->type2.mac_addr;
5194c8a339Sleisen 		total_bits = ctx->long_data_len * BYTE_BITS;
5294c8a339Sleisen 		sqe->type2.long_a_data_len = total_bits;
5394c8a339Sleisen 		ctx->iv_len = 0;
5494c8a339Sleisen 	} else {
5594c8a339Sleisen 		/* SHORT BD */
5694c8a339Sleisen 		ctx->iv_len = 0;
5794c8a339Sleisen 	}
5894c8a339Sleisen }
5994c8a339Sleisen 
to_hash_ctx(struct crypto_hash_ctx * ctx)6094c8a339Sleisen static struct crypto_hash *to_hash_ctx(struct crypto_hash_ctx *ctx)
6194c8a339Sleisen {
6294c8a339Sleisen 	return container_of(ctx, struct crypto_hash, hash_ctx);
6394c8a339Sleisen }
6494c8a339Sleisen 
sec_digest_get_alg_type(uint32_t algo)6594c8a339Sleisen static uint32_t sec_digest_get_alg_type(uint32_t algo)
6694c8a339Sleisen {
6794c8a339Sleisen 	switch (algo) {
6894c8a339Sleisen 	case TEE_ALG_MD5:
6994c8a339Sleisen 		return A_ALG_MD5;
7094c8a339Sleisen 	case TEE_ALG_HMAC_MD5:
7194c8a339Sleisen 		return A_ALG_HMAC_MD5;
7294c8a339Sleisen 	case TEE_ALG_SHA1:
7394c8a339Sleisen 		return A_ALG_SHA1;
7494c8a339Sleisen 	case TEE_ALG_HMAC_SHA1:
7594c8a339Sleisen 		return A_ALG_HMAC_SHA1;
7694c8a339Sleisen 	case TEE_ALG_SHA224:
7794c8a339Sleisen 		return A_ALG_SHA224;
7894c8a339Sleisen 	case TEE_ALG_HMAC_SHA224:
7994c8a339Sleisen 		return A_ALG_HMAC_SHA224;
8094c8a339Sleisen 	case TEE_ALG_SM3:
8194c8a339Sleisen 		return A_ALG_SM3;
8294c8a339Sleisen 	case TEE_ALG_HMAC_SM3:
8394c8a339Sleisen 		return A_ALG_HMAC_SM3;
8494c8a339Sleisen 	case TEE_ALG_SHA256:
8594c8a339Sleisen 		return A_ALG_SHA256;
8694c8a339Sleisen 	case TEE_ALG_HMAC_SHA256:
8794c8a339Sleisen 		return A_ALG_HMAC_SHA256;
8894c8a339Sleisen 	case TEE_ALG_SHA384:
8994c8a339Sleisen 		return A_ALG_SHA384;
9094c8a339Sleisen 	case TEE_ALG_HMAC_SHA384:
9194c8a339Sleisen 		return A_ALG_HMAC_SHA384;
9294c8a339Sleisen 	case TEE_ALG_SHA512:
9394c8a339Sleisen 		return A_ALG_SHA512;
9494c8a339Sleisen 	case TEE_ALG_HMAC_SHA512:
9594c8a339Sleisen 		return A_ALG_HMAC_SHA512;
9694c8a339Sleisen 	default:
9794c8a339Sleisen 		return A_ALG_MAX;
9894c8a339Sleisen 	}
9994c8a339Sleisen }
10094c8a339Sleisen 
sec_digest_fill_sqe(void * bd,void * msg)10194c8a339Sleisen static enum hisi_drv_status sec_digest_fill_sqe(void *bd, void *msg)
10294c8a339Sleisen {
10394c8a339Sleisen 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
10494c8a339Sleisen 	struct hisi_sec_sqe *sqe = bd;
10594c8a339Sleisen 	struct hashctx *ctx = msg;
10694c8a339Sleisen 	uint32_t alg_type = 0;
10794c8a339Sleisen 
10894c8a339Sleisen 	if (!ctx->in_len) {
10994c8a339Sleisen 		EMSG("Digest bd2 not support 0 packet");
11094c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
11194c8a339Sleisen 	}
11294c8a339Sleisen 
11394c8a339Sleisen 	sqe->type_auth_cipher = BD_TYPE2;
11494c8a339Sleisen 	sqe->sds_sa_type = SHIFT_U32(SCENE_NOTHING, SEC_SCENE_OFFSET);
11594c8a339Sleisen 	sqe->type_auth_cipher |= SHIFT_U32(AUTH_MAC_CALCULATE, SEC_AUTH_OFFSET);
11694c8a339Sleisen 	sqe->type2.alen_ivllen = ctx->in_len;
11794c8a339Sleisen 
11894c8a339Sleisen 	sqe->type2.data_src_addr = ctx->in_dma;
11994c8a339Sleisen 	sqe->type2.mac_addr = ctx->out_dma;
12094c8a339Sleisen 	sqe->type2.mac_key_alg |= ctx->mac_len / SEC_ENCODE_BYTES;
12194c8a339Sleisen 
12294c8a339Sleisen 	if (ctx->mode == WCRYPTO_DIGEST_HMAC) {
12394c8a339Sleisen 		ret = sec_digest_set_hmac_key(ctx, sqe);
12494c8a339Sleisen 		if (ret)
12594c8a339Sleisen 			return ret;
12694c8a339Sleisen 	}
12794c8a339Sleisen 
12894c8a339Sleisen 	alg_type = sec_digest_get_alg_type(ctx->algo);
12994c8a339Sleisen 	if (alg_type >= A_ALG_MAX) {
13094c8a339Sleisen 		EMSG("Fail to get digest alg type");
13194c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
13294c8a339Sleisen 	}
13394c8a339Sleisen 	sqe->type2.mac_key_alg |= SHIFT_U32(alg_type, SEC_AEAD_ALG_OFFSET);
13494c8a339Sleisen 
13594c8a339Sleisen 	sec_digest_fill_long_bd2(ctx, sqe);
13694c8a339Sleisen 
13794c8a339Sleisen 	return ret;
13894c8a339Sleisen }
13994c8a339Sleisen 
14094c8a339Sleisen static enum hisi_drv_status
sec_digest_set_hmac_bd3_key(struct hashctx * ctx,struct hisi_sec_bd3_sqe * sqe)14194c8a339Sleisen sec_digest_set_hmac_bd3_key(struct hashctx *ctx, struct hisi_sec_bd3_sqe *sqe)
14294c8a339Sleisen {
14394c8a339Sleisen 	if (ctx->key_len > SEC_DIGEST_MAX_KEY_SIZE || !ctx->key_len) {
14494c8a339Sleisen 		EMSG("Invalid digest key len(%ld)", ctx->key_len);
14594c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
14694c8a339Sleisen 	}
14794c8a339Sleisen 
14894c8a339Sleisen 	/* If the length of key is not word-aligned, increment by 1 */
14994c8a339Sleisen 	sqe->auth_mac_key |= SHIFT_U64(DIV_ROUND_UP(ctx->key_len,
15094c8a339Sleisen 						    SEC_ENCODE_BYTES),
15194c8a339Sleisen 				       SEC_AKEY_OFFSET_V3);
15294c8a339Sleisen 	sqe->a_key_addr = ctx->key_dma;
15394c8a339Sleisen 
15494c8a339Sleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
15594c8a339Sleisen }
15694c8a339Sleisen 
sec_digest_fill_long_bd3(struct hashctx * ctx,struct hisi_sec_bd3_sqe * sqe)15794c8a339Sleisen static void sec_digest_fill_long_bd3(struct hashctx *ctx,
15894c8a339Sleisen 				     struct hisi_sec_bd3_sqe *sqe)
15994c8a339Sleisen {
16094c8a339Sleisen 	uint64_t total_bits = 0;
16194c8a339Sleisen 
16294c8a339Sleisen 	if (ctx->has_next && !ctx->iv_len) {
16394c8a339Sleisen 		/* LONG BD FIRST */
16494c8a339Sleisen 		sqe->auth_mac_key |= SHIFT_U32(AI_GEN_INNER,
16594c8a339Sleisen 					       SEC_AI_GEN_OFFSET_V3);
16694c8a339Sleisen 		sqe->stream_scene.auth_pad = AUTHPAD_NOPAD;
16794c8a339Sleisen 		ctx->iv_len = ctx->mac_len;
16894c8a339Sleisen 	} else if (ctx->has_next && ctx->iv_len) {
16994c8a339Sleisen 		/* LONG BD MIDDLE */
17094c8a339Sleisen 		sqe->auth_mac_key |= SHIFT_U32(AI_GEN_IVIN_ADDR,
17194c8a339Sleisen 					       SEC_AI_GEN_OFFSET_V3);
17294c8a339Sleisen 		sqe->stream_scene.auth_pad = AUTHPAD_NOPAD;
17394c8a339Sleisen 		sqe->a_ivin_addr = sqe->mac_addr;
17494c8a339Sleisen 		ctx->iv_len = ctx->mac_len;
17594c8a339Sleisen 	} else if (!ctx->has_next && ctx->iv_len) {
17694c8a339Sleisen 		/* LONG BD END */
17794c8a339Sleisen 		sqe->auth_mac_key |= SHIFT_U32(AI_GEN_IVIN_ADDR,
17894c8a339Sleisen 					       SEC_AI_GEN_OFFSET_V3);
17994c8a339Sleisen 		sqe->stream_scene.auth_pad = AUTHPAD_PAD;
18094c8a339Sleisen 		sqe->a_ivin_addr = sqe->mac_addr;
18194c8a339Sleisen 		total_bits = ctx->long_data_len * BYTE_BITS;
18294c8a339Sleisen 		sqe->stream_scene.long_a_data_len = total_bits;
18394c8a339Sleisen 		ctx->iv_len = 0;
18494c8a339Sleisen 	} else {
18594c8a339Sleisen 		/* SHORT BD */
18694c8a339Sleisen 		ctx->iv_len = 0;
18794c8a339Sleisen 	}
18894c8a339Sleisen }
18994c8a339Sleisen 
sec_digest_fill_bd3_sqe(void * bd,void * msg)19094c8a339Sleisen static enum hisi_drv_status sec_digest_fill_bd3_sqe(void *bd, void *msg)
19194c8a339Sleisen {
19294c8a339Sleisen 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
19394c8a339Sleisen 	struct hisi_sec_bd3_sqe *sqe = bd;
19494c8a339Sleisen 	struct hashctx *ctx = msg;
19594c8a339Sleisen 	uint32_t alg_type = 0;
19694c8a339Sleisen 
19794c8a339Sleisen 	sqe->bd_param = BD_TYPE3 | SHIFT_U32(ctx->scene, SEC_SCENE_OFFSET_V3);
19894c8a339Sleisen 	sqe->a_len_key = ctx->in_len;
19994c8a339Sleisen 	sqe->auth_mac_key = AUTH_MAC_CALCULATE;
20094c8a339Sleisen 	sqe->data_src_addr = ctx->in_dma;
20194c8a339Sleisen 	sqe->mac_addr = ctx->out_dma;
20294c8a339Sleisen 
20394c8a339Sleisen 	if (ctx->mode == WCRYPTO_DIGEST_HMAC) {
20494c8a339Sleisen 		ret = sec_digest_set_hmac_bd3_key(ctx, sqe);
20594c8a339Sleisen 		if (ret)
20694c8a339Sleisen 			return HISI_QM_DRVCRYPT_IN_EPARA;
20794c8a339Sleisen 	}
20894c8a339Sleisen 
20994c8a339Sleisen 	sqe->auth_mac_key |= SHIFT_U64(ctx->mac_len / SEC_ENCODE_BYTES,
21094c8a339Sleisen 				       SEC_MAC_OFFSET_V3);
21194c8a339Sleisen 	alg_type = sec_digest_get_alg_type(ctx->algo);
21294c8a339Sleisen 	if (alg_type >= A_ALG_MAX) {
21394c8a339Sleisen 		EMSG("Fail to get digest bd3 alg");
21494c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
21594c8a339Sleisen 	}
21694c8a339Sleisen 	sqe->auth_mac_key |= SHIFT_U32(alg_type, SEC_AUTH_ALG_OFFSET_V3);
21794c8a339Sleisen 	sec_digest_fill_long_bd3(ctx, sqe);
21894c8a339Sleisen 
21994c8a339Sleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
22094c8a339Sleisen }
22194c8a339Sleisen 
sec_digest_do_task(struct hisi_qp * qp,void * msg)22294c8a339Sleisen static TEE_Result sec_digest_do_task(struct hisi_qp *qp, void *msg)
22394c8a339Sleisen {
22494c8a339Sleisen 	TEE_Result ret = TEE_SUCCESS;
22594c8a339Sleisen 
22694c8a339Sleisen 	ret = hisi_qp_send(qp, msg);
22794c8a339Sleisen 	if (ret) {
22894c8a339Sleisen 		EMSG("Fail to send task, ret=%d", ret);
22994c8a339Sleisen 		return TEE_ERROR_BAD_STATE;
23094c8a339Sleisen 	}
23194c8a339Sleisen 
23294c8a339Sleisen 	ret = hisi_qp_recv_sync(qp, msg);
23394c8a339Sleisen 	if (ret) {
23494c8a339Sleisen 		EMSG("Recv task error, ret=%d", ret);
23594c8a339Sleisen 		return TEE_ERROR_BAD_STATE;
23694c8a339Sleisen 	}
23794c8a339Sleisen 
23894c8a339Sleisen 	return TEE_SUCCESS;
23994c8a339Sleisen }
24094c8a339Sleisen 
sec_parse_digest_sqe(void * bd,void * msg __unused)24194c8a339Sleisen static enum hisi_drv_status sec_parse_digest_sqe(void *bd, void *msg __unused)
24294c8a339Sleisen {
24394c8a339Sleisen 	struct hisi_sec_sqe *sqe = bd;
24494c8a339Sleisen 	uint16_t done = 0;
24594c8a339Sleisen 
24694c8a339Sleisen 	done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
24794c8a339Sleisen 	if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
24894c8a339Sleisen 		EMSG("SEC BD2 fail! done=%#"PRIx16", etype=%#"PRIx8,
24994c8a339Sleisen 		     done, sqe->type2.error_type);
25094c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
25194c8a339Sleisen 	}
25294c8a339Sleisen 
25394c8a339Sleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
25494c8a339Sleisen }
25594c8a339Sleisen 
sec_parse_digest_bd3_sqe(void * bd,void * msg __unused)25694c8a339Sleisen static enum hisi_drv_status sec_parse_digest_bd3_sqe(void *bd,
25794c8a339Sleisen 						     void *msg __unused)
25894c8a339Sleisen {
25994c8a339Sleisen 	struct hisi_sec_bd3_sqe *sqe = bd;
26094c8a339Sleisen 	uint16_t done = 0;
26194c8a339Sleisen 
26294c8a339Sleisen 	done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
26394c8a339Sleisen 	if (done != SEC_HW_TASK_DONE || sqe->error_type) {
26494c8a339Sleisen 		EMSG("SEC BD3 fail! done=%#"PRIx16", etype=%#"PRIx8,
26594c8a339Sleisen 		     done, sqe->error_type);
26694c8a339Sleisen 		return HISI_QM_DRVCRYPT_IN_EPARA;
26794c8a339Sleisen 	}
26894c8a339Sleisen 
26994c8a339Sleisen 	return HISI_QM_DRVCRYPT_NO_ERR;
27094c8a339Sleisen }
27194c8a339Sleisen 
hisi_sec_digest_ctx_init(struct hashctx * hash_ctx,const uint8_t * key,size_t len)27294c8a339Sleisen TEE_Result hisi_sec_digest_ctx_init(struct hashctx *hash_ctx,
27394c8a339Sleisen 				    const uint8_t *key, size_t len)
27494c8a339Sleisen {
27594c8a339Sleisen 	if (!hash_ctx) {
27694c8a339Sleisen 		EMSG("Input hash_ctx is NULL");
27794c8a339Sleisen 		return TEE_ERROR_BAD_PARAMETERS;
27894c8a339Sleisen 	}
27994c8a339Sleisen 
28094c8a339Sleisen 	hash_ctx->in_len = 0;
28194c8a339Sleisen 	hash_ctx->iv_len = 0;
28294c8a339Sleisen 	hash_ctx->has_next = false;
28394c8a339Sleisen 	hash_ctx->long_data_len = 0;
28494c8a339Sleisen 	hash_ctx->scene = SCENE_NOTHING;
28594c8a339Sleisen 
28694c8a339Sleisen 	/*
28794c8a339Sleisen 	 * In reset ctx scenarios, sec_hash_initialize will be called.
28894c8a339Sleisen 	 * To ensure in data is NULL, reset ctx need to free in data
28994c8a339Sleisen 	 * which is not NULL.
29094c8a339Sleisen 	 */
29194c8a339Sleisen 	free(hash_ctx->in);
29294c8a339Sleisen 	hash_ctx->in = NULL;
29394c8a339Sleisen 
29494c8a339Sleisen 	if (len) {
29594c8a339Sleisen 		hash_ctx->key_len = len;
29694c8a339Sleisen 		memcpy(hash_ctx->key, key, len);
29794c8a339Sleisen 	}
29894c8a339Sleisen 
29994c8a339Sleisen 	return TEE_SUCCESS;
30094c8a339Sleisen }
30194c8a339Sleisen 
sec_hash_initialize(struct crypto_hash_ctx * ctx)30294c8a339Sleisen static TEE_Result sec_hash_initialize(struct crypto_hash_ctx *ctx)
30394c8a339Sleisen {
30494c8a339Sleisen 	struct crypto_hash *hash = NULL;
30594c8a339Sleisen 	struct hashctx *hash_ctx = NULL;
30694c8a339Sleisen 
30794c8a339Sleisen 	if (!ctx) {
30894c8a339Sleisen 		EMSG("Input ctx is NULL");
30994c8a339Sleisen 		return TEE_ERROR_BAD_PARAMETERS;
31094c8a339Sleisen 	}
31194c8a339Sleisen 
31294c8a339Sleisen 	hash = to_hash_ctx(ctx);
31394c8a339Sleisen 	hash_ctx = hash->ctx;
31494c8a339Sleisen 
31594c8a339Sleisen 	return hisi_sec_digest_ctx_init(hash_ctx, NULL, 0);
31694c8a339Sleisen }
31794c8a339Sleisen 
hisi_sec_digest_do_update(struct hashctx * hash_ctx,const uint8_t * data,size_t len)31894c8a339Sleisen TEE_Result hisi_sec_digest_do_update(struct hashctx *hash_ctx,
31994c8a339Sleisen 				     const uint8_t *data, size_t len)
32094c8a339Sleisen {
32194c8a339Sleisen 	TEE_Result ret = TEE_SUCCESS;
32294c8a339Sleisen 	size_t left_size = 0;
32394c8a339Sleisen 
32494c8a339Sleisen 	hash_ctx->long_data_len += len;
32594c8a339Sleisen 
32694c8a339Sleisen 	if (!hash_ctx->in) {
32794c8a339Sleisen 		if (len <= SMALL_BUF_SIZE)
32894c8a339Sleisen 			hash_ctx->buf_len = SMALL_BUF_SIZE;
32994c8a339Sleisen 		else if (len <= MAX_AUTH_LENGTH)
33094c8a339Sleisen 			hash_ctx->buf_len = ROUNDUP(len, HISI_QM_ALIGN128);
33194c8a339Sleisen 		else
33294c8a339Sleisen 			hash_ctx->buf_len = MAX_AUTH_LENGTH;
33394c8a339Sleisen 
33494c8a339Sleisen 		hash_ctx->in_len = 0;
33594c8a339Sleisen 		hash_ctx->in = malloc(hash_ctx->buf_len);
33694c8a339Sleisen 		if (!hash_ctx->in) {
33794c8a339Sleisen 			EMSG("Fail to alloc in data buf");
338*e885351cSleisen 			return TEE_ERROR_OUT_OF_MEMORY;
33994c8a339Sleisen 		}
34094c8a339Sleisen 		hash_ctx->in_dma = virt_to_phys(hash_ctx->in);
34194c8a339Sleisen 	}
34294c8a339Sleisen 
34394c8a339Sleisen 	while (len > 0) {
34494c8a339Sleisen 		if (hash_ctx->in_len + len <= hash_ctx->buf_len) {
34594c8a339Sleisen 			memcpy(hash_ctx->in + hash_ctx->in_len, data, len);
34694c8a339Sleisen 			hash_ctx->in_len += len;
34794c8a339Sleisen 			len = 0;
34894c8a339Sleisen 		} else {
34994c8a339Sleisen 			left_size = hash_ctx->buf_len - hash_ctx->in_len;
35094c8a339Sleisen 			memcpy(hash_ctx->in + hash_ctx->in_len, data,
35194c8a339Sleisen 			       left_size);
35294c8a339Sleisen 			hash_ctx->in_len = hash_ctx->buf_len;
35394c8a339Sleisen 			hash_ctx->scene = SCENE_STREAM;
35494c8a339Sleisen 			hash_ctx->has_next = true;
35594c8a339Sleisen 			data += left_size;
35694c8a339Sleisen 			len -= left_size;
35794c8a339Sleisen 			ret = sec_digest_do_task(hash_ctx->qp, hash_ctx);
35894c8a339Sleisen 			if (ret) {
35994c8a339Sleisen 				EMSG("Fail to do digest task! ret = %#"PRIx32,
36094c8a339Sleisen 				     ret);
36194c8a339Sleisen 				return ret;
36294c8a339Sleisen 			}
36394c8a339Sleisen 			hash_ctx->iv_len = hash_ctx->mac_len;
36494c8a339Sleisen 			hash_ctx->in_len = 0;
36594c8a339Sleisen 		}
36694c8a339Sleisen 	}
36794c8a339Sleisen 	return TEE_SUCCESS;
36894c8a339Sleisen }
36994c8a339Sleisen 
sec_hash_do_update(struct crypto_hash_ctx * ctx,const uint8_t * data,size_t len)37094c8a339Sleisen static TEE_Result sec_hash_do_update(struct crypto_hash_ctx *ctx,
37194c8a339Sleisen 				     const uint8_t *data, size_t len)
37294c8a339Sleisen {
37394c8a339Sleisen 	struct crypto_hash *hash = NULL;
37494c8a339Sleisen 	struct hashctx *hash_ctx = NULL;
37594c8a339Sleisen 
37694c8a339Sleisen 	if (!len) {
37794c8a339Sleisen 		IMSG("This is 0 len task, skip");
37894c8a339Sleisen 		return TEE_SUCCESS;
37994c8a339Sleisen 	}
38094c8a339Sleisen 
38194c8a339Sleisen 	if (!ctx || (!data && len)) {
38294c8a339Sleisen 		EMSG("Invalid input parameters");
38394c8a339Sleisen 		return TEE_ERROR_BAD_PARAMETERS;
38494c8a339Sleisen 	}
38594c8a339Sleisen 
38694c8a339Sleisen 	hash = to_hash_ctx(ctx);
38794c8a339Sleisen 	hash_ctx = hash->ctx;
38894c8a339Sleisen 
38994c8a339Sleisen 	return hisi_sec_digest_do_update(hash_ctx, data, len);
39094c8a339Sleisen }
39194c8a339Sleisen 
hisi_sec_digest_do_final(struct hashctx * hash_ctx,uint8_t * digest,size_t len)39294c8a339Sleisen TEE_Result hisi_sec_digest_do_final(struct hashctx *hash_ctx, uint8_t *digest,
39394c8a339Sleisen 				    size_t len)
39494c8a339Sleisen {
39594c8a339Sleisen 	TEE_Result ret = TEE_SUCCESS;
39694c8a339Sleisen 
39794c8a339Sleisen 	if (!digest || len == 0) {
39894c8a339Sleisen 		EMSG("Invalid input parameters");
39994c8a339Sleisen 		return TEE_ERROR_BAD_PARAMETERS;
40094c8a339Sleisen 	}
40194c8a339Sleisen 
40294c8a339Sleisen 	if (hash_ctx->mac_len & WORD_ALIGNMENT_MASK) {
40394c8a339Sleisen 		EMSG("Invalid digest out_bytes");
40494c8a339Sleisen 		return TEE_ERROR_BAD_PARAMETERS;
40594c8a339Sleisen 	}
40694c8a339Sleisen 
40794c8a339Sleisen 	hash_ctx->has_next = false;
40894c8a339Sleisen 	ret = sec_digest_do_task(hash_ctx->qp, hash_ctx);
40994c8a339Sleisen 	if (ret) {
41094c8a339Sleisen 		EMSG("Fail to do digest task! ret = %#"PRIx32, ret);
41194c8a339Sleisen 		return ret;
41294c8a339Sleisen 	}
41394c8a339Sleisen 
41494c8a339Sleisen 	memcpy(digest, hash_ctx->out, MIN(hash_ctx->mac_len, len));
41594c8a339Sleisen 
41694c8a339Sleisen 	return TEE_SUCCESS;
41794c8a339Sleisen }
41894c8a339Sleisen 
sec_hash_do_final(struct crypto_hash_ctx * ctx,uint8_t * digest,size_t len)41994c8a339Sleisen static TEE_Result sec_hash_do_final(struct crypto_hash_ctx *ctx,
42094c8a339Sleisen 				    uint8_t *digest, size_t len)
42194c8a339Sleisen {
42294c8a339Sleisen 	struct crypto_hash *hash = to_hash_ctx(ctx);
42394c8a339Sleisen 	struct hashctx *hash_ctx = hash->ctx;
42494c8a339Sleisen 
42594c8a339Sleisen 	return hisi_sec_digest_do_final(hash_ctx, digest, len);
42694c8a339Sleisen }
42794c8a339Sleisen 
hisi_sec_digest_ctx_free(struct hashctx * hash_ctx)42894c8a339Sleisen void hisi_sec_digest_ctx_free(struct hashctx *hash_ctx)
42994c8a339Sleisen {
43094c8a339Sleisen 	hisi_qm_release_qp(hash_ctx->qp);
43194c8a339Sleisen 
43294c8a339Sleisen 	free(hash_ctx->in);
43394c8a339Sleisen 	hash_ctx->in = NULL;
43494c8a339Sleisen 
43594c8a339Sleisen 	memzero_explicit(hash_ctx->key, SEC_DIGEST_MAX_KEY_SIZE);
43694c8a339Sleisen 
43794c8a339Sleisen 	free(hash_ctx);
43894c8a339Sleisen }
43994c8a339Sleisen 
sec_hash_ctx_free(struct crypto_hash_ctx * ctx)44094c8a339Sleisen static void sec_hash_ctx_free(struct crypto_hash_ctx *ctx)
44194c8a339Sleisen {
44294c8a339Sleisen 	struct crypto_hash *hash = NULL;
44394c8a339Sleisen 	struct hashctx *hash_ctx = NULL;
44494c8a339Sleisen 
44594c8a339Sleisen 	if (!ctx)
44694c8a339Sleisen 		return;
44794c8a339Sleisen 
44894c8a339Sleisen 	hash = to_hash_ctx(ctx);
44994c8a339Sleisen 	hash_ctx = hash->ctx;
45094c8a339Sleisen 	if (!hash_ctx)
45194c8a339Sleisen 		return;
45294c8a339Sleisen 	hisi_sec_digest_ctx_free(hash_ctx);
45394c8a339Sleisen 
45494c8a339Sleisen 	hash->ctx = NULL;
45594c8a339Sleisen 
45694c8a339Sleisen 	free(hash);
45794c8a339Sleisen }
45894c8a339Sleisen 
hisi_sec_digest_copy_state(struct hashctx * out_hash_ctx,struct hashctx * in_hash_ctx)45994c8a339Sleisen void hisi_sec_digest_copy_state(struct hashctx *out_hash_ctx,
46094c8a339Sleisen 				struct hashctx *in_hash_ctx)
46194c8a339Sleisen {
46294c8a339Sleisen 	out_hash_ctx->iv_len = in_hash_ctx->iv_len;
46394c8a339Sleisen 	out_hash_ctx->buf_len = in_hash_ctx->buf_len;
46494c8a339Sleisen 	out_hash_ctx->key_len = in_hash_ctx->key_len;
46594c8a339Sleisen 	out_hash_ctx->has_next = in_hash_ctx->has_next;
46694c8a339Sleisen 	out_hash_ctx->long_data_len = in_hash_ctx->long_data_len;
46794c8a339Sleisen 
46894c8a339Sleisen 	if (in_hash_ctx->in) {
46994c8a339Sleisen 		out_hash_ctx->in = malloc(out_hash_ctx->buf_len);
47094c8a339Sleisen 		if (!out_hash_ctx->in) {
47194c8a339Sleisen 			EMSG("Fail to alloc in buf");
47294c8a339Sleisen 			return;
47394c8a339Sleisen 		}
47494c8a339Sleisen 		out_hash_ctx->in_dma = virt_to_phys(out_hash_ctx->in);
47594c8a339Sleisen 		out_hash_ctx->in_len = in_hash_ctx->in_len;
47694c8a339Sleisen 		memcpy(out_hash_ctx->in, in_hash_ctx->in,
47794c8a339Sleisen 		       out_hash_ctx->buf_len);
47894c8a339Sleisen 	}
47994c8a339Sleisen 
48094c8a339Sleisen 	memcpy(out_hash_ctx->iv, in_hash_ctx->iv, out_hash_ctx->iv_len);
48194c8a339Sleisen 	memcpy(out_hash_ctx->key, in_hash_ctx->key, out_hash_ctx->key_len);
48294c8a339Sleisen }
48394c8a339Sleisen 
sec_hash_copy_state(struct crypto_hash_ctx * out_ctx,struct crypto_hash_ctx * in_ctx)48494c8a339Sleisen static void sec_hash_copy_state(struct crypto_hash_ctx *out_ctx,
48594c8a339Sleisen 				struct crypto_hash_ctx *in_ctx)
48694c8a339Sleisen {
48794c8a339Sleisen 	struct crypto_hash *out_hash = NULL;
48894c8a339Sleisen 	struct crypto_hash *in_hash = NULL;
48994c8a339Sleisen 	struct hashctx *out_hash_ctx = NULL;
49094c8a339Sleisen 	struct hashctx *in_hash_ctx = NULL;
49194c8a339Sleisen 
49294c8a339Sleisen 	if (!out_ctx || !in_ctx) {
49394c8a339Sleisen 		EMSG("Invalid input parameters");
49494c8a339Sleisen 		return;
49594c8a339Sleisen 	}
49694c8a339Sleisen 
49794c8a339Sleisen 	out_hash = to_hash_ctx(out_ctx);
49894c8a339Sleisen 	in_hash = to_hash_ctx(in_ctx);
49994c8a339Sleisen 
50094c8a339Sleisen 	out_hash_ctx = out_hash->ctx;
50194c8a339Sleisen 	in_hash_ctx = in_hash->ctx;
50294c8a339Sleisen 
50394c8a339Sleisen 	hisi_sec_digest_copy_state(out_hash_ctx, in_hash_ctx);
50494c8a339Sleisen }
50594c8a339Sleisen 
50694c8a339Sleisen static struct crypto_hash_ops hash_ops = {
50794c8a339Sleisen 	.init = sec_hash_initialize,
50894c8a339Sleisen 	.update = sec_hash_do_update,
50994c8a339Sleisen 	.final = sec_hash_do_final,
51094c8a339Sleisen 	.free_ctx = sec_hash_ctx_free,
51194c8a339Sleisen 	.copy_state = sec_hash_copy_state,
51294c8a339Sleisen };
51394c8a339Sleisen 
sec_hash_get_mac_len(uint32_t type)51494c8a339Sleisen static size_t sec_hash_get_mac_len(uint32_t type)
51594c8a339Sleisen {
51694c8a339Sleisen 	switch (type) {
51794c8a339Sleisen 	case TEE_ALG_MD5:
51894c8a339Sleisen 	case TEE_ALG_HMAC_MD5:
51994c8a339Sleisen 		return HASH_MAC_LEN128;
52094c8a339Sleisen 	case TEE_ALG_SHA1:
52194c8a339Sleisen 	case TEE_ALG_HMAC_SHA1:
52294c8a339Sleisen 		return HASH_MAC_LEN160;
52394c8a339Sleisen 	case TEE_ALG_SHA224:
52494c8a339Sleisen 	case TEE_ALG_HMAC_SHA224:
52594c8a339Sleisen 		return HASH_MAC_LEN224;
52694c8a339Sleisen 	case TEE_ALG_SM3:
52794c8a339Sleisen 	case TEE_ALG_HMAC_SM3:
52894c8a339Sleisen 	case TEE_ALG_SHA256:
52994c8a339Sleisen 	case TEE_ALG_HMAC_SHA256:
53094c8a339Sleisen 		return HASH_MAC_LEN256;
53194c8a339Sleisen 	case TEE_ALG_SHA384:
53294c8a339Sleisen 	case TEE_ALG_HMAC_SHA384:
53394c8a339Sleisen 		return HASH_MAC_LEN384;
53494c8a339Sleisen 	case TEE_ALG_SHA512:
53594c8a339Sleisen 	case TEE_ALG_HMAC_SHA512:
53694c8a339Sleisen 		return HASH_MAC_LEN512;
53794c8a339Sleisen 	default:
53894c8a339Sleisen 		return 0;
53994c8a339Sleisen 	}
54094c8a339Sleisen }
54194c8a339Sleisen 
sec_hash_get_dma(struct hashctx * hash_ctx)54294c8a339Sleisen static TEE_Result sec_hash_get_dma(struct hashctx *hash_ctx)
54394c8a339Sleisen {
54494c8a339Sleisen 	hash_ctx->key_dma = virt_to_phys(hash_ctx->key);
54594c8a339Sleisen 	if (!hash_ctx->key_dma) {
54694c8a339Sleisen 		EMSG("Fail to get key_dma");
547*e885351cSleisen 		return TEE_ERROR_GENERIC;
54894c8a339Sleisen 	}
54994c8a339Sleisen 
55094c8a339Sleisen 	hash_ctx->iv_dma = virt_to_phys(hash_ctx->iv);
55194c8a339Sleisen 	if (!hash_ctx->iv_dma) {
55294c8a339Sleisen 		EMSG("Fail to get iv_dma");
553*e885351cSleisen 		return TEE_ERROR_GENERIC;
55494c8a339Sleisen 	}
55594c8a339Sleisen 
55694c8a339Sleisen 	hash_ctx->out_dma = virt_to_phys(hash_ctx->out);
55794c8a339Sleisen 	if (!hash_ctx->out_dma) {
55894c8a339Sleisen 		EMSG("Fail to get out_dma");
559*e885351cSleisen 		return TEE_ERROR_GENERIC;
56094c8a339Sleisen 	}
56194c8a339Sleisen 
56294c8a339Sleisen 	return TEE_SUCCESS;
56394c8a339Sleisen }
56494c8a339Sleisen 
hisi_sec_hash_ctx_init(struct hashctx * hash_ctx,uint32_t algo)56594c8a339Sleisen TEE_Result hisi_sec_hash_ctx_init(struct hashctx *hash_ctx, uint32_t algo)
56694c8a339Sleisen {
56794c8a339Sleisen 	TEE_Result ret = TEE_SUCCESS;
56894c8a339Sleisen 
56994c8a339Sleisen 	hash_ctx->mac_len = sec_hash_get_mac_len(algo);
57094c8a339Sleisen 	if (!hash_ctx->mac_len) {
57194c8a339Sleisen 		EMSG("Invalid algo type %#"PRIx32, algo);
57294c8a339Sleisen 		return TEE_ERROR_NOT_IMPLEMENTED;
57394c8a339Sleisen 	}
57494c8a339Sleisen 
57594c8a339Sleisen 	hash_ctx->algo = algo;
57694c8a339Sleisen 	hash_ctx->mode = algo >> HASH_MODE_OFFSET;
57794c8a339Sleisen 
57894c8a339Sleisen 	ret = sec_hash_get_dma(hash_ctx);
57994c8a339Sleisen 	if (ret)
58094c8a339Sleisen 		return ret;
58194c8a339Sleisen 
58294c8a339Sleisen 	hash_ctx->qp = sec_create_qp(HISI_QM_CHANNEL_TYPE0);
58394c8a339Sleisen 	if (!hash_ctx->qp) {
58494c8a339Sleisen 		EMSG("Fail to create hash qp");
58594c8a339Sleisen 		return TEE_ERROR_BUSY;
58694c8a339Sleisen 	}
58794c8a339Sleisen 
58894c8a339Sleisen 	if (hash_ctx->qp->qm->version == HISI_QM_HW_V2) {
58994c8a339Sleisen 		hash_ctx->qp->fill_sqe = sec_digest_fill_sqe;
59094c8a339Sleisen 		hash_ctx->qp->parse_sqe = sec_parse_digest_sqe;
59194c8a339Sleisen 	} else {
59294c8a339Sleisen 		hash_ctx->qp->fill_sqe = sec_digest_fill_bd3_sqe;
59394c8a339Sleisen 		hash_ctx->qp->parse_sqe = sec_parse_digest_bd3_sqe;
59494c8a339Sleisen 	}
59594c8a339Sleisen 
59694c8a339Sleisen 	return TEE_SUCCESS;
59794c8a339Sleisen }
59894c8a339Sleisen 
sec_hash_ctx_allocate(struct crypto_hash_ctx ** ctx,uint32_t algo)59994c8a339Sleisen static TEE_Result sec_hash_ctx_allocate(struct crypto_hash_ctx **ctx,
60094c8a339Sleisen 					uint32_t algo)
60194c8a339Sleisen {
60294c8a339Sleisen 	struct crypto_hash *hash = NULL;
60394c8a339Sleisen 	struct hashctx *hash_ctx = NULL;
60494c8a339Sleisen 	TEE_Result ret = TEE_SUCCESS;
60594c8a339Sleisen 
60694c8a339Sleisen 	if (!ctx) {
60794c8a339Sleisen 		EMSG("Ctx is NULL");
60894c8a339Sleisen 		return TEE_ERROR_BAD_PARAMETERS;
60994c8a339Sleisen 	}
61094c8a339Sleisen 
61194c8a339Sleisen 	hash = calloc(1, sizeof(*hash));
61294c8a339Sleisen 	if (!hash) {
61394c8a339Sleisen 		EMSG("Fail to alloc hash");
614*e885351cSleisen 		return TEE_ERROR_OUT_OF_MEMORY;
61594c8a339Sleisen 	}
61694c8a339Sleisen 
61794c8a339Sleisen 	hash_ctx = calloc(1, sizeof(*hash_ctx));
61894c8a339Sleisen 	if (!hash_ctx) {
61994c8a339Sleisen 		EMSG("Fail to alloc hash_ctx");
620*e885351cSleisen 		ret = TEE_ERROR_OUT_OF_MEMORY;
62194c8a339Sleisen 		goto free_hash;
62294c8a339Sleisen 	}
62394c8a339Sleisen 
62494c8a339Sleisen 	ret = hisi_sec_hash_ctx_init(hash_ctx, algo);
62594c8a339Sleisen 	if (ret)
62694c8a339Sleisen 		goto free_ctx;
62794c8a339Sleisen 
62894c8a339Sleisen 	hash->hash_ctx.ops = &hash_ops;
62994c8a339Sleisen 	hash->ctx = hash_ctx;
63094c8a339Sleisen 	*ctx = &hash->hash_ctx;
63194c8a339Sleisen 
63294c8a339Sleisen 	return TEE_SUCCESS;
63394c8a339Sleisen 
63494c8a339Sleisen free_ctx:
63594c8a339Sleisen 	free(hash_ctx);
63694c8a339Sleisen free_hash:
63794c8a339Sleisen 	free(hash);
63894c8a339Sleisen 
63994c8a339Sleisen 	return ret;
64094c8a339Sleisen }
64194c8a339Sleisen 
sec_hash_init(void)64294c8a339Sleisen static TEE_Result sec_hash_init(void)
64394c8a339Sleisen {
64494c8a339Sleisen 	TEE_Result ret = TEE_SUCCESS;
64594c8a339Sleisen 
64694c8a339Sleisen 	ret = drvcrypt_register_hash(&sec_hash_ctx_allocate);
64794c8a339Sleisen 	if (ret)
648*e885351cSleisen 		EMSG("Sec hash register to crypto fail ret=%#"PRIx32, ret);
64994c8a339Sleisen 
65094c8a339Sleisen 	return ret;
65194c8a339Sleisen }
65294c8a339Sleisen driver_init(sec_hash_init);
653