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