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 "tee_object_api.h"
14 #include "tee_ext_api.h"
15 #include "tee_log.h"
16 #include "securec.h"
17
18 #define TA_KEY_IV_LEN 16
19 #define TA_AES_KEY_LEN 32
20 #define TA_AES_KEY_LEN_BIT (32 * 8)
21 #define TA_MAC_BUFFER_SIZE 32
22 #define TA_DATA_BUFFER_SIZE 64
23
24 static uint8_t g_data_plain_text[TA_DATA_BUFFER_SIZE] = { 0 };
25
26 enum {
27 CMD_ID_AES_CBC_MAC_DEMO = 1,
28 CMD_ID_AES_CMAC_DEMO = 2,
29 };
30
31 /*
32 * Demo For AES-CBC-MAC
33 * You can generate a key and use AES-CBC-MAC to get the MAC of TA data
34 */
crypto_api_aes_cbc_mac_test(void)35 static TEE_Result crypto_api_aes_cbc_mac_test(void)
36 {
37 TEE_Result ret;
38
39 /* operation */
40 TEE_OperationHandle operation_mac = NULL;
41 uint8_t object_id[TA_KEY_IV_LEN];
42
43 /* key object */
44 TEE_ObjectHandle object = NULL;
45
46 /* other params */
47 uint8_t *plaintext = NULL;
48 uint8_t mac_result[TA_MAC_BUFFER_SIZE] = { 0 };
49 size_t mac_len = TA_MAC_BUFFER_SIZE;
50
51 /* 1.Allocate Operation */
52 ret = TEE_AllocateOperation(&operation_mac, TEE_ALG_AES_CBC_MAC_NOPAD, TEE_MODE_MAC, TA_AES_KEY_LEN_BIT);
53 if (ret != TEE_SUCCESS) {
54 tloge("Failed to allocate operation for mac, ret is 0x%x", ret);
55 return ret;
56 }
57
58 /* 2. Generate key */
59 ret = TEE_AllocateTransientObject(TEE_TYPE_AES, TA_AES_KEY_LEN_BIT, &object);
60 if (ret != TEE_SUCCESS) {
61 tloge("Failed to allocate object for AES key: ret=0x%x", ret);
62 goto cleanup_1;
63 }
64 ret = TEE_GenerateKey(object, TA_AES_KEY_LEN_BIT, NULL, 0);
65 if (ret != TEE_SUCCESS) {
66 tloge("Failed to generate AES key:ret=0x%x", ret);
67 goto cleanup_2;
68 }
69
70 /* 3.Set operation key */
71 ret = TEE_SetOperationKey(operation_mac, object);
72 if (ret != TEE_SUCCESS) {
73 tloge("failed to set operation key for mac:ret=0x%x", ret);
74 goto cleanup_2;
75 }
76
77 /* 4.Set object_id and generate random plaintext(In user case maybe the plaintext is the key data of the TA) */
78 TEE_GenerateRandom(object_id, sizeof(object_id));
79 plaintext = g_data_plain_text;
80 TEE_GenerateRandom((void *)plaintext, sizeof(g_data_plain_text));
81
82 /* 5.Use the Key and object_id to Do AES-CBC-MAC */
83 TEE_MACInit(operation_mac, object_id, sizeof(object_id));
84 TEE_MACUpdate(operation_mac, (void *)plaintext, (size_t)(sizeof(g_data_plain_text) - TA_MAC_BUFFER_SIZE));
85 ret = TEE_MACComputeFinal(operation_mac,
86 (void *)(plaintext + sizeof(g_data_plain_text) - TA_MAC_BUFFER_SIZE),
87 TA_MAC_BUFFER_SIZE,
88 (void *)(mac_result),
89 &mac_len);
90 if (ret != TEE_SUCCESS) {
91 tloge("Failed to mac compute final do final:ret=0x%x", ret);
92 goto cleanup_2;
93 }
94 tlogi("Succeed to do AES-CBC-MAC");
95
96 cleanup_2:
97 TEE_FreeTransientObject(object);
98 cleanup_1:
99 TEE_FreeOperation(operation_mac);
100 return ret;
101 }
102
103 /*
104 * Demo For AES-CMAC
105 * You can generate a key and use AES-CMAC to get the MAC of TA data
106 */
crypto_api_aes_cmac_test(void)107 static TEE_Result crypto_api_aes_cmac_test(void)
108 {
109 TEE_Result ret;
110
111 /* operation */
112 TEE_OperationHandle operation_mac = NULL;
113
114 /* key object */
115 TEE_ObjectHandle object = NULL;
116
117 /* other params */
118 uint8_t *plaintext = NULL;
119 uint8_t mac_result[TA_MAC_BUFFER_SIZE] = { 0 };
120 size_t mac_len = TA_MAC_BUFFER_SIZE;
121
122 /* 1.Allocate Operation */
123 ret = TEE_AllocateOperation(&operation_mac, TEE_ALG_AES_CMAC, TEE_MODE_MAC, TA_AES_KEY_LEN_BIT);
124 if (ret != TEE_SUCCESS) {
125 tloge("Failed to allocate operation for mac, ret is 0x%x", ret);
126 return ret;
127 }
128
129 /* 2. Generate key */
130 ret = TEE_AllocateTransientObject(TEE_TYPE_AES, TA_AES_KEY_LEN_BIT, &object);
131 if (ret != TEE_SUCCESS) {
132 tloge("Failed to allocate object for AES key: ret=0x%x", ret);
133 goto cleanup_1;
134 }
135 ret = TEE_GenerateKey(object, TA_AES_KEY_LEN_BIT, NULL, 0);
136 if (ret != TEE_SUCCESS) {
137 tloge("Failed to generate AES key:ret=0x%x", ret);
138 goto cleanup_2;
139 }
140
141 /* 3.Set operation key */
142 ret = TEE_SetOperationKey(operation_mac, object);
143 if (ret != TEE_SUCCESS) {
144 tloge("failed to set operation key for mac:ret=0x%x", ret);
145 goto cleanup_2;
146 }
147
148 /* 4.Set object_id and generate random plaintext(In user case maybe the plaintext is the key data of the TA) */
149 plaintext = g_data_plain_text;
150 TEE_GenerateRandom((void *)plaintext, sizeof(g_data_plain_text));
151
152 /* 5.Use the Key and object_id to Do AES-CMAC(CMAC do not use object_id) */
153 TEE_MACInit(operation_mac, NULL, 0);
154 TEE_MACUpdate(operation_mac, (void *)plaintext, (size_t)(sizeof(g_data_plain_text) - TA_MAC_BUFFER_SIZE));
155 ret = TEE_MACComputeFinal(operation_mac,
156 (void *)(plaintext + sizeof(g_data_plain_text) - TA_MAC_BUFFER_SIZE),
157 TA_MAC_BUFFER_SIZE,
158 (void *)(mac_result),
159 &mac_len);
160 if (ret != TEE_SUCCESS) {
161 tloge("Failed to mac compute final do final:ret=0x%x", ret);
162 goto cleanup_2;
163 }
164 tlogi("Succeed to do AES-CMAC\n");
165 cleanup_2:
166 TEE_FreeTransientObject(object);
167 cleanup_1:
168 TEE_FreeOperation(operation_mac);
169 return ret;
170 }
171
TA_CreateEntryPoint(void)172 TEE_Result TA_CreateEntryPoint(void)
173 {
174 TEE_Result ret;
175
176 tlogd("----- TA entry point ----- ");
177 /* When you develop your own CA, you need to change the name to your own path and CA name. */
178 ret = AddCaller_CA_exec("/vendor/bin/mac_demo_ca", 0);
179 if (ret == TEE_SUCCESS) {
180 tlogd("TA entry point: add ca whitelist success");
181 } else {
182 tloge("TA entry point: add ca whitelist failed");
183 return TEE_ERROR_GENERIC;
184 }
185
186 return TEE_SUCCESS;
187 }
188
TA_OpenSessionEntryPoint(uint32_t param_types,TEE_Param params[4],void ** session_context)189 TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, TEE_Param params[4], void** session_context)
190 {
191 (void)param_types;
192 (void)params;
193 (void)session_context;
194 tlogd("---- TA MAC Demo OpenSession EntryPoint -----");
195
196 return TEE_SUCCESS;
197 }
198
TA_InvokeCommandEntryPoint(void * session_context,uint32_t cmd_id,uint32_t param_types,TEE_Param params[4])199 TEE_Result TA_InvokeCommandEntryPoint(void* session_context, uint32_t cmd_id, uint32_t param_types, TEE_Param params[4])
200 {
201 (void)session_context;
202 (void)params;
203 TEE_Result ret;
204 if (!check_param_type(param_types,
205 TEE_PARAM_TYPE_NONE,
206 TEE_PARAM_TYPE_NONE,
207 TEE_PARAM_TYPE_NONE,
208 TEE_PARAM_TYPE_NONE)) {
209 tloge("Bad expected parameter types");
210 return TEE_ERROR_BAD_PARAMETERS;
211 }
212
213 tlogd("--- TA MAC Demo InvokeCommand EntryPoint ---");
214 switch (cmd_id) {
215 case CMD_ID_AES_CBC_MAC_DEMO:
216 ret = crypto_api_aes_cbc_mac_test();
217 break;
218 case CMD_ID_AES_CMAC_DEMO:
219 ret = crypto_api_aes_cmac_test();
220 break;
221 default:
222 tloge("invalid cmd:%u", cmd_id);
223 ret = TEE_ERROR_BAD_PARAMETERS;
224 break;
225 }
226 if (ret != TEE_SUCCESS) {
227 tloge("Cmd id %u Test Failed, ret is 0x%x", cmd_id, ret);
228 } else {
229 tlogd("Cmd id %u Test Pass", cmd_id);
230 }
231 return ret;
232 }
233
TA_CloseSessionEntryPoint(void * session_context)234 void TA_CloseSessionEntryPoint(void* session_context)
235 {
236 (void)session_context;
237 tlogd("---- TA MAC Demo CloseSession EntryPoint -----");
238 }
239
TA_DestroyEntryPoint(void)240 void TA_DestroyEntryPoint(void)
241 {
242 tlogd("---- TA MAC Demo Destroy EntryPoint ----");
243 }
244