1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include "tee_crypto_api.h"
13 #include <string.h>
14 #include <tee_log.h>
15 #include <tee_property_inner.h>
16 #include <tee_object_api.h>
17 #include <crypto_inner_defines.h>
18 #include <crypto_hal_hash.h>
19 #include <crypto_driver_adaptor.h>
20 #include "tee_operation.h"
21 #include "tee_crypto_common_hash.h"
22
23 /* For GP compatible, we add some panic when there is some error, For common use, we need to disable this panic */
24 #ifndef GP_COMPATIBLE
25 #define TEE_Panic(x) \
26 do { \
27 } while (0)
28 #endif
29
digest_update_param_check(TEE_OperationHandle operation,const void * chunk,size_t chunk_size)30 static TEE_Result digest_update_param_check(TEE_OperationHandle operation, const void *chunk, size_t chunk_size)
31 {
32 bool check = (operation == NULL || chunk == NULL || chunk_size == 0 ||
33 (check_operation((const TEE_OperationHandle)operation) != TEE_SUCCESS));
34 if (check) {
35 tloge("operation handle or other param is Invalid!");
36 return TEE_ERROR_BAD_PARAMETERS;
37 }
38
39 if (tee_get_ta_api_level() > API_LEVEL1_0 && chunk_size > MAX_SRC_SIZE) {
40 tloge("The chunk size is invalid!");
41 return TEE_ERROR_BAD_PARAMETERS;
42 }
43 return TEE_SUCCESS;
44 }
45
tee_digest_update100(TEE_OperationHandle operation,const void * chunk,size_t chunk_size)46 TEE_Result tee_digest_update100(TEE_OperationHandle operation, const void *chunk, size_t chunk_size)
47 {
48 TEE_Result ret = digest_update_param_check(operation, chunk, chunk_size);
49 if (ret != TEE_SUCCESS) {
50 TEE_Panic(ret);
51 return ret;
52 }
53
54 if (crypto_lock_operation(operation) != TEE_SUCCESS)
55 return TEE_ERROR_GENERIC;
56
57 ret = digest_operation_state_check((const TEE_OperationHandle)operation);
58 if (ret != TEE_SUCCESS) {
59 crypto_unlock_operation(operation);
60 TEE_Panic(ret);
61 return ret;
62 }
63
64 ret = proc_hal_digest_update(operation, chunk, chunk_size);
65 crypto_unlock_operation(operation);
66 if (ret != TEE_SUCCESS) {
67 tloge("Do digest update failed, ret=0x%x\n", ret);
68 TEE_Panic(ret);
69 return ret;
70 }
71
72 return TEE_SUCCESS;
73 }
74
tee_digest_update111(TEE_OperationHandle operation,const void * chunk,size_t chunk_size)75 void tee_digest_update111(TEE_OperationHandle operation, const void *chunk, size_t chunk_size)
76 {
77 if (tee_digest_update100(operation, chunk, chunk_size) != TEE_SUCCESS)
78 tloge("Tee Digest Update failed!");
79 }
80
crypto_output_buff_len_check(uint32_t algorithm,size_t output_len)81 static TEE_Result crypto_output_buff_len_check(uint32_t algorithm, size_t output_len)
82 {
83 for (uint32_t i = 0; i < ELEM_NUM(g_output_lower_limit); i++) {
84 if (g_output_lower_limit[i].algorithm == algorithm) {
85 if (output_len < g_output_lower_limit[i].output_lower_limit)
86 return TEE_ERROR_SHORT_BUFFER;
87 else
88 return TEE_SUCCESS;
89 }
90 }
91
92 return TEE_ERROR_NOT_SUPPORTED;
93 }
94
proc_hal_digest_dofinal(TEE_OperationHandle operation,const void * chunk,size_t chunk_size,void * hash,size_t * hash_len)95 static TEE_Result proc_hal_digest_dofinal(TEE_OperationHandle operation, const void *chunk, size_t chunk_size,
96 void *hash, size_t *hash_len)
97 {
98 struct memref_t data_in = {0};
99 struct memref_t data_out = {0};
100 data_in.buffer = (uint64_t)(uintptr_t)chunk;
101 data_in.size = (uint32_t)chunk_size;
102 data_out.buffer = (uint64_t)(uintptr_t)hash;
103 data_out.size = (uint32_t)(*hash_len);
104
105 TEE_Result result = proc_hal_digest_init(operation);
106 if (result != TEE_SUCCESS)
107 return result;
108
109 int32_t ret = tee_crypto_hash_dofinal(operation->crypto_ctxt, &data_in, &data_out);
110 free_operation_ctx(operation);
111
112 crypto_hal_info *crypto_hal_data = operation->hal_info;
113 crypto_hal_data->digestalloc_flag = DIGEST_NO_ALLOC_CTX;
114 if (ret != TEE_SUCCESS)
115 return change_hal_ret_to_gp(ret);
116
117 *hash_len = (size_t)data_out.size;
118
119 return TEE_SUCCESS;
120 }
121
TEE_DigestDoFinal(TEE_OperationHandle operation,const void * chunk,size_t chunkLen,void * hash,size_t * hashLen)122 TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, size_t chunkLen, void *hash,
123 size_t *hashLen)
124 {
125 bool check = (operation == NULL || hash == NULL || hashLen == NULL || *hashLen == 0 ||
126 (check_operation((const TEE_OperationHandle)operation) != TEE_SUCCESS));
127 if (check) {
128 tloge("bad params");
129 TEE_Panic(TEE_ERROR_BAD_PARAMETERS);
130 return TEE_ERROR_BAD_PARAMETERS;
131 }
132
133 if (crypto_lock_operation(operation) != TEE_SUCCESS)
134 return TEE_ERROR_GENERIC;
135
136 TEE_Result ret = digest_operation_state_check((const TEE_OperationHandle)operation);
137 if (ret != TEE_SUCCESS) {
138 crypto_unlock_operation(operation);
139 TEE_Panic(ret);
140 return ret;
141 }
142
143 if (crypto_output_buff_len_check(operation->algorithm, *hashLen) != TEE_SUCCESS) {
144 tloge("Output buffer is too short\n");
145 crypto_unlock_operation(operation);
146 return TEE_ERROR_SHORT_BUFFER;
147 }
148
149 ret = proc_hal_digest_dofinal(operation, chunk, chunkLen, hash, hashLen);
150 operation->digestLength = *hashLen;
151 crypto_unlock_operation(operation);
152 if (ret != TEE_SUCCESS) {
153 tloge("tee proc digest failed, ret=0x%x\n", ret);
154 TEE_Panic(ret);
155 return ret;
156 }
157
158 return TEE_SUCCESS;
159 }
160
161