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