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