xref: /OK3568_Linux_fs/u-boot/common/write_keybox.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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