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 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
get_ciphertext(uint8_t * dst,size_t dst_len)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
versal_sha3_384(const uint8_t * src,size_t src_len,uint8_t * dst,size_t dst_len)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
versal_sha3_384_init(void)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