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