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