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