1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) Foundries Ltd. 2022
4  * Author: Jorge Ramirez <jorge@foundries.io>
5  */
6 
7 #include <drivers/versal_sha3_384.h>
8 #include <initcall.h>
9 #include <ipi.h>
10 #include <mm/core_memprot.h>
11 #include <string.h>
12 
13 #define VERSAL_SHA3_384_FIRST_PACKET		BIT(30)
14 #define VERSAL_SHA3_384_NEXT_PACKET		BIT(31)
15 
16 static struct mutex lock = MUTEX_INITIALIZER;
17 static bool engine_ready;
18 
input_plaintext(const uint8_t * src,size_t src_len)19 static TEE_Result input_plaintext(const uint8_t *src, size_t src_len)
20 {
21 	uint32_t first = VERSAL_SHA3_384_FIRST_PACKET;
22 	struct versal_cmd_args arg = { .dlen = 1, };
23 	struct versal_mbox_mem p = { };
24 	TEE_Result ret = TEE_SUCCESS;
25 	size_t len = 0;
26 	size_t i = 0;
27 
28 	while (src_len && !ret) {
29 		len = MIN(src_len, SMALL_PAGE_SIZE);
30 		src_len -= len;
31 		versal_mbox_alloc(len, src + i * SMALL_PAGE_SIZE, &p);
32 
33 		arg.data[0] = first | VERSAL_SHA3_384_NEXT_PACKET | len;
34 		arg.ibuf[0].mem = p;
35 		ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL);
36 		if (ret)
37 			EMSG("VERSAL_SHA3_UPDATE [%ld, len = %zu]", i, len);
38 
39 		free(p.buf);
40 		first = 0;
41 		i++;
42 	}
43 
44 	return ret;
45 }
46 
get_ciphertext(uint8_t * dst,size_t dst_len)47 static TEE_Result get_ciphertext(uint8_t *dst, size_t dst_len)
48 {
49 	struct versal_cmd_args arg = { };
50 	struct versal_mbox_mem p = { };
51 	TEE_Result ret = TEE_SUCCESS;
52 
53 	versal_mbox_alloc(TEE_SHA384_HASH_SIZE, NULL, &p);
54 
55 	arg.ibuf[0].mem = p;
56 	ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL);
57 	if (!ret)
58 		memcpy(dst, p.buf, MIN(dst_len, (size_t)TEE_SHA384_HASH_SIZE));
59 	else
60 		EMSG("VERSAL_SHA3_UPDATE final");
61 
62 	free(p.buf);
63 
64 	return ret;
65 }
66 
versal_sha3_384(const uint8_t * src,size_t src_len,uint8_t * dst,size_t dst_len)67 TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len,
68 			   uint8_t *dst, size_t dst_len)
69 {
70 	TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
71 
72 	if (!src_len || !dst_len || !src || !dst)
73 		return ret;
74 
75 	if (!engine_ready)
76 		return TEE_ERROR_BAD_STATE;
77 
78 	mutex_lock(&lock);
79 
80 	ret = input_plaintext(src, src_len);
81 	if (!ret)
82 		ret = get_ciphertext(dst, dst_len);
83 
84 	mutex_unlock(&lock);
85 
86 	return ret;
87 }
88 
versal_sha3_384_init(void)89 static TEE_Result versal_sha3_384_init(void)
90 {
91 	struct versal_cmd_args arg = { };
92 	TEE_Result ret = TEE_SUCCESS;
93 
94 	ret = versal_crypto_request(VERSAL_SHA3_KAT, &arg, NULL);
95 	if (!ret)
96 		engine_ready = true;
97 
98 	return ret;
99 }
100 
101 /* Be available for the HUK */
102 service_init(versal_sha3_384_init);
103