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