xref: /optee_os/core/drivers/crypto/aspeed/hace_ast2600.c (revision ca1d8e13c259dc00803b55cec62f814c2b5b44c2)
1e752c173SChia-Wei Wang // SPDX-License-Identifier: BSD-2-Clause
2e752c173SChia-Wei Wang /*
3e752c173SChia-Wei Wang  * Copyright (c) 2022, Aspeed Technology Inc.
4e752c173SChia-Wei Wang  */
5e752c173SChia-Wei Wang #include <stdint.h>
6e752c173SChia-Wei Wang #include <stddef.h>
7e752c173SChia-Wei Wang #include <string.h>
8e752c173SChia-Wei Wang #include <io.h>
9e752c173SChia-Wei Wang #include <util.h>
10e752c173SChia-Wei Wang #include <drvcrypt_hash.h>
11e752c173SChia-Wei Wang #include <mm/core_mmu.h>
12e752c173SChia-Wei Wang #include <mm/core_memprot.h>
13e752c173SChia-Wei Wang #include <kernel/delay.h>
14e752c173SChia-Wei Wang #include <tee/cache.h>
15e752c173SChia-Wei Wang 
16e752c173SChia-Wei Wang #include "hace_ast2600.h"
17e752c173SChia-Wei Wang 
18e752c173SChia-Wei Wang #define HACE_BASE	0x1e6d0000
19e752c173SChia-Wei Wang 
20e752c173SChia-Wei Wang /* register offsets and bit fields */
21e752c173SChia-Wei Wang #define HACE_STS		0x1C
22e752c173SChia-Wei Wang #define   HACE_STS_HASH_INT		BIT(9)
23e752c173SChia-Wei Wang #define   HACE_STS_HASH_BUSY		BIT(0)
24e752c173SChia-Wei Wang #define HACE_HASH_DATA		0x20
25e752c173SChia-Wei Wang #define HACE_HASH_DIGEST	0x24
26e752c173SChia-Wei Wang #define HACE_HASH_HMAC_KEY	0x28
27e752c173SChia-Wei Wang #define HACE_HASH_DATA_LEN	0x2C
28e752c173SChia-Wei Wang #define HACE_HASH_CMD		0x30
29e752c173SChia-Wei Wang #define   HACE_HASH_CMD_ACCUM		BIT(8)
30e752c173SChia-Wei Wang #define   HACE_HASH_CMD_ALG_SHA1	BIT(5)
31e752c173SChia-Wei Wang #define   HACE_HASH_CMD_ALG_SHA256	(BIT(6) | BIT(4))
32e752c173SChia-Wei Wang #define   HACE_HASH_CMD_ALG_SHA384	(BIT(10) | BIT(6) | BIT(5))
33e752c173SChia-Wei Wang #define   HACE_HASH_CMD_ALG_SHA512	(BIT(6) | BIT(5))
34e752c173SChia-Wei Wang #define   HACE_HASH_CMD_SHA_BE		BIT(3)
35e752c173SChia-Wei Wang 
36e752c173SChia-Wei Wang /* buffer size based on SHA-512 need */
37e752c173SChia-Wei Wang #define HASH_BLK_BUFSZ	128
38e752c173SChia-Wei Wang #define HASH_DGT_BUFSZ	64
39e752c173SChia-Wei Wang 
40e752c173SChia-Wei Wang register_phys_mem(MEM_AREA_IO_SEC, HACE_BASE, SMALL_PAGE_SIZE);
41e752c173SChia-Wei Wang 
42e752c173SChia-Wei Wang struct ast2600_hace_ctx {
43e752c173SChia-Wei Wang 	struct crypto_hash_ctx hash_ctx;
44e752c173SChia-Wei Wang 	uint32_t cmd;
45e752c173SChia-Wei Wang 	uint32_t algo;
46e752c173SChia-Wei Wang 	uint32_t dgt_size;
47e752c173SChia-Wei Wang 	uint32_t blk_size;
48e752c173SChia-Wei Wang 	uint32_t pad_size;
49e752c173SChia-Wei Wang 	uint64_t total[2];
50e752c173SChia-Wei Wang 
51e752c173SChia-Wei Wang 	/* DMA memory to interact with HACE */
52*ca1d8e13SNeal Liu 	uint8_t *buf;
53*ca1d8e13SNeal Liu 	uint8_t *digest;
54e752c173SChia-Wei Wang };
55e752c173SChia-Wei Wang 
56e752c173SChia-Wei Wang static vaddr_t hace_virt;
57e752c173SChia-Wei Wang struct mutex hace_mtx = MUTEX_INITIALIZER;
58e752c173SChia-Wei Wang 
59e752c173SChia-Wei Wang static const uint32_t iv_sha1[8] = {
60e752c173SChia-Wei Wang 	0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210,
61e752c173SChia-Wei Wang 	0xf0e1d2c3, 0, 0, 0
62e752c173SChia-Wei Wang };
63e752c173SChia-Wei Wang 
64e752c173SChia-Wei Wang static const uint32_t iv_sha256[8] = {
65e752c173SChia-Wei Wang 	0x67e6096a, 0x85ae67bb, 0x72f36e3c, 0x3af54fa5,
66e752c173SChia-Wei Wang 	0x7f520e51, 0x8c68059b, 0xabd9831f, 0x19cde05b
67e752c173SChia-Wei Wang };
68e752c173SChia-Wei Wang 
69e752c173SChia-Wei Wang static const uint32_t iv_sha384[16] = {
70e752c173SChia-Wei Wang 	0x5d9dbbcb, 0xd89e05c1, 0x2a299a62, 0x07d57c36,
71e752c173SChia-Wei Wang 	0x5a015991, 0x17dd7030, 0xd8ec2f15, 0x39590ef7,
72e752c173SChia-Wei Wang 	0x67263367, 0x310bc0ff, 0x874ab48e, 0x11155868,
73e752c173SChia-Wei Wang 	0x0d2e0cdb, 0xa78ff964, 0x1d48b547, 0xa44ffabe
74e752c173SChia-Wei Wang };
75e752c173SChia-Wei Wang 
76e752c173SChia-Wei Wang static const uint32_t iv_sha512[16] = {
77e752c173SChia-Wei Wang 	0x67e6096a, 0x08c9bcf3, 0x85ae67bb, 0x3ba7ca84,
78e752c173SChia-Wei Wang 	0x72f36e3c, 0x2bf894fe, 0x3af54fa5, 0xf1361d5f,
79e752c173SChia-Wei Wang 	0x7f520e51, 0xd182e6ad, 0x8c68059b, 0x1f6c3e2b,
80e752c173SChia-Wei Wang 	0xabd9831f, 0x6bbd41fb, 0x19cde05b, 0x79217e13
81e752c173SChia-Wei Wang };
82e752c173SChia-Wei Wang 
ast2600_hace_process(struct crypto_hash_ctx * ctx,const uint8_t * data,size_t len)83e752c173SChia-Wei Wang static TEE_Result ast2600_hace_process(struct crypto_hash_ctx *ctx,
84e752c173SChia-Wei Wang 				       const uint8_t *data, size_t len)
85e752c173SChia-Wei Wang {
86e752c173SChia-Wei Wang 	TEE_Result rc = TEE_ERROR_GENERIC;
87e752c173SChia-Wei Wang 	uint32_t sts = 0;
88e752c173SChia-Wei Wang 	uint64_t tref = 0;
89e752c173SChia-Wei Wang 	paddr_t data_phys = 0;
90e752c173SChia-Wei Wang 	paddr_t digest_phys = 0;
91e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *hctx = NULL;
92e752c173SChia-Wei Wang 
93*ca1d8e13SNeal Liu 	mutex_lock(&hace_mtx);
94*ca1d8e13SNeal Liu 
95e752c173SChia-Wei Wang 	hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx);
96e752c173SChia-Wei Wang 
97e752c173SChia-Wei Wang 	sts = io_read32(hace_virt + HACE_STS);
98*ca1d8e13SNeal Liu 	if (sts & HACE_STS_HASH_BUSY) {
99*ca1d8e13SNeal Liu 		rc = TEE_ERROR_BUSY;
100*ca1d8e13SNeal Liu 		goto out;
101*ca1d8e13SNeal Liu 	}
102e752c173SChia-Wei Wang 
103e752c173SChia-Wei Wang 	cache_operation(TEE_CACHEFLUSH, (void *)data, len);
104e752c173SChia-Wei Wang 
105e752c173SChia-Wei Wang 	data_phys = virt_to_phys((void *)data);
106e752c173SChia-Wei Wang 	digest_phys = virt_to_phys(hctx->digest);
107e752c173SChia-Wei Wang 
108e752c173SChia-Wei Wang 	io_write32(hace_virt + HACE_HASH_DATA, (uint32_t)data_phys);
109e752c173SChia-Wei Wang 	io_write32(hace_virt + HACE_HASH_DIGEST, (uint32_t)digest_phys);
110e752c173SChia-Wei Wang 	io_write32(hace_virt + HACE_HASH_HMAC_KEY, (uint32_t)digest_phys);
111e752c173SChia-Wei Wang 
112e752c173SChia-Wei Wang 	io_write32(hace_virt + HACE_HASH_DATA_LEN, len);
113e752c173SChia-Wei Wang 	io_write32(hace_virt + HACE_HASH_CMD, hctx->cmd);
114e752c173SChia-Wei Wang 
115e752c173SChia-Wei Wang 	/* poll for completion */
116e752c173SChia-Wei Wang 	tref = timeout_init_us(1000 + (len >> 3));
117e752c173SChia-Wei Wang 
118e752c173SChia-Wei Wang 	do {
119e752c173SChia-Wei Wang 		sts = io_read32(hace_virt + HACE_STS);
120e752c173SChia-Wei Wang 		if (timeout_elapsed(tref)) {
121e752c173SChia-Wei Wang 			rc = TEE_ERROR_TARGET_DEAD;
122e752c173SChia-Wei Wang 			goto out;
123e752c173SChia-Wei Wang 		}
124e752c173SChia-Wei Wang 	} while (!(sts & HACE_STS_HASH_INT));
125e752c173SChia-Wei Wang 
126*ca1d8e13SNeal Liu 	io_write32(hace_virt + HACE_STS, HACE_STS_HASH_INT);
127*ca1d8e13SNeal Liu 
128*ca1d8e13SNeal Liu 	rc = TEE_SUCCESS;
129e752c173SChia-Wei Wang out:
130e752c173SChia-Wei Wang 	mutex_unlock(&hace_mtx);
131e752c173SChia-Wei Wang 
132e752c173SChia-Wei Wang 	return rc;
133e752c173SChia-Wei Wang }
134e752c173SChia-Wei Wang 
ast2600_hace_init(struct crypto_hash_ctx * ctx)135e752c173SChia-Wei Wang static TEE_Result ast2600_hace_init(struct crypto_hash_ctx *ctx)
136e752c173SChia-Wei Wang {
137e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *hctx = NULL;
138e752c173SChia-Wei Wang 
139e752c173SChia-Wei Wang 	hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx);
140e752c173SChia-Wei Wang 
141e752c173SChia-Wei Wang 	switch (hctx->algo) {
142e752c173SChia-Wei Wang 	case TEE_ALG_SHA1:
143e752c173SChia-Wei Wang 		memcpy(hctx->digest, iv_sha1, sizeof(iv_sha1));
144e752c173SChia-Wei Wang 		break;
145e752c173SChia-Wei Wang 	case TEE_ALG_SHA256:
146e752c173SChia-Wei Wang 		memcpy(hctx->digest, iv_sha256, sizeof(iv_sha256));
147e752c173SChia-Wei Wang 		break;
148e752c173SChia-Wei Wang 	case TEE_ALG_SHA384:
149e752c173SChia-Wei Wang 		memcpy(hctx->digest, iv_sha384, sizeof(iv_sha384));
150e752c173SChia-Wei Wang 		break;
151e752c173SChia-Wei Wang 	case TEE_ALG_SHA512:
152e752c173SChia-Wei Wang 		memcpy(hctx->digest, iv_sha512, sizeof(iv_sha512));
153e752c173SChia-Wei Wang 		break;
154e752c173SChia-Wei Wang 	default:
155e752c173SChia-Wei Wang 		return TEE_ERROR_NOT_SUPPORTED;
156e752c173SChia-Wei Wang 	}
157e752c173SChia-Wei Wang 
1580c2a8f2fSNeal Liu 	hctx->total[0] = 0;
1590c2a8f2fSNeal Liu 	hctx->total[1] = 0;
160e752c173SChia-Wei Wang 
161*ca1d8e13SNeal Liu 	cache_operation(TEE_CACHEFLUSH, hctx->digest, HASH_DGT_BUFSZ);
162e752c173SChia-Wei Wang 
163e752c173SChia-Wei Wang 	return TEE_SUCCESS;
164e752c173SChia-Wei Wang }
165e752c173SChia-Wei Wang 
ast2600_hace_update(struct crypto_hash_ctx * ctx,const uint8_t * data,size_t len)166e752c173SChia-Wei Wang static TEE_Result ast2600_hace_update(struct crypto_hash_ctx *ctx,
167e752c173SChia-Wei Wang 				      const uint8_t *data, size_t len)
168e752c173SChia-Wei Wang {
169e752c173SChia-Wei Wang 	TEE_Result rc = TEE_ERROR_GENERIC;
170e752c173SChia-Wei Wang 	uint32_t left = 0;
171e752c173SChia-Wei Wang 	uint32_t fill = 0;
172e752c173SChia-Wei Wang 	size_t blk_size = 0;
173e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *hctx = NULL;
174e752c173SChia-Wei Wang 
175*ca1d8e13SNeal Liu 	if (!ctx || !data || !len)
176*ca1d8e13SNeal Liu 		return TEE_ERROR_BAD_PARAMETERS;
177*ca1d8e13SNeal Liu 
178e752c173SChia-Wei Wang 	hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx);
179e752c173SChia-Wei Wang 
180e752c173SChia-Wei Wang 	blk_size = hctx->blk_size;
181e752c173SChia-Wei Wang 
182e752c173SChia-Wei Wang 	left = hctx->total[0] & (blk_size - 1);
183e752c173SChia-Wei Wang 	fill = blk_size - left;
184e752c173SChia-Wei Wang 
185e752c173SChia-Wei Wang 	hctx->total[0] += len;
186e752c173SChia-Wei Wang 	if (hctx->total[0] < len)
187e752c173SChia-Wei Wang 		hctx->total[1]++;
188e752c173SChia-Wei Wang 
189e752c173SChia-Wei Wang 	if (left && len >= fill) {
190e752c173SChia-Wei Wang 		memcpy(hctx->buf + left, data, fill);
191e752c173SChia-Wei Wang 		rc = ast2600_hace_process(ctx, hctx->buf, blk_size);
192e752c173SChia-Wei Wang 		if (rc)
193e752c173SChia-Wei Wang 			return rc;
194e752c173SChia-Wei Wang 
195e752c173SChia-Wei Wang 		data += fill;
196e752c173SChia-Wei Wang 		len -= fill;
197e752c173SChia-Wei Wang 		left = 0;
198e752c173SChia-Wei Wang 	}
199e752c173SChia-Wei Wang 
200e752c173SChia-Wei Wang 	while (len >= blk_size) {
201*ca1d8e13SNeal Liu 		memcpy(hctx->buf, data, blk_size);
202*ca1d8e13SNeal Liu 		rc = ast2600_hace_process(ctx, hctx->buf, blk_size);
203e752c173SChia-Wei Wang 		if (rc)
204e752c173SChia-Wei Wang 			return rc;
205e752c173SChia-Wei Wang 
206e752c173SChia-Wei Wang 		data += blk_size;
207e752c173SChia-Wei Wang 		len -= blk_size;
208e752c173SChia-Wei Wang 	}
209e752c173SChia-Wei Wang 
210e752c173SChia-Wei Wang 	if (len)
211e752c173SChia-Wei Wang 		memcpy(hctx->buf + left, data, len);
212e752c173SChia-Wei Wang 
213e752c173SChia-Wei Wang 	return TEE_SUCCESS;
214e752c173SChia-Wei Wang }
215e752c173SChia-Wei Wang 
ast2600_hace_final(struct crypto_hash_ctx * ctx,uint8_t * digest,size_t len)216e752c173SChia-Wei Wang static TEE_Result ast2600_hace_final(struct crypto_hash_ctx *ctx,
217e752c173SChia-Wei Wang 				     uint8_t *digest, size_t len)
218e752c173SChia-Wei Wang {
219e752c173SChia-Wei Wang 	TEE_Result rc = TEE_ERROR_GENERIC;
220e752c173SChia-Wei Wang 	uint32_t last = 0;
221e752c173SChia-Wei Wang 	uint32_t padn = 0;
222e752c173SChia-Wei Wang 	uint8_t pad[HASH_BLK_BUFSZ * 2] = { };
223e752c173SChia-Wei Wang 	uint64_t dbits[2] = { };
224e752c173SChia-Wei Wang 	uint64_t dbits_be[2] = { };
225e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *hctx = NULL;
226*ca1d8e13SNeal Liu 	size_t length = 0;
227e752c173SChia-Wei Wang 
228e752c173SChia-Wei Wang 	hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx);
229*ca1d8e13SNeal Liu 	length = MIN(len, hctx->dgt_size);
230e752c173SChia-Wei Wang 
231e752c173SChia-Wei Wang 	memset(pad, 0, sizeof(pad));
232e752c173SChia-Wei Wang 	pad[0] = 0x80;
233e752c173SChia-Wei Wang 
234e752c173SChia-Wei Wang 	dbits[0] = (hctx->total[0] << 3);
235e752c173SChia-Wei Wang 	dbits_be[0] = get_be64(&dbits[0]);
236e752c173SChia-Wei Wang 
237e752c173SChia-Wei Wang 	dbits[1] = (hctx->total[0] >> 61) | (hctx->total[1] << 3);
238e752c173SChia-Wei Wang 	dbits_be[1] = get_be64(&dbits[1]);
239e752c173SChia-Wei Wang 
240e752c173SChia-Wei Wang 	last = hctx->total[0] & (hctx->blk_size - 1);
241e752c173SChia-Wei Wang 
2420c2a8f2fSNeal Liu 	switch (hctx->algo) {
243e752c173SChia-Wei Wang 	case TEE_ALG_SHA1:
244e752c173SChia-Wei Wang 	case TEE_ALG_SHA256:
245e752c173SChia-Wei Wang 		if (last < 56)
246e752c173SChia-Wei Wang 			padn = 56 - last;
247e752c173SChia-Wei Wang 		else
248e752c173SChia-Wei Wang 			padn = 120 - last;
249e752c173SChia-Wei Wang 
250e752c173SChia-Wei Wang 		rc = ast2600_hace_update(ctx, pad, padn);
251e752c173SChia-Wei Wang 		if (rc)
252e752c173SChia-Wei Wang 			return rc;
253e752c173SChia-Wei Wang 
254e752c173SChia-Wei Wang 		rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[0],
255e752c173SChia-Wei Wang 					 sizeof(dbits_be[0]));
256e752c173SChia-Wei Wang 		if (rc)
257e752c173SChia-Wei Wang 			return rc;
258e752c173SChia-Wei Wang 		break;
259e752c173SChia-Wei Wang 	case TEE_ALG_SHA384:
260e752c173SChia-Wei Wang 	case TEE_ALG_SHA512:
261e752c173SChia-Wei Wang 		if (last < 112)
262e752c173SChia-Wei Wang 			padn = 112 - last;
263e752c173SChia-Wei Wang 		else
264e752c173SChia-Wei Wang 			padn = 240 - last;
265e752c173SChia-Wei Wang 
266e752c173SChia-Wei Wang 		rc = ast2600_hace_update(ctx, pad, padn);
267e752c173SChia-Wei Wang 		if (rc)
268e752c173SChia-Wei Wang 			return rc;
269e752c173SChia-Wei Wang 
270e752c173SChia-Wei Wang 		rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[1],
271e752c173SChia-Wei Wang 					 sizeof(dbits_be[1]));
272e752c173SChia-Wei Wang 		if (rc)
273e752c173SChia-Wei Wang 			return rc;
274e752c173SChia-Wei Wang 
275e752c173SChia-Wei Wang 		rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[0],
276e752c173SChia-Wei Wang 					 sizeof(dbits_be[0]));
277e752c173SChia-Wei Wang 		if (rc)
278e752c173SChia-Wei Wang 			return rc;
279e752c173SChia-Wei Wang 		break;
280e752c173SChia-Wei Wang 	default:
281e752c173SChia-Wei Wang 		return TEE_ERROR_NOT_SUPPORTED;
282e752c173SChia-Wei Wang 	}
283e752c173SChia-Wei Wang 
284*ca1d8e13SNeal Liu 	cache_operation(TEE_CACHEINVALIDATE, hctx->digest, HASH_DGT_BUFSZ);
285e752c173SChia-Wei Wang 
286*ca1d8e13SNeal Liu 	memcpy(digest, hctx->digest, length);
287e752c173SChia-Wei Wang 
288e752c173SChia-Wei Wang 	return TEE_SUCCESS;
289e752c173SChia-Wei Wang }
290e752c173SChia-Wei Wang 
ast2600_hace_free(struct crypto_hash_ctx * ctx)291e752c173SChia-Wei Wang static void ast2600_hace_free(struct crypto_hash_ctx *ctx)
292e752c173SChia-Wei Wang {
293e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *hctx = NULL;
294e752c173SChia-Wei Wang 
295e752c173SChia-Wei Wang 	hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx);
296e752c173SChia-Wei Wang 
297*ca1d8e13SNeal Liu 	free(hctx->buf);
298*ca1d8e13SNeal Liu 	free(hctx->digest);
299e752c173SChia-Wei Wang 	free(hctx);
300e752c173SChia-Wei Wang }
301e752c173SChia-Wei Wang 
ast2600_hace_copy_state(struct crypto_hash_ctx * dst_ctx,struct crypto_hash_ctx * src_ctx)302e752c173SChia-Wei Wang static void ast2600_hace_copy_state(struct crypto_hash_ctx *dst_ctx,
303e752c173SChia-Wei Wang 				    struct crypto_hash_ctx *src_ctx)
304e752c173SChia-Wei Wang {
305e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *src_hctx = NULL;
306e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *dst_hctx = NULL;
307e752c173SChia-Wei Wang 
308e752c173SChia-Wei Wang 	src_hctx = container_of(src_ctx, struct ast2600_hace_ctx, hash_ctx);
309e752c173SChia-Wei Wang 	dst_hctx = container_of(dst_ctx, struct ast2600_hace_ctx, hash_ctx);
310e752c173SChia-Wei Wang 
311*ca1d8e13SNeal Liu 	dst_hctx->hash_ctx = src_hctx->hash_ctx;
312*ca1d8e13SNeal Liu 	dst_hctx->cmd = src_hctx->cmd;
313*ca1d8e13SNeal Liu 	dst_hctx->dgt_size = src_hctx->dgt_size;
314*ca1d8e13SNeal Liu 	dst_hctx->blk_size = src_hctx->blk_size;
315*ca1d8e13SNeal Liu 	dst_hctx->pad_size = src_hctx->pad_size;
316*ca1d8e13SNeal Liu 	dst_hctx->total[0] = src_hctx->total[0];
317*ca1d8e13SNeal Liu 	dst_hctx->total[1] = src_hctx->total[1];
318e752c173SChia-Wei Wang 
319*ca1d8e13SNeal Liu 	cache_operation(TEE_CACHEINVALIDATE, src_hctx->buf, HASH_BLK_BUFSZ);
320*ca1d8e13SNeal Liu 	memcpy(dst_hctx->buf, src_hctx->buf, HASH_BLK_BUFSZ);
321*ca1d8e13SNeal Liu 	cache_operation(TEE_CACHEFLUSH,	dst_hctx->buf, HASH_BLK_BUFSZ);
322e752c173SChia-Wei Wang 
323*ca1d8e13SNeal Liu 	cache_operation(TEE_CACHEINVALIDATE, src_hctx->digest, HASH_DGT_BUFSZ);
324*ca1d8e13SNeal Liu 	memcpy(dst_hctx->digest, src_hctx->digest, HASH_DGT_BUFSZ);
325*ca1d8e13SNeal Liu 	cache_operation(TEE_CACHEFLUSH,	dst_hctx->digest, HASH_DGT_BUFSZ);
326e752c173SChia-Wei Wang }
327e752c173SChia-Wei Wang 
328e752c173SChia-Wei Wang static const struct crypto_hash_ops ast2600_hace_ops = {
329e752c173SChia-Wei Wang 	.init = ast2600_hace_init,
330e752c173SChia-Wei Wang 	.update = ast2600_hace_update,
331e752c173SChia-Wei Wang 	.final = ast2600_hace_final,
332e752c173SChia-Wei Wang 	.free_ctx = ast2600_hace_free,
333e752c173SChia-Wei Wang 	.copy_state = ast2600_hace_copy_state,
334e752c173SChia-Wei Wang };
335e752c173SChia-Wei Wang 
ast2600_hace_alloc(struct crypto_hash_ctx ** pctx,uint32_t algo)336e752c173SChia-Wei Wang static TEE_Result ast2600_hace_alloc(struct crypto_hash_ctx **pctx,
337e752c173SChia-Wei Wang 				     uint32_t algo)
338e752c173SChia-Wei Wang {
339e752c173SChia-Wei Wang 	struct ast2600_hace_ctx *hctx = calloc(1, sizeof(*hctx));
340e752c173SChia-Wei Wang 
341e752c173SChia-Wei Wang 	if (!hctx)
342e752c173SChia-Wei Wang 		return TEE_ERROR_OUT_OF_MEMORY;
343*ca1d8e13SNeal Liu 	hctx->buf = memalign(HASH_BLK_BUFSZ, HASH_BLK_BUFSZ);
344*ca1d8e13SNeal Liu 	if (!hctx->buf)
345*ca1d8e13SNeal Liu 		return TEE_ERROR_OUT_OF_MEMORY;
346*ca1d8e13SNeal Liu 
347*ca1d8e13SNeal Liu 	hctx->digest = memalign(HASH_DGT_BUFSZ, HASH_DGT_BUFSZ);
348*ca1d8e13SNeal Liu 	if (!hctx->digest)
349*ca1d8e13SNeal Liu 		return TEE_ERROR_OUT_OF_MEMORY;
350e752c173SChia-Wei Wang 
3510c2a8f2fSNeal Liu 	hctx->hash_ctx.ops = &ast2600_hace_ops;
3520c2a8f2fSNeal Liu 	hctx->algo = algo;
3530c2a8f2fSNeal Liu 	hctx->cmd = HACE_HASH_CMD_ACCUM | HACE_HASH_CMD_SHA_BE;
354e752c173SChia-Wei Wang 
355e752c173SChia-Wei Wang 	switch (algo) {
356e752c173SChia-Wei Wang 	case TEE_ALG_SHA1:
357e752c173SChia-Wei Wang 		hctx->dgt_size = 20;
358e752c173SChia-Wei Wang 		hctx->blk_size = 64;
359e752c173SChia-Wei Wang 		hctx->pad_size = 8;
360e752c173SChia-Wei Wang 		hctx->cmd |= HACE_HASH_CMD_ALG_SHA1;
361e752c173SChia-Wei Wang 		break;
362e752c173SChia-Wei Wang 	case TEE_ALG_SHA256:
363e752c173SChia-Wei Wang 		hctx->dgt_size = 32;
364e752c173SChia-Wei Wang 		hctx->blk_size = 64;
365e752c173SChia-Wei Wang 		hctx->pad_size = 8;
366e752c173SChia-Wei Wang 		hctx->cmd |= HACE_HASH_CMD_ALG_SHA256;
367e752c173SChia-Wei Wang 		break;
368e752c173SChia-Wei Wang 	case TEE_ALG_SHA384:
369e752c173SChia-Wei Wang 		hctx->dgt_size = 48;
370e752c173SChia-Wei Wang 		hctx->blk_size = 128;
371e752c173SChia-Wei Wang 		hctx->pad_size = 16;
372e752c173SChia-Wei Wang 		hctx->cmd |= HACE_HASH_CMD_ALG_SHA384;
373e752c173SChia-Wei Wang 		break;
374e752c173SChia-Wei Wang 	case TEE_ALG_SHA512:
375e752c173SChia-Wei Wang 		hctx->dgt_size = 64;
376e752c173SChia-Wei Wang 		hctx->blk_size = 128;
377e752c173SChia-Wei Wang 		hctx->pad_size = 16;
378e752c173SChia-Wei Wang 		hctx->cmd |= HACE_HASH_CMD_ALG_SHA512;
379e752c173SChia-Wei Wang 		break;
380e752c173SChia-Wei Wang 	default:
381e752c173SChia-Wei Wang 		free(hctx);
382e752c173SChia-Wei Wang 		return TEE_ERROR_NOT_IMPLEMENTED;
383e752c173SChia-Wei Wang 	}
384e752c173SChia-Wei Wang 
385e752c173SChia-Wei Wang 	*pctx = &hctx->hash_ctx;
386e752c173SChia-Wei Wang 
387e752c173SChia-Wei Wang 	return TEE_SUCCESS;
388e752c173SChia-Wei Wang }
389e752c173SChia-Wei Wang 
ast2600_drvcrypt_register_hash(void)390e752c173SChia-Wei Wang TEE_Result ast2600_drvcrypt_register_hash(void)
391e752c173SChia-Wei Wang {
392e752c173SChia-Wei Wang 	hace_virt = core_mmu_get_va(HACE_BASE, MEM_AREA_IO_SEC,
393e752c173SChia-Wei Wang 				    SMALL_PAGE_SIZE);
394e752c173SChia-Wei Wang 	if (!hace_virt) {
395e752c173SChia-Wei Wang 		EMSG("cannot get HACE virtual address");
396e752c173SChia-Wei Wang 		return TEE_ERROR_GENERIC;
397e752c173SChia-Wei Wang 	}
398e752c173SChia-Wei Wang 
399e752c173SChia-Wei Wang 	return drvcrypt_register_hash(ast2600_hace_alloc);
400e752c173SChia-Wei Wang }
401