1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <boot_rkimg.h>
8*4882a593Smuzhiyun #include <stdlib.h>
9*4882a593Smuzhiyun #include <attestation_key.h>
10*4882a593Smuzhiyun #include <write_keybox.h>
11*4882a593Smuzhiyun #include <keymaster.h>
12*4882a593Smuzhiyun #include <optee_include/OpteeClientApiLib.h>
13*4882a593Smuzhiyun #include <optee_include/tee_client_api.h>
14*4882a593Smuzhiyun #include <optee_include/tee_api_defines.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define STORAGE_CMD_WRITE 6
17*4882a593Smuzhiyun #define SIZE_OF_TAG 4
18*4882a593Smuzhiyun #define BOOT_FROM_EMMC (1 << 1)
19*4882a593Smuzhiyun #define WIDEVINE_TAG "KBOX"
20*4882a593Smuzhiyun #define ATTESTATION_TAG "ATTE"
21*4882a593Smuzhiyun #define PLAYREADY30_TAG "SL30"
22*4882a593Smuzhiyun
write_to_security_storage(uint8_t is_use_rpmb,uint8_t * filename,uint32_t filename_size,uint8_t * data,uint32_t data_size)23*4882a593Smuzhiyun TEEC_Result write_to_security_storage(uint8_t is_use_rpmb,
24*4882a593Smuzhiyun uint8_t *filename,
25*4882a593Smuzhiyun uint32_t filename_size,
26*4882a593Smuzhiyun uint8_t *data,
27*4882a593Smuzhiyun uint32_t data_size)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun TEEC_Result TeecResult;
30*4882a593Smuzhiyun TEEC_Context TeecContext;
31*4882a593Smuzhiyun TEEC_Session TeecSession;
32*4882a593Smuzhiyun TEEC_SharedMemory SharedMem0 = {0};
33*4882a593Smuzhiyun TEEC_SharedMemory SharedMem1 = {0};
34*4882a593Smuzhiyun uint32_t ErrorOrigin;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun TEEC_UUID tempuuid = { 0x1b484ea5,
37*4882a593Smuzhiyun 0x698b,
38*4882a593Smuzhiyun 0x4142,
39*4882a593Smuzhiyun { 0x82, 0xb8, 0x3a,
40*4882a593Smuzhiyun 0xcf, 0x16, 0xe9,
41*4882a593Smuzhiyun 0x9e, 0x2a } };
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun TEEC_UUID *TeecUuid = &tempuuid;
44*4882a593Smuzhiyun TEEC_Operation TeecOperation = {0};
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun TeecResult = OpteeClientApiLibInitialize();
47*4882a593Smuzhiyun if (TeecResult) {
48*4882a593Smuzhiyun printf("OpteeClientApiLibInitialize fail\n");
49*4882a593Smuzhiyun return TeecResult;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun TeecResult = TEEC_InitializeContext(NULL, &TeecContext);
52*4882a593Smuzhiyun if (TeecResult) {
53*4882a593Smuzhiyun printf("TEEC_InitializeContext fail\n");
54*4882a593Smuzhiyun return TeecResult;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
57*4882a593Smuzhiyun TEEC_NONE,
58*4882a593Smuzhiyun TEEC_NONE,
59*4882a593Smuzhiyun TEEC_NONE);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /*0 nand or emmc "security" partition , 1 rpmb*/
62*4882a593Smuzhiyun TeecOperation.params[0].value.a = is_use_rpmb;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun TeecResult = TEEC_OpenSession(&TeecContext,
65*4882a593Smuzhiyun &TeecSession,
66*4882a593Smuzhiyun TeecUuid,
67*4882a593Smuzhiyun TEEC_LOGIN_PUBLIC,
68*4882a593Smuzhiyun NULL, &TeecOperation,
69*4882a593Smuzhiyun &ErrorOrigin);
70*4882a593Smuzhiyun if (TeecResult) {
71*4882a593Smuzhiyun printf("TEEC_OpenSession fail\n");
72*4882a593Smuzhiyun return TeecResult;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun SharedMem0.size = filename_size;
76*4882a593Smuzhiyun SharedMem0.flags = 0;
77*4882a593Smuzhiyun TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem0);
78*4882a593Smuzhiyun if (TeecResult) {
79*4882a593Smuzhiyun printf("TEEC_AllocateSharedMemory fail\n");
80*4882a593Smuzhiyun return TeecResult;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun memcpy(SharedMem0.buffer, filename, SharedMem0.size);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun SharedMem1.size = data_size;
85*4882a593Smuzhiyun SharedMem1.flags = 0;
86*4882a593Smuzhiyun TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem1);
87*4882a593Smuzhiyun if (TeecResult) {
88*4882a593Smuzhiyun printf("TEEC_AllocateSharedMemory fail\n");
89*4882a593Smuzhiyun return TeecResult;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun memcpy(SharedMem1.buffer, data, SharedMem1.size);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun TeecOperation.params[0].tmpref.buffer = SharedMem0.buffer;
94*4882a593Smuzhiyun TeecOperation.params[0].tmpref.size = SharedMem0.size;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun TeecOperation.params[1].tmpref.buffer = SharedMem1.buffer;
97*4882a593Smuzhiyun TeecOperation.params[1].tmpref.size = SharedMem1.size;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
100*4882a593Smuzhiyun TEEC_MEMREF_TEMP_INOUT,
101*4882a593Smuzhiyun TEEC_NONE,
102*4882a593Smuzhiyun TEEC_NONE);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun TeecResult = TEEC_InvokeCommand(&TeecSession,
105*4882a593Smuzhiyun 1,
106*4882a593Smuzhiyun &TeecOperation,
107*4882a593Smuzhiyun &ErrorOrigin);
108*4882a593Smuzhiyun if (TeecResult) {
109*4882a593Smuzhiyun printf("TEEC_InvokeCommand fail\n");
110*4882a593Smuzhiyun return TeecResult;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun TEEC_ReleaseSharedMemory(&SharedMem0);
113*4882a593Smuzhiyun TEEC_ReleaseSharedMemory(&SharedMem1);
114*4882a593Smuzhiyun TEEC_CloseSession(&TeecSession);
115*4882a593Smuzhiyun TEEC_FinalizeContext(&TeecContext);
116*4882a593Smuzhiyun debug("TeecResult %x\n", TeecResult);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun return TeecResult;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
rk_send_keybox_to_ta(uint8_t * filename,uint32_t filename_size,TEEC_UUID uuid,uint8_t * key,uint32_t key_size,uint8_t * data,uint32_t data_size)121*4882a593Smuzhiyun uint32_t rk_send_keybox_to_ta(uint8_t *filename, uint32_t filename_size,
122*4882a593Smuzhiyun TEEC_UUID uuid,
123*4882a593Smuzhiyun uint8_t *key, uint32_t key_size,
124*4882a593Smuzhiyun uint8_t *data, uint32_t data_size)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun uint32_t ErrorOrigin;
127*4882a593Smuzhiyun TEEC_Result TeecResult;
128*4882a593Smuzhiyun TEEC_Context TeecContext;
129*4882a593Smuzhiyun TEEC_Session TeecSession;
130*4882a593Smuzhiyun TEEC_UUID *TeecUuid = &uuid;
131*4882a593Smuzhiyun TEEC_Operation TeecOperation = {0};
132*4882a593Smuzhiyun TEEC_SharedMemory SharedMem0 = {0};
133*4882a593Smuzhiyun TEEC_SharedMemory SharedMem1 = {0};
134*4882a593Smuzhiyun TEEC_SharedMemory SharedMem2 = {0};
135*4882a593Smuzhiyun struct blk_desc *dev_desc;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun dev_desc = rockchip_get_bootdev();
138*4882a593Smuzhiyun if (!dev_desc) {
139*4882a593Smuzhiyun printf("%s: dev_desc is NULL!\n", __func__);
140*4882a593Smuzhiyun return -TEEC_ERROR_GENERIC;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun TeecResult = OpteeClientApiLibInitialize();
144*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
145*4882a593Smuzhiyun return TeecResult;
146*4882a593Smuzhiyun TeecResult = TEEC_InitializeContext(NULL, &TeecContext);
147*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
148*4882a593Smuzhiyun return TeecResult;
149*4882a593Smuzhiyun TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
150*4882a593Smuzhiyun TEEC_NONE,
151*4882a593Smuzhiyun TEEC_NONE,
152*4882a593Smuzhiyun TEEC_NONE);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* 0 nand or emmc "security" partition , 1 rpmb */
155*4882a593Smuzhiyun TeecOperation.params[0].value.a =
156*4882a593Smuzhiyun (dev_desc->if_type == IF_TYPE_MMC) ? 1 : 0;
157*4882a593Smuzhiyun #ifdef CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION
158*4882a593Smuzhiyun TeecOperation.params[0].value.a = 0;
159*4882a593Smuzhiyun #endif
160*4882a593Smuzhiyun TeecResult = TEEC_OpenSession(&TeecContext,
161*4882a593Smuzhiyun &TeecSession,
162*4882a593Smuzhiyun TeecUuid,
163*4882a593Smuzhiyun TEEC_LOGIN_PUBLIC,
164*4882a593Smuzhiyun NULL,
165*4882a593Smuzhiyun &TeecOperation,
166*4882a593Smuzhiyun &ErrorOrigin);
167*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
168*4882a593Smuzhiyun return TeecResult;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun SharedMem0.size = filename_size;
171*4882a593Smuzhiyun SharedMem0.flags = 0;
172*4882a593Smuzhiyun TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem0);
173*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
174*4882a593Smuzhiyun return TeecResult;
175*4882a593Smuzhiyun memcpy(SharedMem0.buffer, filename, SharedMem0.size);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun SharedMem1.size = key_size;
178*4882a593Smuzhiyun SharedMem1.flags = 0;
179*4882a593Smuzhiyun TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem1);
180*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
181*4882a593Smuzhiyun return TeecResult;
182*4882a593Smuzhiyun memcpy(SharedMem1.buffer, key, SharedMem1.size);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun SharedMem2.size = data_size;
185*4882a593Smuzhiyun SharedMem2.flags = 0;
186*4882a593Smuzhiyun TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem2);
187*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
188*4882a593Smuzhiyun return TeecResult;
189*4882a593Smuzhiyun memcpy(SharedMem2.buffer, data, SharedMem2.size);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun TeecOperation.params[0].tmpref.buffer = SharedMem0.buffer;
192*4882a593Smuzhiyun TeecOperation.params[0].tmpref.size = SharedMem0.size;
193*4882a593Smuzhiyun TeecOperation.params[1].tmpref.buffer = SharedMem1.buffer;
194*4882a593Smuzhiyun TeecOperation.params[1].tmpref.size = SharedMem1.size;
195*4882a593Smuzhiyun TeecOperation.params[2].tmpref.buffer = SharedMem2.buffer;
196*4882a593Smuzhiyun TeecOperation.params[2].tmpref.size = SharedMem2.size;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
199*4882a593Smuzhiyun TEEC_MEMREF_TEMP_INPUT,
200*4882a593Smuzhiyun TEEC_MEMREF_TEMP_INOUT,
201*4882a593Smuzhiyun TEEC_NONE);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun printf("write keybox to secure storage\n");
204*4882a593Smuzhiyun TeecResult = TEEC_InvokeCommand(&TeecSession,
205*4882a593Smuzhiyun STORAGE_CMD_WRITE,
206*4882a593Smuzhiyun &TeecOperation,
207*4882a593Smuzhiyun &ErrorOrigin);
208*4882a593Smuzhiyun if (TeecResult != TEEC_SUCCESS)
209*4882a593Smuzhiyun printf("send data to TA failed with code 0x%x\n", TeecResult);
210*4882a593Smuzhiyun else
211*4882a593Smuzhiyun printf("send data to TA success with code 0x%x\n", TeecResult);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun TEEC_ReleaseSharedMemory(&SharedMem0);
214*4882a593Smuzhiyun TEEC_ReleaseSharedMemory(&SharedMem1);
215*4882a593Smuzhiyun TEEC_ReleaseSharedMemory(&SharedMem2);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun TEEC_CloseSession(&TeecSession);
218*4882a593Smuzhiyun TEEC_FinalizeContext(&TeecContext);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun return TeecResult;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
write_keybox_to_secure_storage(uint8_t * received_data,uint32_t len)223*4882a593Smuzhiyun uint32_t write_keybox_to_secure_storage(uint8_t *received_data, uint32_t len)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun uint8_t *widevine_data;
226*4882a593Smuzhiyun uint8_t *attestation_data;
227*4882a593Smuzhiyun uint8_t *playready_sl30_data;
228*4882a593Smuzhiyun uint32_t key_size;
229*4882a593Smuzhiyun uint32_t data_size;
230*4882a593Smuzhiyun int rc = 0;
231*4882a593Smuzhiyun TEEC_Result ret;
232*4882a593Smuzhiyun struct blk_desc *dev_desc;
233*4882a593Smuzhiyun uint8_t is_use_rpmb;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun dev_desc = rockchip_get_bootdev();
236*4882a593Smuzhiyun if (!dev_desc) {
237*4882a593Smuzhiyun printf("%s: dev_desc is NULL!\n", __func__);
238*4882a593Smuzhiyun return -EIO;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun is_use_rpmb = (dev_desc->if_type == IF_TYPE_MMC) ? 1 : 0;
241*4882a593Smuzhiyun #ifdef CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION
242*4882a593Smuzhiyun is_use_rpmb = 0;
243*4882a593Smuzhiyun #endif
244*4882a593Smuzhiyun if (is_use_rpmb)
245*4882a593Smuzhiyun printf("I will write key to rpmb\n");
246*4882a593Smuzhiyun else
247*4882a593Smuzhiyun printf("I will write key to security partition\n");
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun rc = write_to_security_storage(0, (uint8_t *)"security_partition",
250*4882a593Smuzhiyun sizeof("security_partition"),
251*4882a593Smuzhiyun &is_use_rpmb, sizeof(is_use_rpmb));
252*4882a593Smuzhiyun if (rc)
253*4882a593Smuzhiyun return -EIO;
254*4882a593Smuzhiyun widevine_data = (uint8_t *)new_strstr((char *)received_data,
255*4882a593Smuzhiyun WIDEVINE_TAG, len);
256*4882a593Smuzhiyun attestation_data = (uint8_t *)new_strstr((char *)received_data,
257*4882a593Smuzhiyun ATTESTATION_TAG, len);
258*4882a593Smuzhiyun playready_sl30_data = (uint8_t *)new_strstr((char *)received_data,
259*4882a593Smuzhiyun PLAYREADY30_TAG, len);
260*4882a593Smuzhiyun if (widevine_data) {
261*4882a593Smuzhiyun /* widevine keybox */
262*4882a593Smuzhiyun TEEC_UUID widevine_uuid = { 0x1b484ea5, 0x698b, 0x4142,
263*4882a593Smuzhiyun { 0x82, 0xb8, 0x3a, 0xcf, 0x16, 0xe9, 0x9e, 0x2a } };
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun key_size = *(widevine_data + SIZE_OF_TAG);
266*4882a593Smuzhiyun data_size = *(widevine_data + SIZE_OF_TAG + sizeof(key_size));
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun ret = rk_send_keybox_to_ta((uint8_t *)"widevine_keybox",
269*4882a593Smuzhiyun sizeof("widevine_keybox"),
270*4882a593Smuzhiyun widevine_uuid,
271*4882a593Smuzhiyun widevine_data + SIZE_OF_TAG +
272*4882a593Smuzhiyun sizeof(key_size) + sizeof(data_size),
273*4882a593Smuzhiyun key_size,
274*4882a593Smuzhiyun widevine_data + 12 + key_size,
275*4882a593Smuzhiyun data_size);
276*4882a593Smuzhiyun if (ret == TEEC_SUCCESS) {
277*4882a593Smuzhiyun rc = 0;
278*4882a593Smuzhiyun printf("write widevine keybox to secure storage success\n");
279*4882a593Smuzhiyun } else {
280*4882a593Smuzhiyun rc = -EIO;
281*4882a593Smuzhiyun printf("write widevine keybox to secure storage fail\n");
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun } else if (attestation_data) {
284*4882a593Smuzhiyun /* attestation key */
285*4882a593Smuzhiyun atap_result ret;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun ret = write_attestation_key_to_secure_storage(attestation_data,
288*4882a593Smuzhiyun len);
289*4882a593Smuzhiyun if (ret == ATAP_RESULT_OK) {
290*4882a593Smuzhiyun rc = 0;
291*4882a593Smuzhiyun printf("write attestation key to secure storage success\n");
292*4882a593Smuzhiyun } else {
293*4882a593Smuzhiyun rc = -EIO;
294*4882a593Smuzhiyun printf("write attestation key to secure storage fail\n");
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun } else if (playready_sl30_data) {
297*4882a593Smuzhiyun /* PlayReady SL3000 root key */
298*4882a593Smuzhiyun uint32_t ret;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun data_size = *(playready_sl30_data + SIZE_OF_TAG);
301*4882a593Smuzhiyun ret = write_to_security_storage(is_use_rpmb,
302*4882a593Smuzhiyun (uint8_t *)"PlayReady_SL3000",
303*4882a593Smuzhiyun sizeof("PlayReady_SL3000"),
304*4882a593Smuzhiyun playready_sl30_data +
305*4882a593Smuzhiyun SIZE_OF_TAG +sizeof(data_size),
306*4882a593Smuzhiyun data_size);
307*4882a593Smuzhiyun if (ret == TEEC_SUCCESS) {
308*4882a593Smuzhiyun rc = 0;
309*4882a593Smuzhiyun printf("write PlayReady SL3000 root key to secure storage success\n");
310*4882a593Smuzhiyun } else {
311*4882a593Smuzhiyun rc = -EIO;
312*4882a593Smuzhiyun printf("write PlayReady SL3000 root key to secure storage fail\n");
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun /* write all data to secure storage for readback check */
317*4882a593Smuzhiyun if (!rc) {
318*4882a593Smuzhiyun uint32_t ret;
319*4882a593Smuzhiyun uint8_t *raw_data = malloc(len + sizeof(uint32_t));
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* add raw_data_len(4 byte) in begin of raw_data */
322*4882a593Smuzhiyun memcpy(raw_data, &len, sizeof(uint32_t));
323*4882a593Smuzhiyun memcpy((raw_data + sizeof(uint32_t)), received_data, len);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun ret = write_to_security_storage(is_use_rpmb,
326*4882a593Smuzhiyun (uint8_t *)"raw_data",
327*4882a593Smuzhiyun sizeof("raw_data"),
328*4882a593Smuzhiyun raw_data,
329*4882a593Smuzhiyun len + sizeof(uint32_t));
330*4882a593Smuzhiyun if (ret == TEEC_SUCCESS)
331*4882a593Smuzhiyun rc = 0;
332*4882a593Smuzhiyun else
333*4882a593Smuzhiyun rc = -EIO;
334*4882a593Smuzhiyun free(raw_data);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun return rc;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
read_raw_data_from_secure_storage(uint8_t * data,uint32_t data_size)339*4882a593Smuzhiyun uint32_t read_raw_data_from_secure_storage(uint8_t *data, uint32_t data_size)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun uint32_t rc;
342*4882a593Smuzhiyun uint32_t key_size;
343*4882a593Smuzhiyun uint8_t *read_data = malloc(1024 * 40);
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun rc = read_from_keymaster((uint8_t *)"raw_data", sizeof("raw_data"),
346*4882a593Smuzhiyun read_data, data_size);
347*4882a593Smuzhiyun if (rc != TEEC_SUCCESS)
348*4882a593Smuzhiyun return 0;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun memcpy(&key_size, read_data, sizeof(uint32_t));
351*4882a593Smuzhiyun memcpy(data, read_data + sizeof(uint32_t), key_size);
352*4882a593Smuzhiyun rc = key_size;
353*4882a593Smuzhiyun free(read_data);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun return rc;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
new_strstr(const char * s1,const char * s2,uint32_t l1)358*4882a593Smuzhiyun char *new_strstr(const char *s1, const char *s2, uint32_t l1)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun uint32_t l2;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun l2 = strlen(s2);
363*4882a593Smuzhiyun if (!l2)
364*4882a593Smuzhiyun return (char *)s1;
365*4882a593Smuzhiyun while (l1 >= l2) {
366*4882a593Smuzhiyun l1--;
367*4882a593Smuzhiyun if (!memcmp(s1, s2, l2))
368*4882a593Smuzhiyun return (char *)s1;
369*4882a593Smuzhiyun s1++;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun return NULL;
372*4882a593Smuzhiyun }
373