1e656c62eSopenharmony_ci/* 2e656c62eSopenharmony_ci * Copyright (C) 2022 Huawei Technologies Co., Ltd. 3e656c62eSopenharmony_ci * Licensed under the Mulan PSL v2. 4e656c62eSopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2. 5e656c62eSopenharmony_ci * You may obtain a copy of Mulan PSL v2 at: 6e656c62eSopenharmony_ci * http://license.coscl.org.cn/MulanPSL2 7e656c62eSopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR 8e656c62eSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR 9e656c62eSopenharmony_ci * PURPOSE. 10e656c62eSopenharmony_ci * See the Mulan PSL v2 for more details. 11e656c62eSopenharmony_ci */ 12e656c62eSopenharmony_ci 13e656c62eSopenharmony_ci#include "secfile_load_agent.h" 14e656c62eSopenharmony_ci#include <limits.h> 15e656c62eSopenharmony_ci#include <securec.h> 16e656c62eSopenharmony_ci#include <sys/prctl.h> 17e656c62eSopenharmony_ci#include "tc_ns_client.h" 18e656c62eSopenharmony_ci#include "tee_log.h" 19e656c62eSopenharmony_ci 20e656c62eSopenharmony_ci#define MAX_PATH_LEN 256 21e656c62eSopenharmony_ci#ifdef LOG_TAG 22e656c62eSopenharmony_ci#undef LOG_TAG 23e656c62eSopenharmony_ci#endif 24e656c62eSopenharmony_ci#define LOG_TAG "teecd_agent" 25e656c62eSopenharmony_ci#define MAX_BUFFER_LEN (8 * 1024 * 1024) 26e656c62eSopenharmony_ci#define H_OFFSET 32 27e656c62eSopenharmony_ciint g_secLoadAgentFd = -1; 28e656c62eSopenharmony_ci 29e656c62eSopenharmony_ciint GetSecLoadAgentFd(void) 30e656c62eSopenharmony_ci{ 31e656c62eSopenharmony_ci return g_secLoadAgentFd; 32e656c62eSopenharmony_ci} 33e656c62eSopenharmony_ci 34e656c62eSopenharmony_civoid SetSecLoadAgentFd(int secLoadAgentFd) 35e656c62eSopenharmony_ci{ 36e656c62eSopenharmony_ci g_secLoadAgentFd = secLoadAgentFd; 37e656c62eSopenharmony_ci} 38e656c62eSopenharmony_ci 39e656c62eSopenharmony_cistatic int GetImgLen(FILE *fp, long *totalLlen) 40e656c62eSopenharmony_ci{ 41e656c62eSopenharmony_ci int ret; 42e656c62eSopenharmony_ci 43e656c62eSopenharmony_ci ret = fseek(fp, 0, SEEK_END); 44e656c62eSopenharmony_ci if (ret != 0) { 45e656c62eSopenharmony_ci tloge("fseek error\n"); 46e656c62eSopenharmony_ci return -1; 47e656c62eSopenharmony_ci } 48e656c62eSopenharmony_ci *totalLlen = ftell(fp); 49e656c62eSopenharmony_ci if (*totalLlen <= 0 || *totalLlen > MAX_BUFFER_LEN) { 50e656c62eSopenharmony_ci tloge("file is not exist or size is too large, filesize = %ld\n", *totalLlen); 51e656c62eSopenharmony_ci return -1; 52e656c62eSopenharmony_ci } 53e656c62eSopenharmony_ci ret = fseek(fp, 0, SEEK_SET); 54e656c62eSopenharmony_ci if (ret != 0) { 55e656c62eSopenharmony_ci tloge("fseek error\n"); 56e656c62eSopenharmony_ci return -1; 57e656c62eSopenharmony_ci } 58e656c62eSopenharmony_ci return ret; 59e656c62eSopenharmony_ci} 60e656c62eSopenharmony_ci 61e656c62eSopenharmony_cistatic int32_t SecFileLoadWork(int tzFd, const char *filePath, enum SecFileType fileType, const TEEC_UUID *uuid) 62e656c62eSopenharmony_ci{ 63e656c62eSopenharmony_ci char realPath[PATH_MAX + 1] = { 0 }; 64e656c62eSopenharmony_ci FILE *fp = NULL; 65e656c62eSopenharmony_ci int ret; 66e656c62eSopenharmony_ci 67e656c62eSopenharmony_ci if (tzFd < 0) { 68e656c62eSopenharmony_ci tloge("fd of tzdriver is valid!\n"); 69e656c62eSopenharmony_ci return -1; 70e656c62eSopenharmony_ci } 71e656c62eSopenharmony_ci if (realpath(filePath, realPath) == NULL) { 72e656c62eSopenharmony_ci tloge("realpath open file err=%d, filePath=%s\n", errno, filePath); 73e656c62eSopenharmony_ci return -1; 74e656c62eSopenharmony_ci } 75e656c62eSopenharmony_ci if (strncmp(realPath, TEE_DEFAULT_PATH, strlen(TEE_DEFAULT_PATH)) != 0) { 76e656c62eSopenharmony_ci tloge("realpath -%s- is invalid\n", realPath); 77e656c62eSopenharmony_ci return -1; 78e656c62eSopenharmony_ci } 79e656c62eSopenharmony_ci fp = fopen(realPath, "r"); 80e656c62eSopenharmony_ci if (fp == NULL) { 81e656c62eSopenharmony_ci tloge("open file err=%d, path=%s\n", errno, filePath); 82e656c62eSopenharmony_ci return -1; 83e656c62eSopenharmony_ci } 84e656c62eSopenharmony_ci ret = LoadSecFile(tzFd, fp, fileType, uuid); 85e656c62eSopenharmony_ci if (fp != NULL) { 86e656c62eSopenharmony_ci fclose(fp); 87e656c62eSopenharmony_ci } 88e656c62eSopenharmony_ci return ret; 89e656c62eSopenharmony_ci} 90e656c62eSopenharmony_ci 91e656c62eSopenharmony_ci// input param uuid may be NULL, so don need to check if uuid is NULL 92e656c62eSopenharmony_ciint32_t LoadSecFile(int tzFd, FILE *fp, enum SecFileType fileType, const TEEC_UUID *uuid) 93e656c62eSopenharmony_ci{ 94e656c62eSopenharmony_ci int32_t ret; 95e656c62eSopenharmony_ci char *fileBuffer = NULL; 96e656c62eSopenharmony_ci struct SecLoadIoctlStruct ioctlArg = {{ 0 }, { 0 }, { NULL } }; 97e656c62eSopenharmony_ci 98e656c62eSopenharmony_ci if (tzFd < 0 || fp == NULL) { 99e656c62eSopenharmony_ci tloge("param erro!\n"); 100e656c62eSopenharmony_ci return -1; 101e656c62eSopenharmony_ci } 102e656c62eSopenharmony_ci 103e656c62eSopenharmony_ci do { 104e656c62eSopenharmony_ci long totalLen = 0; 105e656c62eSopenharmony_ci ret = GetImgLen(fp, &totalLen); 106e656c62eSopenharmony_ci if (ret != 0) { 107e656c62eSopenharmony_ci break; 108e656c62eSopenharmony_ci } 109e656c62eSopenharmony_ci 110e656c62eSopenharmony_ci if (totalLen <= 0 || totalLen > MAX_BUFFER_LEN) { 111e656c62eSopenharmony_ci ret = -1; 112e656c62eSopenharmony_ci tloge("totalLen is invalid\n"); 113e656c62eSopenharmony_ci break; 114e656c62eSopenharmony_ci } 115e656c62eSopenharmony_ci 116e656c62eSopenharmony_ci /* alloc a less than 8M heap memory, it needn't slice. */ 117e656c62eSopenharmony_ci fileBuffer = malloc((size_t)totalLen); 118e656c62eSopenharmony_ci if (fileBuffer == NULL) { 119e656c62eSopenharmony_ci tloge("alloc TA file buffer(size=%ld) failed\n", totalLen); 120e656c62eSopenharmony_ci ret = -1; 121e656c62eSopenharmony_ci break; 122e656c62eSopenharmony_ci } 123e656c62eSopenharmony_ci 124e656c62eSopenharmony_ci /* read total ta file to file buffer */ 125e656c62eSopenharmony_ci long fileSize = (long)fread(fileBuffer, 1, totalLen, fp); 126e656c62eSopenharmony_ci if (fileSize != totalLen) { 127e656c62eSopenharmony_ci tloge("read ta file failed, read size/total size=%ld/%ld\n", fileSize, totalLen); 128e656c62eSopenharmony_ci ret = -1; 129e656c62eSopenharmony_ci break; 130e656c62eSopenharmony_ci } 131e656c62eSopenharmony_ci 132e656c62eSopenharmony_ci ioctlArg.secFileInfo.fileType = fileType; 133e656c62eSopenharmony_ci ioctlArg.secFileInfo.fileSize = (uint32_t)totalLen; 134e656c62eSopenharmony_ci ioctlArg.memref.file_addr = (uint32_t)(uintptr_t)fileBuffer; 135e656c62eSopenharmony_ci ioctlArg.memref.file_h_addr = (uint32_t)(((uint64_t)(uintptr_t)fileBuffer) >> H_OFFSET); 136e656c62eSopenharmony_ci if (uuid != NULL && memcpy_s((void *)(&ioctlArg.uuid), sizeof(ioctlArg.uuid), uuid, sizeof(*uuid)) != EOK) { 137e656c62eSopenharmony_ci tloge("memcpy uuid fail\n"); 138e656c62eSopenharmony_ci break; 139e656c62eSopenharmony_ci } 140e656c62eSopenharmony_ci 141e656c62eSopenharmony_ci ret = ioctl(tzFd, (int)TC_NS_CLIENT_IOCTL_LOAD_APP_REQ, &ioctlArg); 142e656c62eSopenharmony_ci if (ret != 0) { 143e656c62eSopenharmony_ci tloge("ioctl to load sec file failed, ret = 0x%x\n", ret); 144e656c62eSopenharmony_ci } 145e656c62eSopenharmony_ci } while (false); 146e656c62eSopenharmony_ci 147e656c62eSopenharmony_ci if (fileBuffer != NULL) { 148e656c62eSopenharmony_ci free(fileBuffer); 149e656c62eSopenharmony_ci } 150e656c62eSopenharmony_ci return ret; 151e656c62eSopenharmony_ci} 152e656c62eSopenharmony_ci 153e656c62eSopenharmony_cistatic bool IsTaLib(const TEEC_UUID *uuid) 154e656c62eSopenharmony_ci{ 155e656c62eSopenharmony_ci char *chr = (char *)uuid; 156e656c62eSopenharmony_ci uint32_t i; 157e656c62eSopenharmony_ci 158e656c62eSopenharmony_ci for (i = 0; i < sizeof(*uuid); i++) { 159e656c62eSopenharmony_ci if (chr[i] != 0) { 160e656c62eSopenharmony_ci return true; 161e656c62eSopenharmony_ci } 162e656c62eSopenharmony_ci } 163e656c62eSopenharmony_ci return false; 164e656c62eSopenharmony_ci} 165e656c62eSopenharmony_ci 166e656c62eSopenharmony_cistatic void LoadLib(struct SecAgentControlType *secAgentControl) 167e656c62eSopenharmony_ci{ 168e656c62eSopenharmony_ci int32_t ret; 169e656c62eSopenharmony_ci char fname[MAX_PATH_LEN] = { 0 }; 170e656c62eSopenharmony_ci 171e656c62eSopenharmony_ci if (secAgentControl == NULL) { 172e656c62eSopenharmony_ci tloge("secAgentControl is null\n"); 173e656c62eSopenharmony_ci return; 174e656c62eSopenharmony_ci } 175e656c62eSopenharmony_ci if (strnlen(secAgentControl->LibSec.libName, MAX_SEC_FILE_NAME_LEN) >= MAX_SEC_FILE_NAME_LEN) { 176e656c62eSopenharmony_ci tloge("libName is too long!\n"); 177e656c62eSopenharmony_ci secAgentControl->ret = -1; 178e656c62eSopenharmony_ci return; 179e656c62eSopenharmony_ci } 180e656c62eSopenharmony_ci 181e656c62eSopenharmony_ci if (IsTaLib(&(secAgentControl->LibSec.uuid))) { 182e656c62eSopenharmony_ci ret = 183e656c62eSopenharmony_ci snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1, 184e656c62eSopenharmony_ci "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s.sec", 185e656c62eSopenharmony_ci TEE_DEFAULT_PATH, secAgentControl->LibSec.uuid.timeLow, secAgentControl->LibSec.uuid.timeMid, 186e656c62eSopenharmony_ci secAgentControl->LibSec.uuid.timeHiAndVersion, secAgentControl->LibSec.uuid.clockSeqAndNode[0], 187e656c62eSopenharmony_ci secAgentControl->LibSec.uuid.clockSeqAndNode[1], secAgentControl->LibSec.uuid.clockSeqAndNode[2], 188e656c62eSopenharmony_ci secAgentControl->LibSec.uuid.clockSeqAndNode[3], secAgentControl->LibSec.uuid.clockSeqAndNode[4], 189e656c62eSopenharmony_ci secAgentControl->LibSec.uuid.clockSeqAndNode[5], secAgentControl->LibSec.uuid.clockSeqAndNode[6], 190e656c62eSopenharmony_ci secAgentControl->LibSec.uuid.clockSeqAndNode[7], secAgentControl->LibSec.libName); 191e656c62eSopenharmony_ci } else { 192e656c62eSopenharmony_ci ret = snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1, 193e656c62eSopenharmony_ci "%s/%s.sec", TEE_DEFAULT_PATH, secAgentControl->LibSec.libName); 194e656c62eSopenharmony_ci } 195e656c62eSopenharmony_ci if (ret < 0) { 196e656c62eSopenharmony_ci tloge("pack fname err\n"); 197e656c62eSopenharmony_ci secAgentControl->ret = -1; 198e656c62eSopenharmony_ci return; 199e656c62eSopenharmony_ci } 200e656c62eSopenharmony_ci ret = SecFileLoadWork(g_secLoadAgentFd, (const char *)fname, LOAD_LIB, NULL); 201e656c62eSopenharmony_ci if (ret != 0) { 202e656c62eSopenharmony_ci tloge("teec load app failed\n"); 203e656c62eSopenharmony_ci secAgentControl->ret = -1; 204e656c62eSopenharmony_ci secAgentControl->error = errno; 205e656c62eSopenharmony_ci return; 206e656c62eSopenharmony_ci } 207e656c62eSopenharmony_ci secAgentControl->ret = 0; 208e656c62eSopenharmony_ci return; 209e656c62eSopenharmony_ci} 210e656c62eSopenharmony_ci 211e656c62eSopenharmony_cistatic void LoadTa(struct SecAgentControlType *secAgentControl) 212e656c62eSopenharmony_ci{ 213e656c62eSopenharmony_ci int32_t ret; 214e656c62eSopenharmony_ci char fname[MAX_PATH_LEN] = { 0 }; 215e656c62eSopenharmony_ci 216e656c62eSopenharmony_ci if (secAgentControl == NULL) { 217e656c62eSopenharmony_ci tloge("secAgentControl is null\n"); 218e656c62eSopenharmony_ci return; 219e656c62eSopenharmony_ci } 220e656c62eSopenharmony_ci 221e656c62eSopenharmony_ci ret = snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1, "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x.sec", 222e656c62eSopenharmony_ci TEE_DEFAULT_PATH, secAgentControl->TaSec.uuid.timeLow, secAgentControl->TaSec.uuid.timeMid, 223e656c62eSopenharmony_ci secAgentControl->TaSec.uuid.timeHiAndVersion, secAgentControl->TaSec.uuid.clockSeqAndNode[0], 224e656c62eSopenharmony_ci secAgentControl->TaSec.uuid.clockSeqAndNode[1], secAgentControl->TaSec.uuid.clockSeqAndNode[2], 225e656c62eSopenharmony_ci secAgentControl->TaSec.uuid.clockSeqAndNode[3], secAgentControl->TaSec.uuid.clockSeqAndNode[4], 226e656c62eSopenharmony_ci secAgentControl->TaSec.uuid.clockSeqAndNode[5], secAgentControl->TaSec.uuid.clockSeqAndNode[6], 227e656c62eSopenharmony_ci secAgentControl->TaSec.uuid.clockSeqAndNode[7]); 228e656c62eSopenharmony_ci if (ret < 0) { 229e656c62eSopenharmony_ci tloge("pack fname err\n"); 230e656c62eSopenharmony_ci secAgentControl->ret = -1; 231e656c62eSopenharmony_ci return; 232e656c62eSopenharmony_ci } 233e656c62eSopenharmony_ci secAgentControl->ret = 0; 234e656c62eSopenharmony_ci ret = SecFileLoadWork(g_secLoadAgentFd, (const char *)fname, LOAD_TA, &(secAgentControl->TaSec.uuid)); 235e656c62eSopenharmony_ci if (ret != 0) { 236e656c62eSopenharmony_ci tloge("teec load TA app failed\n"); 237e656c62eSopenharmony_ci secAgentControl->ret = ret; 238e656c62eSopenharmony_ci secAgentControl->error = errno; 239e656c62eSopenharmony_ci return; 240e656c62eSopenharmony_ci } 241e656c62eSopenharmony_ci return; 242e656c62eSopenharmony_ci} 243e656c62eSopenharmony_ci 244e656c62eSopenharmony_cistatic void SecLoadAgentWork(struct SecAgentControlType *secAgentControl) 245e656c62eSopenharmony_ci{ 246e656c62eSopenharmony_ci if (secAgentControl == NULL) { 247e656c62eSopenharmony_ci tloge("secAgentControl is null\n"); 248e656c62eSopenharmony_ci return; 249e656c62eSopenharmony_ci } 250e656c62eSopenharmony_ci switch (secAgentControl->cmd) { 251e656c62eSopenharmony_ci case LOAD_LIB_SEC: 252e656c62eSopenharmony_ci LoadLib(secAgentControl); 253e656c62eSopenharmony_ci break; 254e656c62eSopenharmony_ci case LOAD_TA_SEC: 255e656c62eSopenharmony_ci LoadTa(secAgentControl); 256e656c62eSopenharmony_ci break; 257e656c62eSopenharmony_ci case LOAD_SERVICE_SEC: 258e656c62eSopenharmony_ci default: 259e656c62eSopenharmony_ci tloge("gtask agent error cmd:%d\n", secAgentControl->cmd); 260e656c62eSopenharmony_ci secAgentControl->ret = -1; 261e656c62eSopenharmony_ci break; 262e656c62eSopenharmony_ci } 263e656c62eSopenharmony_ci} 264e656c62eSopenharmony_ci 265e656c62eSopenharmony_civoid *SecfileLoadAgentThread(void *control) 266e656c62eSopenharmony_ci{ 267e656c62eSopenharmony_ci (void)prctl(PR_SET_NAME, "teecd_sec_load_agent", 0, 0, 0); 268e656c62eSopenharmony_ci struct SecAgentControlType *secAgentControl = NULL; 269e656c62eSopenharmony_ci if (control == NULL) { 270e656c62eSopenharmony_ci tloge("control is NULL\n"); 271e656c62eSopenharmony_ci return NULL; 272e656c62eSopenharmony_ci } 273e656c62eSopenharmony_ci secAgentControl = (struct SecAgentControlType *)control; 274e656c62eSopenharmony_ci if (g_secLoadAgentFd < 0) { 275e656c62eSopenharmony_ci tloge("m_gtask_agent_fd is -1\n"); 276e656c62eSopenharmony_ci return NULL; 277e656c62eSopenharmony_ci } 278e656c62eSopenharmony_ci secAgentControl->magic = SECFILE_LOAD_AGENT_ID; 279e656c62eSopenharmony_ci while (true) { 280e656c62eSopenharmony_ci int ret = ioctl(g_secLoadAgentFd, (int)TC_NS_CLIENT_IOCTL_WAIT_EVENT, SECFILE_LOAD_AGENT_ID); 281e656c62eSopenharmony_ci if (ret) { 282e656c62eSopenharmony_ci tloge("gtask agent wait event failed, errno = %d\n", errno); 283e656c62eSopenharmony_ci break; 284e656c62eSopenharmony_ci } 285e656c62eSopenharmony_ci SecLoadAgentWork(secAgentControl); 286e656c62eSopenharmony_ci 287e656c62eSopenharmony_ci __asm__ volatile("isb"); 288e656c62eSopenharmony_ci __asm__ volatile("dsb sy"); 289e656c62eSopenharmony_ci 290e656c62eSopenharmony_ci secAgentControl->magic = SECFILE_LOAD_AGENT_ID; 291e656c62eSopenharmony_ci 292e656c62eSopenharmony_ci __asm__ volatile("isb"); 293e656c62eSopenharmony_ci __asm__ volatile("dsb sy"); 294e656c62eSopenharmony_ci ret = ioctl(g_secLoadAgentFd, (int)TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, SECFILE_LOAD_AGENT_ID); 295e656c62eSopenharmony_ci if (ret) { 296e656c62eSopenharmony_ci tloge("gtask agent send reponse failed\n"); 297e656c62eSopenharmony_ci break; 298e656c62eSopenharmony_ci } 299e656c62eSopenharmony_ci } 300e656c62eSopenharmony_ci return NULL; 301e656c62eSopenharmony_ci} 302