xref: /OK3568_Linux_fs/external/security/librkcrypto/src/rkcrypto_otp_key.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
3  */
4 #include <string.h>
5 #include "rkcrypto_core_int.h"
6 #include "rkcrypto_otp_key.h"
7 #include "rkcrypto_trace.h"
8 #include "tee_client_api.h"
9 
10 #define STORAGE_UUID { 0x2d26d8a8, 0x5134, 0x4dd8, \
11 		{ 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }
12 #define RK_CRYPTO_SERVICE_UUID	{ 0x0cacdb5d, 0x4fea, 0x466c, \
13 		{ 0x97, 0x16, 0x3d, 0x54, 0x16, 0x52, 0x83, 0x0f } }
14 
15 #define STORAGE_CMD_WRITE_OEM_OTP_KEY			14
16 #define STORAGE_CMD_SET_OEM_HR_OTP_READ_LOCK		15
17 #define STORAGE_CMD_OEM_OTP_KEY_IS_WRITTEN		16
18 #define CRYPTO_SERVICE_CMD_OEM_OTP_KEY_CIPHER		0x00000001
19 #define CRYPTO_SERVICE_CMD_OEM_OTP_KEY_PHYS_CIPHER	0x00000002
20 
21 static const struct {
22 	const uint32_t tee_code;
23 	const uint32_t rk_crypto_code;
24 } tee_crypto_code[] = {
25 	{TEEC_SUCCESS,			RK_CRYPTO_SUCCESS},
26 	{TEEC_ERROR_GENERIC,		RK_CRYPTO_ERR_GENERIC},
27 	{TEEC_ERROR_BAD_PARAMETERS,	RK_CRYPTO_ERR_PARAMETER},
28 	{TEEC_ERROR_BAD_STATE,		RK_CRYPTO_ERR_STATE},
29 	{TEEC_ERROR_NOT_SUPPORTED,	RK_CRYPTO_ERR_NOT_SUPPORTED},
30 	{TEEC_ERROR_OUT_OF_MEMORY,	RK_CRYPTO_ERR_OUT_OF_MEMORY},
31 	{TEEC_ERROR_ACCESS_DENIED,	RK_CRYPTO_ERR_ACCESS_DENIED},
32 };
33 
tee_to_crypto_code(uint32_t tee_code)34 static RK_RES tee_to_crypto_code(uint32_t tee_code)
35 {
36 	uint32_t i;
37 	uint32_t array_size = sizeof(tee_crypto_code) / sizeof((tee_crypto_code)[0]);
38 
39 	for (i = 0; i < array_size; i++) {
40 		if (tee_code == tee_crypto_code[i].tee_code)
41 			return tee_crypto_code[i].rk_crypto_code;
42 	}
43 
44 	/* Others convert to RK_CRYPTO_ERR_GENERIC. */
45 	return RK_CRYPTO_ERR_GENERIC;
46 }
47 
cipher_get_blocksize(uint32_t algo)48 static uint32_t cipher_get_blocksize(uint32_t algo)
49 {
50 	switch (algo) {
51 	case RK_ALGO_DES:
52 	case RK_ALGO_TDES:
53 		return DES_BLOCK_SIZE;
54 	case RK_ALGO_AES:
55 		return AES_BLOCK_SIZE;
56 	case RK_ALGO_SM4:
57 		return SM4_BLOCK_SIZE;
58 	default:
59 		return 1;
60 	}
61 }
62 
rk_write_oem_otp_key(enum RK_OEM_OTP_KEYID key_id,uint8_t * key,uint32_t key_len)63 RK_RES rk_write_oem_otp_key(enum RK_OEM_OTP_KEYID key_id, uint8_t *key,
64 			    uint32_t key_len)
65 {
66 	RK_RES res;
67 	TEEC_Context contex;
68 	TEEC_Session session;
69 	TEEC_Operation operation;
70 	TEEC_UUID uuid = STORAGE_UUID;
71 	uint32_t error_origin = 0;
72 
73 	RK_CRYPTO_CHECK_PARAM(key_id != RK_OEM_OTP_KEY0 &&
74 			      key_id != RK_OEM_OTP_KEY1 &&
75 			      key_id != RK_OEM_OTP_KEY2 &&
76 			      key_id != RK_OEM_OTP_KEY3 &&
77 			      key_id != RK_OEM_OTP_KEY_FW);
78 	RK_CRYPTO_CHECK_PARAM(!key);
79 	RK_CRYPTO_CHECK_PARAM(key_len != 16 &&
80 			      key_len != 24 &&
81 			      key_len != 32);
82 	RK_CRYPTO_CHECK_PARAM(key_id == RK_OEM_OTP_KEY_FW &&
83 			      key_len != 16);
84 
85 	res = TEEC_InitializeContext(NULL, &contex);
86 	if (res != TEEC_SUCCESS) {
87 		E_TRACE("TEEC_InitializeContext failed with code TEEC res= 0x%x", res);
88 		return tee_to_crypto_code(res);
89 	}
90 
91 	res = TEEC_OpenSession(&contex, &session, &uuid, TEEC_LOGIN_PUBLIC,
92 			       NULL, NULL, &error_origin);
93 	if (res != TEEC_SUCCESS) {
94 		E_TRACE("TEEC_Opensession failed with code TEEC res= 0x%x origin 0x%x",
95 			res, error_origin);
96 		goto out;
97 	}
98 
99 	memset(&operation, 0, sizeof(TEEC_Operation));
100 	operation.params[0].value.a       = key_id;
101 	operation.params[1].tmpref.buffer = key;
102 	operation.params[1].tmpref.size   = key_len;
103 	operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
104 						TEEC_MEMREF_TEMP_INPUT,
105 						TEEC_NONE,
106 						TEEC_NONE);
107 
108 	res = TEEC_InvokeCommand(&session, STORAGE_CMD_WRITE_OEM_OTP_KEY,
109 				 &operation, &error_origin);
110 	if (res != TEEC_SUCCESS) {
111 		E_TRACE("InvokeCommand ERR! TEEC res= 0x%x, error_origin= 0x%x",
112 			res, error_origin);
113 	}
114 
115 	TEEC_CloseSession(&session);
116 out:
117 	TEEC_FinalizeContext(&contex);
118 	return tee_to_crypto_code(res);
119 }
120 
rk_oem_otp_key_is_written(enum RK_OEM_OTP_KEYID key_id,uint8_t * is_written)121 RK_RES rk_oem_otp_key_is_written(enum RK_OEM_OTP_KEYID key_id, uint8_t *is_written)
122 {
123 	RK_RES res;
124 	TEEC_Context contex;
125 	TEEC_Session session;
126 	TEEC_Operation operation;
127 	TEEC_UUID uuid = STORAGE_UUID;
128 	uint32_t error_origin = 0;
129 
130 	RK_CRYPTO_CHECK_PARAM(key_id != RK_OEM_OTP_KEY0 &&
131 			      key_id != RK_OEM_OTP_KEY1 &&
132 			      key_id != RK_OEM_OTP_KEY2 &&
133 			      key_id != RK_OEM_OTP_KEY3 &&
134 			      key_id != RK_OEM_OTP_KEY_FW);
135 	RK_CRYPTO_CHECK_PARAM(!is_written);
136 
137 	res = TEEC_InitializeContext(NULL, &contex);
138 	if (res != TEEC_SUCCESS) {
139 		E_TRACE("TEEC_InitializeContext failed with code TEEC res= 0x%x", res);
140 		return tee_to_crypto_code(res);
141 	}
142 
143 	res = TEEC_OpenSession(&contex, &session, &uuid, TEEC_LOGIN_PUBLIC,
144 			       NULL, NULL, &error_origin);
145 	if (res != TEEC_SUCCESS) {
146 		E_TRACE("TEEC_Opensession failed with code TEEC res= 0x%x origin 0x%x",
147 			res, error_origin);
148 		goto out;
149 	}
150 
151 	memset(&operation, 0, sizeof(TEEC_Operation));
152 	operation.params[0].value.a = key_id;
153 	operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT,
154 						TEEC_NONE,
155 						TEEC_NONE,
156 						TEEC_NONE);
157 
158 	res = TEEC_InvokeCommand(&session, STORAGE_CMD_OEM_OTP_KEY_IS_WRITTEN,
159 				 &operation, &error_origin);
160 	if (res == TEEC_ERROR_ACCESS_DENIED) {
161 		E_TRACE("Check if it has been set oem_hr_otp_read_lock!");
162 	} else if (res != TEEC_SUCCESS) {
163 		E_TRACE("InvokeCommand ERR! TEEC res= 0x%x, error_origin= 0x%x",
164 			res, error_origin);
165 	} else {
166 		*is_written = operation.params[0].value.b;
167 	}
168 
169 	TEEC_CloseSession(&session);
170 
171 out:
172 	TEEC_FinalizeContext(&contex);
173 	return tee_to_crypto_code(res);
174 }
175 
rk_set_oem_hr_otp_read_lock(enum RK_OEM_OTP_KEYID key_id)176 RK_RES rk_set_oem_hr_otp_read_lock(enum RK_OEM_OTP_KEYID key_id)
177 {
178 	RK_RES res;
179 	TEEC_Context contex;
180 	TEEC_Session session;
181 	TEEC_Operation operation;
182 	TEEC_UUID uuid = STORAGE_UUID;
183 	uint32_t error_origin = 0;
184 
185 	RK_CRYPTO_CHECK_PARAM(key_id != RK_OEM_OTP_KEY0 &&
186 			      key_id != RK_OEM_OTP_KEY1 &&
187 			      key_id != RK_OEM_OTP_KEY2 &&
188 			      key_id != RK_OEM_OTP_KEY3);
189 
190 	res = TEEC_InitializeContext(NULL, &contex);
191 	if (res != TEEC_SUCCESS) {
192 		E_TRACE("TEEC_InitializeContext failed with code TEEC res= 0x%x", res);
193 		return tee_to_crypto_code(res);
194 	}
195 
196 	res = TEEC_OpenSession(&contex, &session, &uuid, TEEC_LOGIN_PUBLIC,
197 			       NULL, NULL, &error_origin);
198 	if (res != TEEC_SUCCESS) {
199 		E_TRACE("TEEC_Opensession failed with code TEEC res= 0x%x origin 0x%x",
200 			res, error_origin);
201 		goto out;
202 	}
203 
204 	memset(&operation, 0, sizeof(TEEC_Operation));
205 	operation.params[0].value.a = key_id;
206 	operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
207 						TEEC_NONE,
208 						TEEC_NONE,
209 						TEEC_NONE);
210 
211 	res = TEEC_InvokeCommand(&session, STORAGE_CMD_SET_OEM_HR_OTP_READ_LOCK,
212 				 &operation, &error_origin);
213 	if (res != TEEC_SUCCESS) {
214 		E_TRACE("InvokeCommand ERR! TEEC res= 0x%x, error_origin= 0x%x",
215 			res, error_origin);
216 	}
217 
218 	TEEC_CloseSession(&session);
219 out:
220 	TEEC_FinalizeContext(&contex);
221 	return tee_to_crypto_code(res);
222 }
223 
rk_oem_otp_key_cipher_virt(enum RK_OEM_OTP_KEYID key_id,rk_cipher_config * config,uint8_t * src,uint8_t * dst,uint32_t len)224 RK_RES rk_oem_otp_key_cipher_virt(enum RK_OEM_OTP_KEYID key_id, rk_cipher_config *config,
225 				  uint8_t *src, uint8_t *dst, uint32_t len)
226 {
227 	RK_RES res;
228 	TEEC_Context contex;
229 	TEEC_Session session;
230 	TEEC_Operation operation;
231 	TEEC_UUID uuid = RK_CRYPTO_SERVICE_UUID;
232 	uint32_t error_origin = 0, len_aligned, len_cipher, block_size;
233 	TEEC_SharedMemory sm;
234 
235 	RK_CRYPTO_CHECK_PARAM(key_id != RK_OEM_OTP_KEY0 &&
236 			      key_id != RK_OEM_OTP_KEY1 &&
237 			      key_id != RK_OEM_OTP_KEY2 &&
238 			      key_id != RK_OEM_OTP_KEY3 &&
239 			      key_id != RK_OEM_OTP_KEY_FW);
240 	RK_CRYPTO_CHECK_PARAM(!config  || !src || !dst);
241 	RK_CRYPTO_CHECK_PARAM(config->algo != RK_ALGO_AES &&
242 			      config->algo != RK_ALGO_SM4);
243 	RK_CRYPTO_CHECK_PARAM(config->mode >= RK_CIPHER_MODE_XTS);
244 	RK_CRYPTO_CHECK_PARAM(config->operation != RK_OP_CIPHER_ENC &&
245 			      config->operation != RK_OP_CIPHER_DEC);
246 	RK_CRYPTO_CHECK_PARAM(config->key_len != 16 &&
247 			      config->key_len != 24 &&
248 			      config->key_len != 32);
249 	RK_CRYPTO_CHECK_PARAM(key_id == RK_OEM_OTP_KEY_FW &&
250 			      config->key_len != 16);
251 	RK_CRYPTO_CHECK_PARAM(len > RK_CRYPTO_MAX_DATA_LEN ||
252 			      len == 0);
253 	RK_CRYPTO_CHECK_PARAM(config->mode == RK_CIPHER_MODE_CTS &&
254 			      len <= 16);
255 
256 	len_cipher = len;
257 	block_size  = cipher_get_blocksize(config->algo);
258 
259 	if (config->mode != RK_CIPHER_MODE_CTS && (len % block_size)) {
260 		RK_CRYPTO_CHECK_PARAM(config->mode != RK_CIPHER_MODE_CTR &&
261 				      config->mode != RK_CIPHER_MODE_CFB &&
262 				      config->mode != RK_CIPHER_MODE_OFB);
263 
264 		len_aligned = ROUNDUP(len, block_size);
265 		len_cipher  = len_aligned;
266 	}
267 
268 	res = TEEC_InitializeContext(NULL, &contex);
269 	if (res != TEEC_SUCCESS) {
270 		E_TRACE("TEEC_InitializeContext failed with code TEEC res= 0x%x", res);
271 		return tee_to_crypto_code(res);
272 	}
273 
274 	res = TEEC_OpenSession(&contex, &session, &uuid, TEEC_LOGIN_PUBLIC,
275 			       NULL, NULL, &error_origin);
276 	if (res != TEEC_SUCCESS) {
277 		E_TRACE("TEEC_Opensession failed with code TEEC res= 0x%x origin 0x%x",
278 			res, error_origin);
279 		goto out;
280 	}
281 
282 	sm.size = len_cipher;
283 	sm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
284 	res = TEEC_AllocateSharedMemory(&contex, &sm);
285 	if (res != TEEC_SUCCESS) {
286 		E_TRACE("AllocateSharedMemory ERR! TEEC res= 0x%x", res);
287 		goto out1;
288 	}
289 
290 	memset(sm.buffer, 0, sm.size);
291 	memcpy(sm.buffer, src, len);
292 
293 	memset(&operation, 0, sizeof(TEEC_Operation));
294 	operation.params[0].value.a       = key_id;
295 	operation.params[1].tmpref.buffer = config;
296 	operation.params[1].tmpref.size   = sizeof(rk_cipher_config);
297 	operation.params[2].memref.parent = &sm;
298 	operation.params[2].memref.offset = 0;
299 	operation.params[2].memref.size   = sm.size;
300 
301 	operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
302 						TEEC_MEMREF_TEMP_INPUT,
303 						TEEC_MEMREF_PARTIAL_INOUT,
304 						TEEC_NONE);
305 
306 	res = TEEC_InvokeCommand(&session, CRYPTO_SERVICE_CMD_OEM_OTP_KEY_CIPHER,
307 				 &operation, &error_origin);
308 	if (res != TEEC_SUCCESS) {
309 		E_TRACE("InvokeCommand ERR! TEEC res= 0x%x, error_origin= 0x%x",
310 			res, error_origin);
311 	} else {
312 		memcpy(dst, sm.buffer, sm.size);
313 	}
314 
315 	TEEC_ReleaseSharedMemory(&sm);
316 
317 out1:
318 	TEEC_CloseSession(&session);
319 
320 out:
321 	TEEC_FinalizeContext(&contex);
322 	return tee_to_crypto_code(res);
323 }
324 
rk_oem_otp_key_cipher(enum RK_OEM_OTP_KEYID key_id,rk_cipher_config * config,int32_t in_fd,int32_t out_fd,uint32_t len)325 RK_RES rk_oem_otp_key_cipher(enum RK_OEM_OTP_KEYID key_id, rk_cipher_config *config,
326 			     int32_t in_fd, int32_t out_fd, uint32_t len)
327 {
328 	RK_RES res;
329 	TEEC_Context contex;
330 	TEEC_Session session;
331 	TEEC_Operation operation;
332 	TEEC_UUID uuid = RK_CRYPTO_SERVICE_UUID;
333 	uint32_t error_origin = 0, len_aligned, len_cipher, block_size;
334 	struct crypt_fd_map_op src_mop;
335 	struct crypt_fd_map_op dst_mop;
336 
337 	RK_CRYPTO_CHECK_PARAM(in_fd < 0);
338 	RK_CRYPTO_CHECK_PARAM(out_fd < 0);
339 	RK_CRYPTO_CHECK_PARAM(key_id != RK_OEM_OTP_KEY0 &&
340 			      key_id != RK_OEM_OTP_KEY1 &&
341 			      key_id != RK_OEM_OTP_KEY2 &&
342 			      key_id != RK_OEM_OTP_KEY3 &&
343 			      key_id != RK_OEM_OTP_KEY_FW);
344 	RK_CRYPTO_CHECK_PARAM(!config);
345 	RK_CRYPTO_CHECK_PARAM(config->algo != RK_ALGO_AES &&
346 			      config->algo != RK_ALGO_SM4);
347 	RK_CRYPTO_CHECK_PARAM(config->mode >= RK_CIPHER_MODE_XTS);
348 	RK_CRYPTO_CHECK_PARAM(config->operation != RK_OP_CIPHER_ENC &&
349 			      config->operation != RK_OP_CIPHER_DEC);
350 	RK_CRYPTO_CHECK_PARAM(config->key_len != 16 &&
351 			      config->key_len != 24 &&
352 			      config->key_len != 32);
353 	RK_CRYPTO_CHECK_PARAM(key_id == RK_OEM_OTP_KEY_FW &&
354 			      config->key_len != 16);
355 	RK_CRYPTO_CHECK_PARAM(len == 0);
356 	RK_CRYPTO_CHECK_PARAM(config->mode == RK_CIPHER_MODE_CTS &&
357 			      len <= 16);
358 
359 	len_cipher = len;
360 	block_size  = cipher_get_blocksize(config->algo);
361 
362 	if (config->mode != RK_CIPHER_MODE_CTS && (len % block_size)) {
363 		RK_CRYPTO_CHECK_PARAM(config->mode != RK_CIPHER_MODE_CTR &&
364 				      config->mode != RK_CIPHER_MODE_CFB &&
365 				      config->mode != RK_CIPHER_MODE_OFB);
366 
367 		len_aligned = ROUNDUP(len, block_size);
368 		len_cipher  = len_aligned;
369 	}
370 
371 	memset(&src_mop, 0, sizeof(src_mop));
372 	memset(&dst_mop, 0, sizeof(dst_mop));
373 	src_mop.dma_fd = in_fd;
374 	dst_mop.dma_fd = out_fd;
375 
376 	res = rk_crypto_fd_ioctl(RIOCCRYPT_FD_MAP, &src_mop);
377 	if (res != RK_CRYPTO_SUCCESS) {
378 		E_TRACE("RIOCCRYPT_FD_MAP failed, res= 0x%x", res);
379 		return res;
380 	}
381 
382 	if (out_fd != in_fd) {
383 		res = rk_crypto_fd_ioctl(RIOCCRYPT_FD_MAP, &dst_mop);
384 		if (res != RK_CRYPTO_SUCCESS) {
385 			E_TRACE("RIOCCRYPT_FD_MAP failed, res= 0x%x", res);
386 			goto out;
387 		}
388 	} else {
389 		dst_mop.phys_addr = src_mop.phys_addr;
390 	}
391 
392 	res = TEEC_InitializeContext(NULL, &contex);
393 	if (res != TEEC_SUCCESS) {
394 		E_TRACE("TEEC_InitializeContext failed with code TEEC res= 0x%x", res);
395 		goto out1;
396 	}
397 
398 	res = TEEC_OpenSession(&contex, &session, &uuid, TEEC_LOGIN_PUBLIC,
399 			       NULL, NULL, &error_origin);
400 	if (res != TEEC_SUCCESS) {
401 		E_TRACE("TEEC_Opensession failed with code TEEC res= 0x%x origin 0x%x",
402 			res, error_origin);
403 		goto out2;
404 	}
405 
406 	memset(&operation, 0, sizeof(TEEC_Operation));
407 	operation.params[0].value.a       = key_id;
408 	operation.params[1].tmpref.buffer = config;
409 	operation.params[1].tmpref.size   = sizeof(rk_cipher_config);
410 	operation.params[2].value.a       = src_mop.phys_addr;
411 	operation.params[2].value.b       = len_cipher;
412 	operation.params[3].value.a       = dst_mop.phys_addr;
413 
414 	operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
415 						TEEC_MEMREF_TEMP_INPUT,
416 						TEEC_VALUE_INPUT,
417 						TEEC_VALUE_INPUT);
418 
419 	res = TEEC_InvokeCommand(&session, CRYPTO_SERVICE_CMD_OEM_OTP_KEY_PHYS_CIPHER,
420 				 &operation, &error_origin);
421 	if (res != TEEC_SUCCESS) {
422 		E_TRACE("InvokeCommand ERR! TEEC res= 0x%x, error_origin= 0x%x",
423 			res, error_origin);
424 	}
425 
426 	TEEC_CloseSession(&session);
427 
428 out2:
429 	TEEC_FinalizeContext(&contex);
430 
431 out1:
432 	res = tee_to_crypto_code(res);
433 
434 	if (out_fd != in_fd)
435 		rk_crypto_fd_ioctl(RIOCCRYPT_FD_UNMAP, &dst_mop);
436 
437 out:
438 	rk_crypto_fd_ioctl(RIOCCRYPT_FD_UNMAP, &src_mop);
439 
440 	return res;
441 }
442