xref: /optee_os/core/drivers/versal_sha3_384.c (revision abca35a69f9bea0496cf05e025c3c36e6d5ea68b)
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 
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 		ret = versal_mbox_alloc(len, src + i * SMALL_PAGE_SIZE, &p);
32 		if (ret)
33 			return ret;
34 
35 		arg.data[0] = first | VERSAL_SHA3_384_NEXT_PACKET | len;
36 		arg.ibuf[0].mem = p;
37 		ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL);
38 		if (ret)
39 			EMSG("VERSAL_SHA3_UPDATE [%ld, len = %zu]", i, len);
40 
41 		versal_mbox_free(&p);
42 		first = 0;
43 		i++;
44 	}
45 
46 	return ret;
47 }
48 
49 static TEE_Result get_ciphertext(uint8_t *dst, size_t dst_len)
50 {
51 	struct versal_cmd_args arg = { };
52 	struct versal_mbox_mem p = { };
53 	TEE_Result ret = TEE_SUCCESS;
54 
55 	ret = versal_mbox_alloc(TEE_SHA384_HASH_SIZE, NULL, &p);
56 	if (ret)
57 		return ret;
58 
59 	arg.ibuf[0].mem = p;
60 	ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL);
61 	if (!ret)
62 		memcpy(dst, p.buf, MIN(dst_len, (size_t)TEE_SHA384_HASH_SIZE));
63 	else
64 		EMSG("VERSAL_SHA3_UPDATE final");
65 
66 	versal_mbox_free(&p);
67 
68 	return ret;
69 }
70 
71 TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len,
72 			   uint8_t *dst, size_t dst_len)
73 {
74 	TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
75 
76 	if (!src_len || !dst_len || !src || !dst)
77 		return ret;
78 
79 	if (!engine_ready)
80 		return TEE_ERROR_BAD_STATE;
81 
82 	mutex_lock(&lock);
83 
84 	ret = input_plaintext(src, src_len);
85 	if (!ret)
86 		ret = get_ciphertext(dst, dst_len);
87 
88 	mutex_unlock(&lock);
89 
90 	return ret;
91 }
92 
93 static TEE_Result versal_sha3_384_init(void)
94 {
95 	uint32_t err = 0;
96 	struct versal_cmd_args arg = { };
97 	TEE_Result ret = TEE_SUCCESS;
98 
99 	arg.data[0] = VERSAL_SHA3_KAT;
100 	arg.dlen = 1;
101 
102 	ret = versal_crypto_request(VERSAL_KAT, &arg, &err);
103 	if (!ret)
104 		engine_ready = true;
105 
106 	if (err) {
107 		DMSG("SHA3 KAT returned 0x%" PRIx32, err);
108 		return TEE_ERROR_GENERIC;
109 	}
110 
111 	return ret;
112 }
113 
114 /* Be available for the HUK */
115 service_init(versal_sha3_384_init);
116