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