xref: /rk3399_rockchip-uboot/common/write_keybox.c (revision 2f6c020d95ebda22b28d3a31f574ec547a9281fb)
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 	if (dev_desc->if_type == IF_TYPE_MMC && dev_desc->devnum == 0)//emmc
158 		TeecOperation.params[0].value.a = 1;
159 	else if (dev_desc->if_type == IF_TYPE_SCSI)//ufs
160 		TeecOperation.params[0].value.a = 1;
161 	else
162 		TeecOperation.params[0].value.a = 0;
163 
164 #ifdef CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION
165 	TeecOperation.params[0].value.a = 0;
166 #endif
167 	TeecResult = TEEC_OpenSession(&TeecContext,
168 				      &TeecSession,
169 				      TeecUuid,
170 				      TEEC_LOGIN_PUBLIC,
171 				      NULL,
172 				      &TeecOperation,
173 				      &ErrorOrigin);
174 	if (TeecResult != TEEC_SUCCESS)
175 		return TeecResult;
176 
177 	SharedMem0.size = filename_size;
178 	SharedMem0.flags = 0;
179 	TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem0);
180 	if (TeecResult != TEEC_SUCCESS)
181 		return TeecResult;
182 	memcpy(SharedMem0.buffer, filename, SharedMem0.size);
183 
184 	SharedMem1.size = key_size;
185 	SharedMem1.flags = 0;
186 	TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem1);
187 	if (TeecResult != TEEC_SUCCESS)
188 		return TeecResult;
189 	memcpy(SharedMem1.buffer, key, SharedMem1.size);
190 
191 	SharedMem2.size = data_size;
192 	SharedMem2.flags = 0;
193 	TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem2);
194 	if (TeecResult != TEEC_SUCCESS)
195 		return TeecResult;
196 	memcpy(SharedMem2.buffer, data, SharedMem2.size);
197 
198 	TeecOperation.params[0].tmpref.buffer = SharedMem0.buffer;
199 	TeecOperation.params[0].tmpref.size = SharedMem0.size;
200 	TeecOperation.params[1].tmpref.buffer = SharedMem1.buffer;
201 	TeecOperation.params[1].tmpref.size = SharedMem1.size;
202 	TeecOperation.params[2].tmpref.buffer = SharedMem2.buffer;
203 	TeecOperation.params[2].tmpref.size = SharedMem2.size;
204 
205 	TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
206 						    TEEC_MEMREF_TEMP_INPUT,
207 						    TEEC_MEMREF_TEMP_INOUT,
208 						    TEEC_NONE);
209 
210 	printf("write keybox to secure storage\n");
211 	TeecResult = TEEC_InvokeCommand(&TeecSession,
212 					STORAGE_CMD_WRITE,
213 					&TeecOperation,
214 					&ErrorOrigin);
215 	if (TeecResult != TEEC_SUCCESS)
216 		printf("send data to TA failed with code 0x%x\n", TeecResult);
217 	else
218 		printf("send data to TA success with code 0x%x\n", TeecResult);
219 
220 	TEEC_ReleaseSharedMemory(&SharedMem0);
221 	TEEC_ReleaseSharedMemory(&SharedMem1);
222 	TEEC_ReleaseSharedMemory(&SharedMem2);
223 
224 	TEEC_CloseSession(&TeecSession);
225 	TEEC_FinalizeContext(&TeecContext);
226 
227 	return TeecResult;
228 }
229 
230 uint32_t write_keybox_to_secure_storage(uint8_t *received_data, uint32_t len)
231 {
232 	uint8_t *widevine_data;
233 	uint8_t *attestation_data;
234 	uint8_t *id_attestation_data;
235 	uint8_t *playready_sl30_data;
236 	uint32_t key_size;
237 	uint32_t data_size;
238 	int rc = 0;
239 	TEEC_Result ret;
240 	struct blk_desc *dev_desc;
241 	uint8_t is_use_rpmb;
242 
243 	dev_desc = rockchip_get_bootdev();
244 	if (!dev_desc) {
245 		printf("%s: dev_desc is NULL!\n", __func__);
246 		return -EIO;
247 	}
248 
249 	/*0 nand or emmc "security" partition , 1 rpmb*/
250 	if (dev_desc->if_type == IF_TYPE_MMC && dev_desc->devnum == 0)//emmc
251 		is_use_rpmb = 1;
252 	else if (dev_desc->if_type == IF_TYPE_SCSI)//ufs
253 		is_use_rpmb = 1;
254 	else
255 		is_use_rpmb = 0;
256 
257 #ifdef CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION
258 	is_use_rpmb = 0;
259 #endif
260 	if (is_use_rpmb)
261 		printf("I will write key to rpmb\n");
262 	else
263 		printf("I will write key to security partition\n");
264 
265 	rc = write_to_security_storage(0, (uint8_t *)"security_partition",
266 				       sizeof("security_partition"),
267 				       &is_use_rpmb, sizeof(is_use_rpmb));
268 	if (rc)
269 		return -EIO;
270 	widevine_data = (uint8_t *)new_strstr((char *)received_data,
271 					      WIDEVINE_TAG, len);
272 	attestation_data = (uint8_t *)new_strstr((char *)received_data,
273 						 ATTESTATION_TAG, len);
274 	id_attestation_data = (uint8_t *)new_strstr((char *)received_data,
275 						    ID_ATTESTATION_TAG, len);
276 	playready_sl30_data = (uint8_t *)new_strstr((char *)received_data,
277 						    PLAYREADY30_TAG, len);
278 	if (widevine_data) {
279 		/* widevine keybox */
280 		TEEC_UUID widevine_uuid = { 0x1b484ea5, 0x698b, 0x4142,
281 			{ 0x82, 0xb8, 0x3a, 0xcf, 0x16, 0xe9, 0x9e, 0x2a } };
282 
283 		key_size = *(widevine_data + SIZE_OF_TAG);
284 		data_size = *(widevine_data + SIZE_OF_TAG + sizeof(key_size));
285 
286 		ret = rk_send_keybox_to_ta((uint8_t *)"widevine_keybox",
287 					   sizeof("widevine_keybox"),
288 					   widevine_uuid,
289 					   widevine_data + SIZE_OF_TAG +
290 					   sizeof(key_size) + sizeof(data_size),
291 					   key_size,
292 					   widevine_data + 12 + key_size,
293 					   data_size);
294 		if (ret == TEEC_SUCCESS) {
295 			rc = 0;
296 			printf("write widevine keybox to secure storage success\n");
297 		} else {
298 			rc = -EIO;
299 			printf("write widevine keybox to secure storage fail\n");
300 		}
301 	} else if (attestation_data) {
302 		/* attestation key */
303 		atap_result ret;
304 
305 		ret = write_attestation_key_to_secure_storage(attestation_data,
306 							      len);
307 		if (ret == ATAP_RESULT_OK) {
308 			rc = 0;
309 			printf("write attestation key to secure storage success\n");
310 		} else {
311 			rc = -EIO;
312 			printf("write attestation key to secure storage fail\n");
313 		}
314 	} else if (id_attestation_data) {
315 		/* id attestation */
316 		ret = write_id_attestation_to_secure_storage(id_attestation_data, len);
317 		if (ret == ATAP_RESULT_OK) {
318 			rc = 0;
319 			printf("write id attestation success!\n");
320 		} else {
321 			rc = -EIO;
322 			printf("write id attestation failed\n");
323 		}
324 	} else if (playready_sl30_data) {
325 		/* PlayReady SL3000 root key */
326 		uint32_t ret;
327 
328 		data_size = *(playready_sl30_data + SIZE_OF_TAG);
329 		ret = write_to_security_storage(is_use_rpmb,
330 						(uint8_t *)"PlayReady_SL3000",
331 						sizeof("PlayReady_SL3000"),
332 						playready_sl30_data +
333 						SIZE_OF_TAG +sizeof(data_size),
334 						data_size);
335 		if (ret == TEEC_SUCCESS) {
336 			rc = 0;
337 			printf("write PlayReady SL3000 root key to secure storage success\n");
338 		} else {
339 			rc = -EIO;
340 			printf("write PlayReady SL3000 root key to secure storage fail\n");
341 		}
342 	}
343 
344 	/* write all data to secure storage for readback check */
345 	if (!rc) {
346 		uint32_t ret;
347 		uint8_t *raw_data = malloc(len + sizeof(uint32_t));
348 
349 		/* add raw_data_len(4 byte) in begin of raw_data */
350 		memcpy(raw_data, &len, sizeof(uint32_t));
351 		memcpy((raw_data + sizeof(uint32_t)), received_data, len);
352 
353 		ret = write_to_security_storage(is_use_rpmb,
354 						(uint8_t *)"raw_data",
355 						sizeof("raw_data"),
356 						raw_data,
357 						len + sizeof(uint32_t));
358 		if (ret == TEEC_SUCCESS)
359 			rc = 0;
360 		else
361 			rc = -EIO;
362 		free(raw_data);
363 	}
364 	return rc;
365 }
366 
367 uint32_t read_raw_data_from_secure_storage(uint8_t *data, uint32_t data_size)
368 {
369 	uint32_t rc;
370 	uint32_t key_size;
371 	uint8_t *read_data = malloc(1024 * 40);
372 
373 	rc = read_from_keymaster((uint8_t *)"raw_data", sizeof("raw_data"),
374 				 read_data, data_size);
375 	if (rc != TEEC_SUCCESS)
376 		return 0;
377 
378 	memcpy(&key_size, read_data, sizeof(uint32_t));
379 	memcpy(data, read_data + sizeof(uint32_t), key_size);
380 	rc = key_size;
381 	free(read_data);
382 
383 	return rc;
384 }
385 
386 char *new_strstr(const char *s1, const char *s2, uint32_t l1)
387 {
388 	uint32_t l2;
389 
390 	l2 = strlen(s2);
391 	if (!l2)
392 		return (char *)s1;
393 	while (l1 >= l2) {
394 		l1--;
395 		if (!memcmp(s1, s2, l2))
396 			return (char *)s1;
397 		s1++;
398 	}
399 	return NULL;
400 }
401