1 /*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
17
18 #include "sec_clone_server.h"
19 #include <stdlib.h>
20 #include <string.h>
21 #include "securec.h"
22 #include "huks_adapter.h"
23 #include "log.h"
24 #include "commonutil.h"
25 #include "distribution.h"
26 #include "hichain.h"
27
28 #define MAX_ITER_COUNT 10
29
30 const char *SEC_CLONE_SRV_PROOF_STR = "hichain_sec_clone_server_proof";
31 const char *SEC_CLONE_CHALLENGE_STR = "hichain_sec_clone_challenge";
32 const char *SEC_CLONE_CLONE_STR = "hichain_sec_clone_clone_data";
33 const char *SEC_CLONE_SEC_RESULT_STR = "hichain_sec_clone_result";
34
35 const int32_t SEC_CLONE_START_RESP_DATA_SIZE = 9216;
36 const int32_t SEC_CLONE_CERT_CHAIN_SIZE = 9216;
37
38 const char *CERT_NUM = "certs";
39 const char *CERT_LEVEL_1 = "cert1";
40 const char *CERT_LEVEL_2 = "cert2";
41 const char *CERT_LEVEL_3 = "cert3";
42 const char *CERT_LEVEL_4 = "cert4";
43
44 const int32_t CERT_CHAIN_NUM = 4;
45
46 static int32_t parse_start_request_data(void *handle, void *data);
47 static int32_t build_start_response_data(void *handle, void *data);
48 static int32_t parse_end_request_data(void *handle, void *data);
49 static int32_t build_end_response_data(void *handle, void *data);
50
build_sec_clone_server(hc_handle hichain)51 struct sec_clone_server *build_sec_clone_server(hc_handle hichain)
52 {
53 struct hichain *hichain_ins = (struct hichain *)hichain;
54 if (hichain_ins->sts_server == NULL) {
55 LOGE("Sts server is null");
56 return NULL;
57 }
58
59 struct sec_clone_server *server = (struct sec_clone_server *)MALLOC(sizeof(struct sec_clone_server));
60 if (server == NULL) {
61 LOGE("Build sec clone server object failed");
62 return NULL;
63 }
64
65 (void)memset_s(server, sizeof(*server), 0, sizeof(*server));
66 struct server_virtual_func_group funcs = { parse_start_request_data,
67 build_start_response_data,
68 parse_end_request_data,
69 build_end_response_data };
70
71 init_server(&server->server_info, &funcs);
72 server->hichain_handle = hichain;
73 server->need_clean_temp_key = false;
74
75 return server;
76 }
77
clear_temp_key(struct hc_key_alias * temp_key_alias)78 static void clear_temp_key(struct hc_key_alias *temp_key_alias)
79 {
80 int32_t ret = check_lt_public_key_exist(temp_key_alias);
81 if (ret != HC_OK) {
82 LOGE("temp key is not exist");
83 return;
84 }
85
86 ret = delete_lt_public_key(temp_key_alias);
87 if (ret != HC_OK) {
88 LOGE("delete temp key failed");
89 }
90 }
91
destroy_sec_clone_server(struct sec_clone_server * handle)92 void destroy_sec_clone_server(struct sec_clone_server *handle)
93 {
94 if (handle == NULL) {
95 return;
96 }
97
98 if (handle->start_request_data.val != NULL) {
99 FREE(handle->start_request_data.val);
100 handle->start_request_data.val = NULL;
101 }
102
103 if (handle->client_sec_data.val != NULL) {
104 FREE(handle->client_sec_data.val);
105 handle->client_sec_data.val = NULL;
106 }
107
108 if (handle->need_clean_temp_key) {
109 struct hc_key_alias *temp_key_alias = &(handle->cert_key_alias);
110 clear_temp_key(temp_key_alias);
111 handle->need_clean_temp_key = false;
112 }
113
114 FREE(handle);
115 }
116
send_sec_clone_start_response(struct sec_clone_server * sec_clone_server,const struct message * receive,struct message * send)117 int32_t send_sec_clone_start_response(struct sec_clone_server *sec_clone_server,
118 const struct message *receive, struct message *send)
119 {
120 check_ptr_return_val(sec_clone_server, HC_INPUT_ERROR);
121 check_ptr_return_val(receive, HC_INPUT_ERROR);
122 check_ptr_return_val(send, HC_INPUT_ERROR);
123 struct uint8_buff *receive_data = (struct uint8_buff *)receive->payload;
124 struct uint8_buff *send_data = (struct uint8_buff *)MALLOC(sizeof(struct uint8_buff));
125 if (send_data == NULL) {
126 LOGE("Malloc struct send_data failed");
127 return HC_MALLOC_FAILED;
128 }
129
130 int32_t send_data_size = SEC_CLONE_START_RESP_DATA_SIZE;
131
132 send_data->val = (uint8_t *)MALLOC(send_data_size);
133 if (send_data->val == NULL) {
134 LOGE("Malloc send data failed");
135 FREE(send_data);
136 return HC_MALLOC_FAILED;
137 }
138 send_data->size = send_data_size;
139 send_data->length = send_data_size;
140 int32_t ret = send_start_response(sec_clone_server, receive_data, send_data);
141 if (ret != HC_OK) {
142 LOGE("Called send_start_response failed, error code is %d", ret);
143 FREE(send_data->val);
144 send_data->val = NULL;
145 FREE(send_data);
146 send->msg_code = INFORM_MESSAGE;
147 } else {
148 LOGI("Called send_start_response success");
149 send->msg_code = SEC_CLONE_START_RESPONSE;
150 send->payload = send_data;
151 }
152
153 return ret;
154 }
155
send_sec_clone_end_response(struct sec_clone_server * sec_clone_server,const struct message * receive,struct message * send)156 int32_t send_sec_clone_end_response(struct sec_clone_server *sec_clone_server,
157 const struct message *receive, struct message *send)
158 {
159 LOGI("Called send_sec_clone_end_response start");
160 check_ptr_return_val(sec_clone_server, HC_INPUT_ERROR);
161 check_ptr_return_val(receive, HC_INPUT_ERROR);
162 check_ptr_return_val(send, HC_INPUT_ERROR);
163 struct uint8_buff *receive_data = (struct uint8_buff *)receive->payload;
164 struct uint8_buff *send_data = (struct uint8_buff *)MALLOC(sizeof(struct uint8_buff));
165 if (send_data == NULL) {
166 LOGE("Malloc struct UINT8_BUFF failed");
167 send->msg_code = INFORM_MESSAGE;
168 return HC_MALLOC_FAILED;
169 }
170
171 int32_t send_data_size = sizeof(int32_t) + HKS_ENCRYPT_MAX_TAG_SIZE;
172
173 send_data->val = (uint8_t *)MALLOC(send_data_size);
174 if (send_data->val == NULL) {
175 send->msg_code = INFORM_MESSAGE;
176 FREE(send_data);
177 return HC_MALLOC_FAILED;
178 }
179 send_data->size = send_data_size;
180 send_data->length = send_data_size;
181
182 int32_t ret = send_end_response(sec_clone_server, receive_data, send_data);
183 if (ret != HC_OK) {
184 LOGE("Called send_end_response failed, error code is %d", ret);
185 if (send_data->val != NULL) {
186 FREE(send_data->val);
187 send_data->val = NULL;
188 }
189 FREE(send_data);
190 send->msg_code = INFORM_MESSAGE;
191 } else {
192 LOGI("Called send_end_response success");
193 send->msg_code = SEC_CLONE_ACK_RESPONSE;
194 send->payload = send_data;
195 }
196
197 return ret;
198 }
199
sec_clone_combine_challenge(struct sec_clone_server * sec_clone_server,struct uint8_buff * challenge_out)200 static int32_t sec_clone_combine_challenge(struct sec_clone_server *sec_clone_server,
201 struct uint8_buff *challenge_out)
202 {
203 struct uint8_buff *recv_challenge = &sec_clone_server->start_request_data;
204 struct hichain *hichain = (struct hichain *)sec_clone_server->hichain_handle;
205 struct sts_server *sts_server = hichain->sts_server;
206 struct challenge *challenge_c = &sts_server->peer_challenge;
207 struct challenge *challenge_s = &sts_server->my_challenge;
208
209 challenge_out->size = CHALLENGE_BUFF_LENGTH * BYTE_TO_HEX_OPER_LENGTH + recv_challenge->length;
210 challenge_out->val = (uint8_t *)MALLOC(challenge_out->size);
211 if (challenge_out->val == NULL) {
212 LOGE("Object MALLOC generate buffer failed");
213 return HC_BUILD_OBJECT_FAILED;
214 }
215
216 if (memcpy_s(challenge_out->val, challenge_out->size, recv_challenge->val, recv_challenge->length) != EOK) {
217 FREE(challenge_out->val);
218 challenge_out->val = NULL;
219 return memory_copy_error(__func__, __LINE__);
220 }
221 challenge_out->length = recv_challenge->length;
222
223 if (memcpy_s(challenge_out->val + challenge_out->length, challenge_out->size - challenge_out->length,
224 challenge_c->challenge, challenge_c->length) != EOK) {
225 FREE(challenge_out->val);
226 challenge_out->val = NULL;
227 return memory_copy_error(__func__, __LINE__);
228 }
229 challenge_out->length += CHALLENGE_BUFF_LENGTH;
230
231 if (memcpy_s(challenge_out->val + challenge_out->length, challenge_out->size - challenge_out->length,
232 challenge_s->challenge, challenge_s->length) != EOK) {
233 FREE(challenge_out->val);
234 challenge_out->val = NULL;
235 return memory_copy_error(__func__, __LINE__);
236 }
237 challenge_out->length += CHALLENGE_BUFF_LENGTH;
238
239 return HC_OK;
240 }
241
sec_clone_gen_srv_proof(struct uint8_buff * certificate_chain,struct uint8_buff * out_srv_proof)242 static int32_t sec_clone_gen_srv_proof(struct uint8_buff *certificate_chain,
243 struct uint8_buff *out_srv_proof)
244 {
245 struct uint8_buff cert_str;
246 cert_str.val = (uint8_t *)MALLOC(SEC_CLONE_CERT_CHAIN_SIZE);
247 if (cert_str.val == NULL)
248 return HC_MALLOC_FAILED;
249
250 (void)memset_s(cert_str.val, SEC_CLONE_CERT_CHAIN_SIZE, 0, SEC_CLONE_CERT_CHAIN_SIZE);
251 if (snprintf_s((char *)cert_str.val, SEC_CLONE_CERT_CHAIN_SIZE, SEC_CLONE_CERT_CHAIN_SIZE - 1,
252 "{\"%s\":%d,\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%s\"}", CERT_NUM, CERT_CHAIN_NUM,
253 CERT_LEVEL_1, certificate_chain[0].val, CERT_LEVEL_2, certificate_chain[1].val,
254 CERT_LEVEL_3, certificate_chain[2].val, CERT_LEVEL_4, certificate_chain[3].val) < 0) {
255 LOGE("String generate failed");
256 FREE(cert_str.val);
257 cert_str.val = NULL;
258 return HC_BUILD_SEND_DATA_FAILED;
259 }
260 cert_str.length = strlen((char *)cert_str.val);
261 LOGI("%d, cert_str.length: %d", __LINE__, cert_str.length);
262 LOGI("%d, strlen(cert_str.val): %d", __LINE__, strlen((const char *)cert_str.val));
263
264 out_srv_proof->val = cert_str.val;
265 out_srv_proof->length = strlen((const char *)cert_str.val);
266 out_srv_proof->size = strlen((const char *)cert_str.val);
267
268 return HC_OK;
269 }
270
parse_start_request_data(void * handle,void * data)271 static int32_t parse_start_request_data(void *handle, void *data)
272 {
273 struct sec_clone_server *sec_clone_server = (struct sec_clone_server *)handle;
274 struct uint8_buff *src_data = (struct uint8_buff *)data;
275 struct hichain *hichain = (struct hichain *)sec_clone_server->hichain_handle;
276 struct aes_aad aes_aad;
277
278 if (memcpy_s(aes_aad.aad, sizeof(aes_aad.aad), SEC_CLONE_CHALLENGE_STR, strlen(SEC_CLONE_CHALLENGE_STR)) != EOK) {
279 return memory_copy_error(__func__, __LINE__);
280 }
281
282 aes_aad.length = strlen(SEC_CLONE_CHALLENGE_STR);
283 /* out data len is less than src data len, so src data len is enough for out data */
284 int32_t out_data_len = src_data->length;
285 struct uint8_buff *out_data = &sec_clone_server->start_request_data;
286 out_data->val = (uint8_t *)MALLOC(out_data_len);
287 if (out_data->val == NULL) {
288 LOGE("MALLOC failed");
289 return HC_MALLOC_FAILED;
290 }
291 out_data->length = out_data_len;
292 out_data->size = out_data_len;
293
294 int32_t ret = aes_gcm_decrypt((struct var_buffer *)&hichain->sts_server->session_key,
295 src_data, &aes_aad, out_data);
296 if (ret != HC_OK) {
297 LOGE("Called parse sec_clone request data failed, errCode:%d", ret);
298 FREE(out_data->val);
299 out_data->val = NULL;
300 return ret;
301 }
302
303 return HC_OK;
304 }
305
gen_temp_cert_key(struct sts_server * sts_server,struct hc_key_alias * cert_key_alias)306 static int32_t gen_temp_cert_key(struct sts_server *sts_server, struct hc_key_alias *cert_key_alias)
307 {
308 int32_t ret;
309
310 struct service_id service_id = generate_service_id(sts_server->identity);
311 if (service_id.length == 0) {
312 LOGE("Generate service id failed");
313 return HC_GEN_SERVICE_ID_FAILED;
314 }
315 *cert_key_alias = generate_key_alias(&service_id, &sts_server->self_id, KEY_ALIAS_TMP);
316 if (cert_key_alias->length == 0) {
317 LOGE("Generate key alias failed");
318 return HC_GEN_ALIAS_FAILED;
319 }
320
321 ret = check_lt_public_key_exist(cert_key_alias);
322 if (ret == HC_OK) {
323 LOGE("key is exist");
324 return HC_OK;
325 }
326
327 struct hc_auth_id temp_auth_id = {
328 .auth_id = {0},
329 .length = HC_AUTH_ID_BUFF_LEN
330 };
331 ret = generate_lt_X25519_key_pair(cert_key_alias, &temp_auth_id);
332 if (ret != HC_OK) {
333 LOGE("gen temp key failed");
334 }
335 return ret;
336 }
337
gen_cert_chain_buff(struct uint8_buff * cert_chain,int32_t len)338 static int32_t gen_cert_chain_buff(struct uint8_buff *cert_chain, int32_t len)
339 {
340 if (len > CERT_CHAIN_NUM) {
341 return HC_INPUT_ERROR;
342 }
343 for (int32_t i = 0; i < CERT_CHAIN_NUM; ++i) {
344 cert_chain[i].size = SEC_CLONE_CERT_CHAIN_SIZE;
345 cert_chain[i].length = SEC_CLONE_CERT_CHAIN_SIZE;
346 cert_chain[i].val = (uint8_t *)MALLOC(SEC_CLONE_CERT_CHAIN_SIZE);
347 if (cert_chain[i].val == NULL) {
348 LOGE("MALLOC cert_chain failed");
349 return HC_MALLOC_FAILED;
350 }
351 (void)memset_s(cert_chain[i].val, SEC_CLONE_CERT_CHAIN_SIZE, 0, SEC_CLONE_CERT_CHAIN_SIZE);
352 }
353 return HC_OK;
354 }
355
build_start_response_data(void * handle,void * data)356 static int32_t build_start_response_data(void *handle, void *data)
357 {
358 struct sec_clone_server *sec_clone_server = (struct sec_clone_server *)handle;
359 struct hichain *hichain = (struct hichain *)sec_clone_server->hichain_handle;
360 struct sts_server *sts_server = (struct sts_server *)hichain->sts_server;
361 struct uint8_buff *resp_data = (struct uint8_buff *)data;
362 int32_t ret;
363
364 if (sts_server == NULL) {
365 LOGE("Sts server is null");
366 return HC_STS_OBJECT_ERROR;
367 }
368
369 struct uint8_buff combined_challenge;
370
371 ret = sec_clone_combine_challenge(sec_clone_server, &combined_challenge);
372 if (ret != HC_OK) {
373 LOGE("Combine challenge failed");
374 return ret;
375 }
376
377 struct uint8_buff cert_chain[CERT_CHAIN_NUM];
378 ret = gen_cert_chain_buff(cert_chain, CERT_CHAIN_NUM);
379 if (ret != HC_OK) {
380 goto FREE_BUFF;
381 }
382 ret = gen_temp_cert_key(sts_server, &sec_clone_server->cert_key_alias);
383 if (ret != HC_OK) {
384 LOGE("Get temp cert key failed");
385 goto FREE_BUFF;
386 }
387 sec_clone_server->need_clean_temp_key = true;
388
389 ret = get_key_attestation(&combined_challenge, &sec_clone_server->cert_key_alias, cert_chain);
390 if (ret != HC_OK) {
391 LOGE("Get key attestation failed");
392 goto FREE_BUFF;
393 }
394
395 ret = sec_clone_gen_srv_proof(cert_chain, resp_data);
396 if (ret != HC_OK) {
397 LOGE("Called sec_clone_gen_srv_proof failed");
398 }
399
400 FREE_BUFF:
401
402 if (combined_challenge.val != NULL) {
403 FREE(combined_challenge.val);
404 combined_challenge.val = NULL;
405 }
406
407 for (int32_t i = 0; i < CERT_CHAIN_NUM; ++i) {
408 if (cert_chain[i].val != NULL) {
409 FREE(cert_chain[i].val);
410 cert_chain[i].val = NULL;
411 }
412 }
413
414 return ret;
415 }
416
gen_peer_key_alias(struct sec_clone_server * sec_clone_server)417 static struct hc_key_alias gen_peer_key_alias(struct sec_clone_server *sec_clone_server)
418 {
419 struct hichain *hichain = (struct hichain *)sec_clone_server->hichain_handle;
420 struct service_id srv_id = generate_service_id(&hichain->identity);
421
422 return generate_key_alias(&srv_id, &hichain->sts_server->peer_id, KEY_ALIAS_LT_KEY_PAIR);
423 }
424
save_sec_data(struct sec_clone_server * sec_clone_server,struct uint8_buff * sec_data)425 static int32_t save_sec_data(struct sec_clone_server *sec_clone_server, struct uint8_buff *sec_data)
426 {
427 uint32_t key_len = HC_ST_PUBLIC_KEY_LEN;
428 if (sec_data->length <= key_len) {
429 LOGE("The sec_data len is lesser than key len");
430 return HC_INPUT_ERROR;
431 }
432
433 struct hc_key_alias target_alias = gen_peer_key_alias(sec_clone_server);
434
435 int32_t ret = asset_unwrap(sec_data, &sec_clone_server->cert_key_alias, &target_alias);
436 if (ret != HC_OK) {
437 LOGE("Called asset_unwrap failed, errCode:%d", ret);
438 }
439 return ret;
440 }
441
parse_end_request_data(void * handle,void * data)442 static int32_t parse_end_request_data(void *handle, void *data)
443 {
444 LOGI("Called parse_end_request_data start");
445 struct sec_clone_server *sec_clone_server = (struct sec_clone_server *)handle;
446 struct uint8_buff *src_data = (struct uint8_buff *)data;
447 struct hichain *hichain = (struct hichain *)sec_clone_server->hichain_handle;
448 struct aes_aad aes_aad;
449
450 if (memcpy_s(aes_aad.aad, sizeof(aes_aad.aad), SEC_CLONE_CLONE_STR, strlen(SEC_CLONE_CLONE_STR)) != EOK) {
451 return memory_copy_error(__func__, __LINE__);
452 }
453
454 aes_aad.length = strlen(SEC_CLONE_CLONE_STR);
455
456 struct uint8_buff *out_data = &sec_clone_server->client_sec_data;
457 out_data->val = (uint8_t *)MALLOC(src_data->length);
458 if (out_data->val == NULL) {
459 LOGE("MALLOC out_data val failed");
460 return HC_MALLOC_FAILED;
461 }
462 out_data->size = src_data->length;
463 out_data->length = src_data->length;
464
465 int32_t ret = aes_gcm_decrypt((struct var_buffer *)&hichain->sts_server->session_key, src_data, &aes_aad, out_data);
466 if (ret != HC_OK) {
467 LOGE("Called parse sec_clone request data failed, errCode:%d", ret);
468 FREE(out_data->val);
469 out_data->val = NULL;
470 return ret;
471 }
472
473 return HC_OK;
474 }
475
sec_clone_gen_end_resp(struct var_buffer * session_key,int32_t ret_code,struct uint8_buff * out_data)476 static int32_t sec_clone_gen_end_resp(struct var_buffer *session_key, int32_t ret_code, struct uint8_buff *out_data)
477 {
478 LOGI("Called sec_clone_gen_end_resp start");
479 int32_t ret;
480 struct aes_aad aes_add;
481
482 if (memcpy_s(aes_add.aad, sizeof(aes_add.aad), SEC_CLONE_SEC_RESULT_STR, strlen(SEC_CLONE_SEC_RESULT_STR)) != EOK) {
483 return memory_copy_error(__func__, __LINE__);
484 }
485
486 aes_add.length = strlen(SEC_CLONE_SEC_RESULT_STR);
487 struct uint8_buff ret_code_buff;
488 (void)memset_s(&ret_code_buff, sizeof(ret_code_buff), 0, sizeof(ret_code_buff));
489
490 ret_code_buff.val = (uint8_t *)MALLOC(sizeof(int32_t));
491 if (ret_code_buff.val == NULL) {
492 LOGE("MALLOC ret_code_buff failed");
493 return HC_MALLOC_FAILED;
494 }
495
496 ret_code_buff.size = sizeof(int32_t);
497 ret_code_buff.length = ret_code_buff.size;
498
499 (void)memcpy_s(ret_code_buff.val, sizeof(int32_t), &ret_code, sizeof(int32_t));
500
501 out_data->size = ret_code_buff.length * BYTE_TO_HEX_OPER_LENGTH + HKS_ENCRYPT_MAX_TAG_SIZE;
502 ret = aes_gcm_encrypt(session_key, &ret_code_buff, &aes_add, out_data);
503 if (ret != ERROR_CODE_SUCCESS) {
504 LOGE("Encrypt retCode failed, errCode:%d", ret);
505 }
506 if (ret_code_buff.val != NULL) {
507 FREE(ret_code_buff.val);
508 ret_code_buff.val = NULL;
509 }
510
511 return ret;
512 }
513
build_end_response_data(void * handle,void * data)514 static int32_t build_end_response_data(void *handle, void *data)
515 {
516 LOGI("Called build_end_response_data start");
517 struct sec_clone_server *sec_clone_server = (struct sec_clone_server *)handle;
518 struct hichain *hichain = (struct hichain *)sec_clone_server->hichain_handle;
519 struct sts_server *sts_server = hichain->sts_server;
520 struct uint8_buff *out_data = (struct uint8_buff *)data;
521
522 int32_t unwrap_ret = save_sec_data(sec_clone_server, &sec_clone_server->client_sec_data);
523 if (unwrap_ret != HC_OK) {
524 LOGE("Called save_sec_data failed, errCode:%d", unwrap_ret);
525 return unwrap_ret;
526 }
527
528 int32_t ret = sec_clone_gen_end_resp((struct var_buffer *)&sts_server->session_key, unwrap_ret, out_data);
529 if (ret != HC_OK) {
530 LOGE("Called sec_clone_gen_end_resp failed, errCode:%d", ret);
531 }
532 return ret;
533 }
534
535 #else
536
537 #include "sec_clone_server.h"
538 #include "log.h"
539 #include "mem_stat.h"
540
build_sec_clone_server(hc_handle hichain)541 struct sec_clone_server *build_sec_clone_server(hc_handle hichain)
542 {
543 LOGE("Donot support sec clone protocol");
544 (void)hichain;
545 return (struct sec_clone_server *)MALLOC(sizeof(struct sec_clone_server));
546 }
547
destroy_sec_clone_server(struct sec_clone_server * handle)548 void destroy_sec_clone_server(struct sec_clone_server *handle)
549 {
550 LOGE("Donot support sec clone protocol");
551 FREE(handle);
552 }
553
554 #endif
555