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 <write_keybox.h> 11 #include <keymaster.h> 12 #include <optee_include/OpteeClientApiLib.h> 13 #include <optee_include/tee_client_api.h> 14 #include <optee_include/tee_api_defines.h> 15 16 #define STORAGE_CMD_WRITE 6 17 #define SIZE_OF_TAG 4 18 #define BOOT_FROM_EMMC (1 << 1) 19 #define WIDEVINE_TAG "KBOX" 20 #define ATTESTATION_TAG "ATTE" 21 #define PLAYREADY30_TAG "SL30" 22 23 TEEC_Result write_to_security_storage(uint8_t is_use_rpmb, 24 uint8_t *filename, 25 uint32_t filename_size, 26 uint8_t *data, 27 uint32_t data_size) 28 { 29 TEEC_Result TeecResult; 30 TEEC_Context TeecContext; 31 TEEC_Session TeecSession; 32 TEEC_SharedMemory SharedMem0 = {0}; 33 TEEC_SharedMemory SharedMem1 = {0}; 34 uint32_t ErrorOrigin; 35 36 TEEC_UUID tempuuid = { 0x1b484ea5, 37 0x698b, 38 0x4142, 39 { 0x82, 0xb8, 0x3a, 40 0xcf, 0x16, 0xe9, 41 0x9e, 0x2a } }; 42 43 TEEC_UUID *TeecUuid = &tempuuid; 44 TEEC_Operation TeecOperation = {0}; 45 46 TeecResult = OpteeClientApiLibInitialize(); 47 if (TeecResult) { 48 printf("OpteeClientApiLibInitialize fail\n"); 49 return TeecResult; 50 } 51 TeecResult = TEEC_InitializeContext(NULL, &TeecContext); 52 if (TeecResult) { 53 printf("TEEC_InitializeContext fail\n"); 54 return TeecResult; 55 } 56 TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, 57 TEEC_NONE, 58 TEEC_NONE, 59 TEEC_NONE); 60 61 /*0 nand or emmc "security" partition , 1 rpmb*/ 62 TeecOperation.params[0].value.a = is_use_rpmb; 63 64 TeecResult = TEEC_OpenSession(&TeecContext, 65 &TeecSession, 66 TeecUuid, 67 TEEC_LOGIN_PUBLIC, 68 NULL, &TeecOperation, 69 &ErrorOrigin); 70 if (TeecResult) { 71 printf("TEEC_OpenSession fail\n"); 72 return TeecResult; 73 } 74 75 SharedMem0.size = filename_size; 76 SharedMem0.flags = 0; 77 TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem0); 78 if (TeecResult) { 79 printf("TEEC_AllocateSharedMemory fail\n"); 80 return TeecResult; 81 } 82 memcpy(SharedMem0.buffer, filename, SharedMem0.size); 83 84 SharedMem1.size = data_size; 85 SharedMem1.flags = 0; 86 TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem1); 87 if (TeecResult) { 88 printf("TEEC_AllocateSharedMemory fail\n"); 89 return TeecResult; 90 } 91 memcpy(SharedMem1.buffer, data, SharedMem1.size); 92 93 TeecOperation.params[0].tmpref.buffer = SharedMem0.buffer; 94 TeecOperation.params[0].tmpref.size = SharedMem0.size; 95 96 TeecOperation.params[1].tmpref.buffer = SharedMem1.buffer; 97 TeecOperation.params[1].tmpref.size = SharedMem1.size; 98 99 TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, 100 TEEC_MEMREF_TEMP_INOUT, 101 TEEC_NONE, 102 TEEC_NONE); 103 104 TeecResult = TEEC_InvokeCommand(&TeecSession, 105 1, 106 &TeecOperation, 107 &ErrorOrigin); 108 if (TeecResult) { 109 printf("TEEC_InvokeCommand fail\n"); 110 return TeecResult; 111 } 112 TEEC_ReleaseSharedMemory(&SharedMem0); 113 TEEC_ReleaseSharedMemory(&SharedMem1); 114 TEEC_CloseSession(&TeecSession); 115 TEEC_FinalizeContext(&TeecContext); 116 debug("TeecResult %x\n", TeecResult); 117 118 return TeecResult; 119 } 120 121 uint32_t rk_send_keybox_to_ta(uint8_t *filename, uint32_t filename_size, 122 TEEC_UUID uuid, 123 uint8_t *key, uint32_t key_size, 124 uint8_t *data, uint32_t data_size) 125 { 126 uint32_t ErrorOrigin; 127 TEEC_Result TeecResult; 128 TEEC_Context TeecContext; 129 TEEC_Session TeecSession; 130 TEEC_UUID *TeecUuid = &uuid; 131 TEEC_Operation TeecOperation = {0}; 132 TEEC_SharedMemory SharedMem0 = {0}; 133 TEEC_SharedMemory SharedMem1 = {0}; 134 TEEC_SharedMemory SharedMem2 = {0}; 135 struct blk_desc *dev_desc; 136 137 dev_desc = rockchip_get_bootdev(); 138 if (!dev_desc) { 139 printf("%s: dev_desc is NULL!\n", __func__); 140 return -TEEC_ERROR_GENERIC; 141 } 142 143 TeecResult = OpteeClientApiLibInitialize(); 144 if (TeecResult != TEEC_SUCCESS) 145 return TeecResult; 146 TeecResult = TEEC_InitializeContext(NULL, &TeecContext); 147 if (TeecResult != TEEC_SUCCESS) 148 return TeecResult; 149 TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, 150 TEEC_NONE, 151 TEEC_NONE, 152 TEEC_NONE); 153 154 /* 0 nand or emmc "security" partition , 1 rpmb */ 155 TeecOperation.params[0].value.a = 156 (dev_desc->if_type == IF_TYPE_MMC) ? 1 : 0; 157 #ifdef CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION 158 TeecOperation.params[0].value.a = 0; 159 #endif 160 TeecResult = TEEC_OpenSession(&TeecContext, 161 &TeecSession, 162 TeecUuid, 163 TEEC_LOGIN_PUBLIC, 164 NULL, 165 &TeecOperation, 166 &ErrorOrigin); 167 if (TeecResult != TEEC_SUCCESS) 168 return TeecResult; 169 170 SharedMem0.size = filename_size; 171 SharedMem0.flags = 0; 172 TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem0); 173 if (TeecResult != TEEC_SUCCESS) 174 return TeecResult; 175 memcpy(SharedMem0.buffer, filename, SharedMem0.size); 176 177 SharedMem1.size = key_size; 178 SharedMem1.flags = 0; 179 TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem1); 180 if (TeecResult != TEEC_SUCCESS) 181 return TeecResult; 182 memcpy(SharedMem1.buffer, key, SharedMem1.size); 183 184 SharedMem2.size = data_size; 185 SharedMem2.flags = 0; 186 TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem2); 187 if (TeecResult != TEEC_SUCCESS) 188 return TeecResult; 189 memcpy(SharedMem2.buffer, data, SharedMem2.size); 190 191 TeecOperation.params[0].tmpref.buffer = SharedMem0.buffer; 192 TeecOperation.params[0].tmpref.size = SharedMem0.size; 193 TeecOperation.params[1].tmpref.buffer = SharedMem1.buffer; 194 TeecOperation.params[1].tmpref.size = SharedMem1.size; 195 TeecOperation.params[2].tmpref.buffer = SharedMem2.buffer; 196 TeecOperation.params[2].tmpref.size = SharedMem2.size; 197 198 TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, 199 TEEC_MEMREF_TEMP_INPUT, 200 TEEC_MEMREF_TEMP_INOUT, 201 TEEC_NONE); 202 203 printf("write keybox to secure storage\n"); 204 TeecResult = TEEC_InvokeCommand(&TeecSession, 205 STORAGE_CMD_WRITE, 206 &TeecOperation, 207 &ErrorOrigin); 208 if (TeecResult != TEEC_SUCCESS) 209 printf("send data to TA failed with code 0x%x\n", TeecResult); 210 else 211 printf("send data to TA success with code 0x%x\n", TeecResult); 212 213 TEEC_ReleaseSharedMemory(&SharedMem0); 214 TEEC_ReleaseSharedMemory(&SharedMem1); 215 TEEC_ReleaseSharedMemory(&SharedMem2); 216 217 TEEC_CloseSession(&TeecSession); 218 TEEC_FinalizeContext(&TeecContext); 219 220 return TeecResult; 221 } 222 223 uint32_t write_keybox_to_secure_storage(uint8_t *received_data, uint32_t len) 224 { 225 uint8_t *widevine_data; 226 uint8_t *attestation_data; 227 uint8_t *playready_sl30_data; 228 uint32_t key_size; 229 uint32_t data_size; 230 int rc = 0; 231 TEEC_Result ret; 232 struct blk_desc *dev_desc; 233 uint8_t is_use_rpmb; 234 235 dev_desc = rockchip_get_bootdev(); 236 if (!dev_desc) { 237 printf("%s: dev_desc is NULL!\n", __func__); 238 return -EIO; 239 } 240 is_use_rpmb = (dev_desc->if_type == IF_TYPE_MMC) ? 1 : 0; 241 #ifdef CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION 242 is_use_rpmb = 0; 243 #endif 244 if (is_use_rpmb) 245 printf("I will write key to rpmb\n"); 246 else 247 printf("I will write key to security partition\n"); 248 249 rc = write_to_security_storage(0, (uint8_t *)"security_partition", 250 sizeof("security_partition"), 251 &is_use_rpmb, sizeof(is_use_rpmb)); 252 if (rc) 253 return -EIO; 254 widevine_data = (uint8_t *)new_strstr((char *)received_data, 255 WIDEVINE_TAG, len); 256 attestation_data = (uint8_t *)new_strstr((char *)received_data, 257 ATTESTATION_TAG, len); 258 playready_sl30_data = (uint8_t *)new_strstr((char *)received_data, 259 PLAYREADY30_TAG, len); 260 if (widevine_data) { 261 /* widevine keybox */ 262 TEEC_UUID widevine_uuid = { 0x1b484ea5, 0x698b, 0x4142, 263 { 0x82, 0xb8, 0x3a, 0xcf, 0x16, 0xe9, 0x9e, 0x2a } }; 264 265 key_size = *(widevine_data + SIZE_OF_TAG); 266 data_size = *(widevine_data + SIZE_OF_TAG + sizeof(key_size)); 267 268 ret = rk_send_keybox_to_ta((uint8_t *)"widevine_keybox", 269 sizeof("widevine_keybox"), 270 widevine_uuid, 271 widevine_data + SIZE_OF_TAG + 272 sizeof(key_size) + sizeof(data_size), 273 key_size, 274 widevine_data + 12 + key_size, 275 data_size); 276 if (ret == TEEC_SUCCESS) { 277 rc = 0; 278 printf("write widevine keybox to secure storage success\n"); 279 } else { 280 rc = -EIO; 281 printf("write widevine keybox to secure storage fail\n"); 282 } 283 } else if (attestation_data) { 284 /* attestation key */ 285 atap_result ret; 286 287 ret = write_attestation_key_to_secure_storage(attestation_data, 288 len); 289 if (ret == ATAP_RESULT_OK) { 290 rc = 0; 291 printf("write attestation key to secure storage success\n"); 292 } else { 293 rc = -EIO; 294 printf("write attestation key to secure storage fail\n"); 295 } 296 } else if (playready_sl30_data) { 297 /* PlayReady SL3000 root key */ 298 uint32_t ret; 299 300 data_size = *(playready_sl30_data + SIZE_OF_TAG); 301 ret = write_to_security_storage(is_use_rpmb, 302 (uint8_t *)"PlayReady_SL3000", 303 sizeof("PlayReady_SL3000"), 304 playready_sl30_data + 305 SIZE_OF_TAG +sizeof(data_size), 306 data_size); 307 if (ret == TEEC_SUCCESS) { 308 rc = 0; 309 printf("write PlayReady SL3000 root key to secure storage success\n"); 310 } else { 311 rc = -EIO; 312 printf("write PlayReady SL3000 root key to secure storage fail\n"); 313 } 314 } 315 316 /* write all data to secure storage for readback check */ 317 if (!rc) { 318 uint32_t ret; 319 uint8_t *raw_data = malloc(len + sizeof(uint32_t)); 320 321 /* add raw_data_len(4 byte) in begin of raw_data */ 322 memcpy(raw_data, &len, sizeof(uint32_t)); 323 memcpy((raw_data + sizeof(uint32_t)), received_data, len); 324 325 ret = write_to_security_storage(is_use_rpmb, 326 (uint8_t *)"raw_data", 327 sizeof("raw_data"), 328 raw_data, 329 len + sizeof(uint32_t)); 330 if (ret == TEEC_SUCCESS) 331 rc = 0; 332 else 333 rc = -EIO; 334 free(raw_data); 335 } 336 return rc; 337 } 338 339 uint32_t read_raw_data_from_secure_storage(uint8_t *data, uint32_t data_size) 340 { 341 uint32_t rc; 342 uint32_t key_size; 343 uint8_t *read_data = malloc(1024 * 40); 344 345 rc = read_from_keymaster((uint8_t *)"raw_data", sizeof("raw_data"), 346 read_data, data_size); 347 if (rc != TEEC_SUCCESS) 348 return 0; 349 350 memcpy(&key_size, read_data, sizeof(uint32_t)); 351 memcpy(data, read_data + sizeof(uint32_t), key_size); 352 rc = key_size; 353 free(read_data); 354 355 return rc; 356 } 357 358 char *new_strstr(const char *s1, const char *s2, uint32_t l1) 359 { 360 uint32_t l2; 361 362 l2 = strlen(s2); 363 if (!l2) 364 return (char *)s1; 365 while (l1 >= l2) { 366 l1--; 367 if (!memcmp(s1, s2, l2)) 368 return (char *)s1; 369 s1++; 370 } 371 return NULL; 372 } 373