You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1973 lines
68 KiB
1973 lines
68 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
* Description: hidl for tee
|
|
* Author: NameMagic
|
|
* Create: 2018-03-10
|
|
*/
|
|
|
|
#define LOG_TAG "LibteecGlobal@3.0"
|
|
|
|
#include "LibteecGlobal.h"
|
|
#include <cstring>
|
|
#include <cerrno>
|
|
#include <csignal>
|
|
#include <pthread.h>
|
|
#include <time.h>
|
|
|
|
#include <log/log.h>
|
|
#include <cutils/list.h>
|
|
#include <sys/types.h>
|
|
#include <sys/syscall.h>
|
|
#include <securec.h>
|
|
|
|
#include "tee_client_api.h"
|
|
#include "tc_ns_client.h"
|
|
#include "tee_ca_daemon.h"
|
|
#include "tee_client_msg.h"
|
|
|
|
using android::hidl::memory::V1_0::IMemory;
|
|
extern "C" int getpidcon(pid_t pid, char **context);
|
|
extern "C" void freecon(char *con);
|
|
|
|
namespace vendor {
|
|
namespace huanglong {
|
|
namespace hardware {
|
|
namespace libteec {
|
|
namespace V3_0 {
|
|
namespace implementation {
|
|
using::android::hardware::Void;
|
|
|
|
#if defined(__LP64__)
|
|
const static char * const DLOPEN_LIBTEEC_PATH = "/vendor/lib64/libteec_vendor.so";
|
|
#else
|
|
const static char * const DLOPEN_LIBTEEC_PATH = "/vendor/lib/libteec_vendor.so";
|
|
#endif
|
|
|
|
const static int DIR_NAME_LENS = 64;
|
|
|
|
/* DeathNote */
|
|
static list_declare(g_teecHidlProcDataList);
|
|
static list_declare(g_teecTidList);
|
|
static pthread_mutex_t g_mutexTidList = PTHREAD_MUTEX_INITIALIZER;
|
|
static sp<ILibteecGlobalNotify> g_teecNotify;
|
|
|
|
static int32_t TidMutexLock(void)
|
|
{
|
|
int lockRet = pthread_mutex_lock(&g_mutexTidList);
|
|
return lockRet;
|
|
}
|
|
|
|
static void TidMutexUnlock(int lockRet)
|
|
{
|
|
int unlockRet;
|
|
if (lockRet != 0) {
|
|
ALOGE("%s: not exe, mutex not in lock state. lock_ret = %d\n", __func__, lockRet);
|
|
return;
|
|
}
|
|
unlockRet = pthread_mutex_unlock(&g_mutexTidList);
|
|
if (unlockRet != 0) {
|
|
ALOGE("%s: exe mutexUnlock error, ret = %d\n", __func__, unlockRet);
|
|
}
|
|
}
|
|
|
|
static DaemonProcdata *GetProcdataByPid(int pid)
|
|
{
|
|
/* found server procdata */
|
|
DaemonProcdata *procDataInList = nullptr;
|
|
struct listnode *ptr = nullptr;
|
|
|
|
/* Paramters right, start execution */
|
|
if (!list_empty(&g_teecHidlProcDataList)) {
|
|
list_for_each(ptr, &g_teecHidlProcDataList) {
|
|
DaemonProcdata *tmp = node_to_item(ptr, DaemonProcdata, procdataHead);
|
|
if (tmp->callingPid == pid) {
|
|
procDataInList = tmp;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return procDataInList;
|
|
}
|
|
|
|
static bool CheckProcDataFdFull(DaemonProcdata *procData)
|
|
{
|
|
int i;
|
|
DaemonProcdata *tmpProcData = procData;
|
|
for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
if (tmpProcData->cxtFd[i] == -1) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool CheckProcDataFdEmpty(DaemonProcdata *procData)
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
if (procData->cxtFd[i] != -1) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static TEEC_Result SetContextToProcData(DaemonProcdata *outProcData, TEEC_ContextHidl *outContext)
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
if (outProcData->cxtFd[i] == -1) {
|
|
outProcData->cxtFd[i] = outContext->fd;
|
|
return TEEC_SUCCESS;
|
|
}
|
|
}
|
|
ALOGE("%s: the cnt of contexts in outProcData is already %d, please finalize some of them\n", __func__, i);
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
static void RemoveContextFromProcData(DaemonProcdata *outProcData, int32_t outContextFd)
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
if (outContextFd == outProcData->cxtFd[i]) {
|
|
outProcData->cxtFd[i] = -1;
|
|
return;
|
|
}
|
|
}
|
|
ALOGE("%s: can not find context in outProcdata\n", __func__);
|
|
}
|
|
|
|
/* just mkdir sec_storage_data, mount sec_storage partition in init.chip.rc */
|
|
static int MakeSecStorageDir(const char *storageDir, int strSize)
|
|
{
|
|
struct stat statBuf;
|
|
int ret;
|
|
|
|
if (strSize < 0) {
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
/* mkdir for sec_storage_data partition */
|
|
if (stat(storageDir, &statBuf)) {
|
|
ALOGE("stat fail, erron=%d\n", errno);
|
|
|
|
if (errno == ENOENT) { /* folder not exist */
|
|
ALOGE("stat folder not exist\n");
|
|
ret = mkdir(storageDir, S_IRUSR | S_IWUSR | S_IXUSR);
|
|
if (ret == -1) {
|
|
ALOGE("make dir fail, err %d\n", errno);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
ret = chown(storageDir, AID_SYSTEM, AID_SYSTEM);
|
|
if (ret < 0) {
|
|
ALOGE("chown error");
|
|
}
|
|
} else {
|
|
ALOGE("stat fail else\n");
|
|
|
|
if (S_ISDIR(statBuf.st_mode)) {
|
|
ALOGE("ROOT DATA DIR is exist, but not a dir\n");
|
|
/* shell we rm it and mkdir? */
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
/* symlink user0 when teecd init */
|
|
static void SymlinkUser0(const char *oldPath, const char *newPath)
|
|
{
|
|
int ret;
|
|
int retChMod;
|
|
int retChOwn;
|
|
|
|
ret = symlink(oldPath, newPath);
|
|
if (ret < 0) {
|
|
ALOGE("symlink user0 erro, errno=%d\n", errno);
|
|
return;
|
|
}
|
|
retChMod = chmod(newPath, S_IRUSR | S_IWUSR | S_IXUSR);
|
|
retChOwn = chown(newPath, AID_SYSTEM, AID_SYSTEM);
|
|
int tmpCheckStatus = ((retChMod < 0) || (retChOwn < 0));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("chmod error %d, or chown error %d", retChMod, retChOwn);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* return 0 when open dir success, others failure */
|
|
static int CheckStatAndOpenDir(const char *name)
|
|
{
|
|
struct stat st;
|
|
/* is it a file or directory? */
|
|
if (lstat(name, &st) < 0) {
|
|
ALOGE("lstat %s failed, errno is %x\n", name, errno);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
/* a file, so unlink it */
|
|
if (S_ISDIR(st.st_mode) != 1) {
|
|
if (unlink(name) != 0) {
|
|
ALOGE("unlink failed, errno is %d\n", errno);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
static int ClearOpenStat(const char *name, DIR *dir)
|
|
{
|
|
/* close directory handle */
|
|
if (closedir(dir) < 0) {
|
|
ALOGE("closedir %s failed, errno is %d\n", name, errno);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
/* delete target directory */
|
|
if (rmdir(name) < 0) { /* no perto handle other dirs */
|
|
ALOGE("rmdir %s failed, errno is %d\n", name, errno);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
/* return -1 on failure, with errno set to the first error */
|
|
static int UnlinkRecursive(const char *name)
|
|
{
|
|
DIR *dir = nullptr;
|
|
struct dirent *de = nullptr;
|
|
int fail = 0;
|
|
char dn[PATH_MAX] = {0};
|
|
errno_t rc = EOK;
|
|
int32_t ret;
|
|
int32_t tmpCheckStatus;
|
|
|
|
ret = CheckStatAndOpenDir(name);
|
|
if (ret != TEE_HIDL_SUCCESS) {
|
|
return ret;
|
|
}
|
|
/* a directory, so open handle */
|
|
dir = opendir(name); /* teecd has no permission to handle other directorys */
|
|
if (dir == nullptr) {
|
|
ALOGE("dir %s open failed\n", name);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
/* recurse over components */
|
|
errno = 0;
|
|
|
|
de = readdir(dir);
|
|
while (de != nullptr) {
|
|
tmpCheckStatus = ((!strncmp(de->d_name, "..", sizeof(".."))) || (!strncmp(de->d_name, ".", sizeof("."))));
|
|
if (tmpCheckStatus) {
|
|
de = readdir(dir);
|
|
continue;
|
|
}
|
|
|
|
rc = snprintf_s(dn, sizeof(dn), sizeof(dn) - 1, "%s/%s", name, de->d_name);
|
|
if (rc == -1) {
|
|
ALOGE("snprintf_s failed %d\n", rc);
|
|
fail = 1;
|
|
break;
|
|
}
|
|
|
|
if (UnlinkRecursive(dn) < 0) { /* no per to handle other dirs */
|
|
ALOGE("loop UnlinkRecursive() failed, there are read-only file\n");
|
|
fail = 1;
|
|
break;
|
|
}
|
|
|
|
errno = 0;
|
|
de = readdir(dir);
|
|
}
|
|
|
|
/* in case readdir or UnlinkRecursive failed */
|
|
tmpCheckStatus = (fail || errno < 0);
|
|
if (tmpCheckStatus) {
|
|
int save = errno;
|
|
closedir(dir);
|
|
errno = save;
|
|
ALOGE("fail is %d, errno is %d\n", fail, errno);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
return ClearOpenStat(name, dir);
|
|
}
|
|
|
|
static void SigUsr1Handler(int sign)
|
|
{
|
|
sign = 0;
|
|
return;
|
|
}
|
|
|
|
static void RemoveTidFromList(TidData *tidData)
|
|
{
|
|
int retMutexLock = TidMutexLock();
|
|
if (retMutexLock)
|
|
ALOGE("tid mutex lock failed\n");
|
|
|
|
list_remove(&tidData->tidHead);
|
|
TidMutexUnlock(retMutexLock);
|
|
free(tidData);
|
|
return;
|
|
}
|
|
|
|
static int AddTidData(TidData **tidData, int pid)
|
|
{
|
|
int ret = TEE_HIDL_SUCCESS;
|
|
int mutexRet;
|
|
|
|
*tidData = reinterpret_cast<TidData *>(malloc(sizeof(TidData)));
|
|
if (*tidData == nullptr) {
|
|
ALOGE("%s: tid_data malloc failed\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
(*tidData)->tid = syscall(SYS_gettid);
|
|
(*tidData)->callingPid = pid;
|
|
list_init(&(*tidData)->tidHead);
|
|
|
|
mutexRet = TidMutexLock();
|
|
if (mutexRet) {
|
|
ALOGE("tid mutex lock failed\n");
|
|
free(*tidData);
|
|
*tidData = nullptr;
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
list_add_tail(&g_teecTidList, &(*tidData)->tidHead);
|
|
TidMutexUnlock(mutexRet);
|
|
ALOGD("%s: tid %d is sending command to TEE\n", __func__, (*tidData)->tid);
|
|
return ret;
|
|
}
|
|
|
|
static void SendSigToTzdriver(int pid)
|
|
{
|
|
int ret;
|
|
int mutexRet;
|
|
struct listnode *ptr = nullptr;
|
|
|
|
signal(SIGUSR1, SigUsr1Handler);
|
|
ALOGD("%s: ignore signal SIGUSR1!\n", __func__);
|
|
|
|
mutexRet = TidMutexLock();
|
|
if (mutexRet) {
|
|
ALOGE("tid mutex lock failed\n");
|
|
return;
|
|
}
|
|
if (!list_empty(&g_teecTidList)) {
|
|
list_for_each(ptr, &g_teecTidList) {
|
|
TidData *tmp = node_to_item(ptr, TidData, tidHead);
|
|
if (tmp->callingPid == pid) {
|
|
ret = tgkill(getpid(), tmp->tid, SIGUSR1);
|
|
ALOGD("%s: send signal SIGUSR1 to tid: %d! ret = %d\n", __func__, tmp->tid, ret);
|
|
}
|
|
}
|
|
}
|
|
TidMutexUnlock(mutexRet);
|
|
return;
|
|
}
|
|
|
|
static int MakeDirAndLinkUser(int userid, uint32_t userStatus, bool status)
|
|
{
|
|
int ret;
|
|
char username[DIR_NAME_LENS] = {0};
|
|
|
|
/* create user sec storage dir */
|
|
ret = MakeSecStorageDir(reinterpret_cast<const char *>(SEC_STORAGE_DATA_USERS), strlen(SEC_STORAGE_DATA_USERS));
|
|
if (ret < 0) {
|
|
ALOGE("mkdir fail ,ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
/* symlink, no matter if error */
|
|
SymlinkUser0(SEC_STORAGE_DATA_DIR, SEC_STORAGE_DATA_USER_0);
|
|
ret = snprintf_s(username, sizeof(username), sizeof(username) - 1,
|
|
"%s%d", SEC_STORAGE_DATA_USERS, userid);
|
|
if (ret < 0) {
|
|
ALOGE("snprintf ret error\n");
|
|
return ret;
|
|
}
|
|
if (!status) {
|
|
ALOGE("userid %u is not in the status %x range\n", userStatus, userid);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
ret = MakeSecStorageDir(username, sizeof(username));
|
|
if (ret < 0) {
|
|
ALOGE("mkdir fail ,ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
static int UnlinkUser(int userid, uint32_t userStatus, bool status)
|
|
{
|
|
int ret;
|
|
char username[DIR_NAME_LENS] = {0};
|
|
|
|
/* delete user */
|
|
if (!status) {
|
|
ALOGE("userid %u is not in the status %x range\n", userStatus, userid);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
ret = snprintf_s(username, sizeof(username), sizeof(username) - 1,
|
|
"%s%d", SEC_STORAGE_DATA_USERS, userid);
|
|
if (ret < 0) {
|
|
ALOGE("snprintf2 ret error\n");
|
|
return ret;
|
|
}
|
|
ret = UnlinkRecursive(username);
|
|
if (ret < 0) {
|
|
ALOGE("rmdir fail ,ret=%d\n", ret);
|
|
return ret;
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
static void CopyToShareMemory(TEEC_SharedMemory *shareMemBuf, uint8_t *data,
|
|
uint32_t shmInfoOffset, uint32_t *shmOffset)
|
|
{
|
|
shareMemBuf->is_allocated = *reinterpret_cast<bool *>(data + shmInfoOffset);
|
|
shmInfoOffset += sizeof(bool);
|
|
|
|
shareMemBuf->flags = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
|
|
shmInfoOffset += sizeof(uint32_t);
|
|
|
|
shareMemBuf->ops_cnt = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
|
|
shmInfoOffset += sizeof(uint32_t);
|
|
|
|
*shmOffset = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
|
|
shmInfoOffset += sizeof(uint32_t);
|
|
|
|
shareMemBuf->size = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
|
|
shmInfoOffset += sizeof(uint32_t);
|
|
}
|
|
|
|
LibteecGlobal::~LibteecGlobal()
|
|
{
|
|
if (mHandle != nullptr) {
|
|
dlclose(mHandle);
|
|
mHandle = nullptr;
|
|
}
|
|
ALOGD("Deinit LibteecGlobal!\n");
|
|
}
|
|
|
|
bool LibteecGlobal::IsValidContextWithoutLock(const TEEC_Context *context, int pid)
|
|
{
|
|
int i;
|
|
int tmpCheckStatus;
|
|
DaemonProcdata *outProcData = GetProcdataByPid(pid);
|
|
|
|
tmpCheckStatus = (outProcData == nullptr || context == nullptr);
|
|
if (tmpCheckStatus) {
|
|
return false;
|
|
}
|
|
|
|
if (context->fd < 0) {
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
if (context->fd == outProcData->cxtFd[i]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool LibteecGlobal::IsValidContext(const TEEC_Context *context, int pid)
|
|
{
|
|
Mutex::Autolock _l(mProcDataLock);
|
|
return IsValidContextWithoutLock(context, pid);
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CheckAndOpenHandle()
|
|
{
|
|
Mutex::Autolock _l(mHandleLock);
|
|
if (mHandle == nullptr) {
|
|
mHandle = dlopen(DLOPEN_LIBTEEC_PATH, RTLD_LAZY);
|
|
if (mHandle == nullptr) {
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
initializeContextProxy =
|
|
reinterpret_cast<InitializeContextFunc>(dlsym(mHandle, "TEEC_InitializeContextWithType"));
|
|
openSessionProxy = reinterpret_cast<OpenSessionFunc>(dlsym(mHandle, "TEEC_OpenSessionHidl"));
|
|
invokeCommandProxy = reinterpret_cast<InvokeCommandFunc>(dlsym(mHandle, "TEEC_InvokeCommandHidl"));
|
|
closeSessionProxy = reinterpret_cast<CloseSessionFunc>(dlsym(mHandle, "TEEC_CloseSessionHidl"));
|
|
registerSharedMemoryProxy =
|
|
reinterpret_cast<RegisterSharedMemoryFunc>(dlsym(mHandle, "TEEC_RegisterSharedMemoryHidl"));
|
|
allocateSharedMemoryProxy =
|
|
reinterpret_cast<AllocateSharedMemoryFunc>(dlsym(mHandle, "TEEC_AllocateSharedMemoryHidl"));
|
|
releaseSharedMemoryProxy =
|
|
reinterpret_cast<ReleaseSharedMemoryFunc>(dlsym(mHandle, "TEEC_ReleaseSharedMemoryHidl"));
|
|
extTuiSendEventProxy = reinterpret_cast<ExtTuiSendEventFunc>(dlsym(mHandle, "TEEC_EXT_TuiSendEvent"));
|
|
getTEEVersionProxy = reinterpret_cast<GetTEEVersionFunc>(dlsym(mHandle, "TEEC_GetTEEVersionHidl"));
|
|
extSendSysHashXmlProxy = reinterpret_cast<ExtSendSysHashXmlFunc>(dlsym(mHandle, "SendSysHashXml"));
|
|
getBnContextProxy = reinterpret_cast<GetBnContextFunc>(dlsym(mHandle, "GetBnContext"));
|
|
putBnContextProxy = reinterpret_cast<PutBnContextFunc>(dlsym(mHandle, "PutBnContext"));
|
|
findAndRemoveBnContextProxy =
|
|
reinterpret_cast<FindAndRemoveBnContextFunc>(dlsym(mHandle, "FindAndRemoveBnContext"));
|
|
getBnSessionProxy = reinterpret_cast<GetBnSessionFunc>(dlsym(mHandle, "GetBnSession"));
|
|
putBnSessionProxy = reinterpret_cast<PutBnSessionFunc>(dlsym(mHandle, "PutBnSession"));
|
|
findAndRemoveBnSessionProxy =
|
|
reinterpret_cast<FindAndRemoveBnSessionFunc>(dlsym(mHandle, "FindAndRemoveSession"));
|
|
getBnShmByOffsetProxy = reinterpret_cast<GetBnShmByOffsetFunc>(dlsym(mHandle, "GetBnShmByOffset"));
|
|
putBnShmProxy = reinterpret_cast<PutBnShmFunc>(dlsym(mHandle, "PutBnShrMem"));
|
|
sendSecfileProxy = reinterpret_cast<SendSecfileFunc>(dlsym(mHandle, "TEEC_SendSecfileHidl"));
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* function implements */
|
|
/**************************************************************************/
|
|
Return<void> LibteecGlobal::initializeContext(const hidl_string &name,
|
|
const hidl_vec<uint8_t> &authInfo, initializeContext_cb hidlCallBackPtr)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_FAIL;
|
|
hidl_vec<uint8_t> contextOutPtr;
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
|
|
if (hidlCallBackPtr == nullptr) {
|
|
ALOGE("%s: hidlCallBackPtr is nullptr\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (putBnContextProxy == nullptr) {
|
|
ALOGE("no putBnContext in this handle!\n");
|
|
hidlCallBackPtr(ret, contextOutPtr);
|
|
return Void();
|
|
}
|
|
|
|
if ((authInfo.data() == nullptr) || (authInfo.size() != sizeof(CaAuthInfo))) {
|
|
ALOGE("%s: authInfo is nullptr or size is 0.\n", __func__);
|
|
hidlCallBackPtr(ret, contextOutPtr);
|
|
return Void();
|
|
}
|
|
|
|
CaAuthInfo *caAuth = reinterpret_cast<CaAuthInfo *>(malloc(sizeof(CaAuthInfo)));
|
|
if (caAuth == nullptr) {
|
|
ALOGE("%s: malloc ca auth failed\n", __func__);
|
|
hidlCallBackPtr(ret, contextOutPtr);
|
|
return Void();
|
|
}
|
|
(void)memcpy_s(caAuth, sizeof(CaAuthInfo), authInfo.data(), sizeof(CaAuthInfo));
|
|
|
|
ALOGD("%s: getCallingPid=%d", __func__, caAuth->pid);
|
|
|
|
Mutex::Autolock _l(mProcDataLock);
|
|
DaemonProcdata *outProcData = CallGetProcDataPtr(caAuth->pid);
|
|
if (outProcData == nullptr) {
|
|
goto INITEND;
|
|
}
|
|
|
|
ret = CallInitializeContextProxy(name, caAuth, &outContext);
|
|
if (ret == (int32_t)TEEC_SUCCESS) {
|
|
if (SetContextToProcData(outProcData, outContext)) {
|
|
ret = TEEC_FAIL;
|
|
putBnContextProxy(outContext); /* pair with ops_cnt++ when add to list */
|
|
putBnContextProxy(outContext); /* pair with initial value 1 */
|
|
goto INITEND;
|
|
}
|
|
contextOutPtr.setToExternal(reinterpret_cast<uint8_t *>(outContext), sizeof(TEEC_ContextHidl));
|
|
putBnContextProxy(outContext); /* pair with ops_cnt++ when add to list */
|
|
}
|
|
|
|
INITEND:
|
|
hidlCallBackPtr(ret, contextOutPtr);
|
|
free(caAuth);
|
|
return Void();
|
|
}
|
|
|
|
Return<DaemonProcdata *> LibteecGlobal::CallGetProcDataPtr(int pid)
|
|
{
|
|
DaemonProcdata *outProcData = GetProcdataByPid(pid);
|
|
if (outProcData != nullptr) {
|
|
if (CheckProcDataFdFull(outProcData)) {
|
|
ALOGE("%s: pid[%d] can not get more context, please finalize some of them\n", __func__, pid);
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
DaemonProcdata *procData = reinterpret_cast<DaemonProcdata *>(malloc(sizeof(DaemonProcdata)));
|
|
if (procData == nullptr) {
|
|
ALOGE("%s: procdata malloc failed\n", __func__);
|
|
return nullptr;
|
|
}
|
|
(void)memset_s(procData, sizeof(DaemonProcdata), 0, sizeof(DaemonProcdata));
|
|
|
|
for (int i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
procData->cxtFd[i] = -1;
|
|
}
|
|
procData->callingPid = pid;
|
|
list_init(&(procData->procdataHead));
|
|
list_add_tail(&g_teecHidlProcDataList, &procData->procdataHead);
|
|
|
|
outProcData = procData;
|
|
}
|
|
return outProcData;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallInitializeContextProxy(const hidl_string &name,
|
|
CaAuthInfo *authInfo, TEEC_ContextHidl **outHidlContext)
|
|
{
|
|
int ret;
|
|
const int32_t type = TEECD_CONNECT;
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
|
|
if (outHidlContext == nullptr) {
|
|
ALOGE("intialize context proxy: out hidl context is nullptr\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
if (initializeContextProxy == nullptr) {
|
|
ALOGE("no initializeContext in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
outContext = reinterpret_cast<TEEC_ContextHidl *>(malloc(sizeof(TEEC_ContextHidl)));
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: outContext malloc failed\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
(void)memset_s(outContext, sizeof(TEEC_ContextHidl), 0x00, sizeof(TEEC_ContextHidl));
|
|
|
|
ret = initializeContextProxy(reinterpret_cast<const char *>(name.c_str()),
|
|
reinterpret_cast<TEEC_ContextHidl *>(outContext), type, true, authInfo);
|
|
if (ret) {
|
|
ALOGE("%s: TEEC_InitializeContextWithType failed(0x%x)\n", __func__, (TEEC_Result)ret);
|
|
free(outContext);
|
|
outContext = nullptr;
|
|
}
|
|
*outHidlContext = outContext;
|
|
return ret;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::finalizeContext(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr)
|
|
{
|
|
ALOGD("%s: getCallingPid=%d", __func__, pid);
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) ||
|
|
(halCxtPtr.size() != sizeof(TEEC_Context)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
Mutex::Autolock _l(mProcDataLock);
|
|
if (!IsValidContextWithoutLock(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)) {
|
|
ALOGE("context and procdata have been released by service_died!\n");
|
|
return Void();
|
|
}
|
|
int32_t tempContextFd = CallFinalizeContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (tempContextFd < 0) {
|
|
ALOGE("%s: CallFinalizeContextProxy failed!\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
DaemonProcdata *outProcData = GetProcdataByPid(pid);
|
|
if (outProcData == nullptr) {
|
|
ALOGE("%s: outProcdata is nullptr\n", __func__);
|
|
return Void();
|
|
}
|
|
RemoveContextFromProcData(outProcData, tempContextFd);
|
|
if (CheckProcDataFdEmpty(outProcData)) {
|
|
list_remove(&outProcData->procdataHead);
|
|
free(outProcData);
|
|
outProcData = nullptr;
|
|
} else {
|
|
ALOGD("%s: still have context not finalize in pid[%d]\n", __func__, pid);
|
|
}
|
|
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallFinalizeContextProxy(const TEEC_Context *contextPtr)
|
|
{
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
int32_t contextFd;
|
|
|
|
if ((findAndRemoveBnContextProxy == nullptr) ||
|
|
(putBnContextProxy == nullptr)) {
|
|
ALOGE("call finalizeContext proxy:missing proxy in this handle!\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
outContext = findAndRemoveBnContextProxy(contextPtr);
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
contextFd = outContext->fd;
|
|
putBnContextProxy(outContext); /* pair with initialize context */
|
|
return contextFd;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::openSession(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const android::hardware::hidl_handle &handle, const hidl_string &taPath,
|
|
const hidl_vec<uint8_t> &halUuidPtr, uint32_t halConnMth, const hidl_vec<uint8_t> &haConnData,
|
|
const hidl_vec<uint8_t> &halOptPtr, const android::hardware::hidl_memory &opMem, openSession_cb hidlCallBackPtr)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_FAIL;
|
|
hidl_vec<uint8_t> contextOutPtr;
|
|
hidl_vec<uint8_t> sessionOutPtr;
|
|
hidl_vec<uint8_t> optOutPtr;
|
|
int32_t originRet = TEEC_ORIGIN_API;
|
|
|
|
if (hidlCallBackPtr == nullptr) {
|
|
ALOGE("%s: hidlCallBackPtr is nullptr\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (putBnSessionProxy == nullptr || putBnContextProxy == nullptr) {
|
|
ALOGE("open session: missing proxy in this handle!\n");
|
|
hidlCallBackPtr(ret, contextOutPtr, sessionOutPtr, optOutPtr, originRet);
|
|
return Void();
|
|
}
|
|
|
|
InOutPara paraInOut; /* just for transfer params */
|
|
paraInOut.cmdId = (int32_t)halConnMth;
|
|
paraInOut.pid = pid;
|
|
ALOGD("%s: getCallingPid=%d ", __func__, paraInOut.pid);
|
|
|
|
TEEC_Session *outSession = nullptr;
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
TEEC_Session retSession;
|
|
(void)memset_s((void *)(&retSession), sizeof(TEEC_Session), 0, sizeof(TEEC_Session));
|
|
int getBnRet = CallGetBnContextProxy(halCxtPtr, paraInOut.pid, &outSession, &outContext);
|
|
if (getBnRet) {
|
|
ret = getBnRet;
|
|
ALOGE("%s: callGetBnProxy failed! ret is %x.\n", __func__, getBnRet);
|
|
hidlCallBackPtr(ret, contextOutPtr, sessionOutPtr, optOutPtr, originRet);
|
|
return Void();
|
|
}
|
|
|
|
TaFileInfo taFile = { .taPath = nullptr, .taFp = nullptr };
|
|
taFile.taPath = reinterpret_cast<const uint8_t *>(taPath.c_str());
|
|
native_handle_t *tempHandle = nullptr;
|
|
taFile.taFp = GetFpFromHandle(handle, tempHandle);
|
|
|
|
TEEC_Operation operation;
|
|
(void)memset_s(&operation, sizeof(TEEC_Operation), 0, sizeof(TEEC_Operation));
|
|
|
|
paraInOut.operationPtr = &operation;
|
|
paraInOut.outContextPtr = outContext;
|
|
paraInOut.outSessionPtr = outSession;
|
|
|
|
if (SubOpenSession(&taFile, halOptPtr, opMem, halUuidPtr, haConnData, ¶InOut)) {
|
|
free(outSession);
|
|
goto OPENSESSIONEND;
|
|
}
|
|
retSession.session_id = outSession->session_id;
|
|
retSession.service_id = outSession->service_id;
|
|
retSession.ops_cnt = outSession->ops_cnt;
|
|
contextOutPtr.setToExternal(reinterpret_cast<uint8_t *>(outContext), sizeof(TEEC_ContextHidl));
|
|
sessionOutPtr.setToExternal(reinterpret_cast<uint8_t *>(&retSession), sizeof(TEEC_Session));
|
|
optOutPtr.setToExternal(reinterpret_cast<uint8_t *>(&operation), sizeof(TEEC_Operation));
|
|
putBnSessionProxy(outSession); /* pair with ops_cnt++ when add to list */
|
|
|
|
OPENSESSIONEND:
|
|
ret = paraInOut.ret;
|
|
originRet = paraInOut.originRet;
|
|
putBnContextProxy(outContext);
|
|
if (taFile.taFp != nullptr) {
|
|
fclose(taFile.taFp);
|
|
}
|
|
native_handle_delete(tempHandle);
|
|
hidlCallBackPtr(ret, contextOutPtr, sessionOutPtr, optOutPtr, originRet);
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallGetBnContextProxy(const hidl_vec<uint8_t> &halCxtPtr,
|
|
int pid, TEEC_Session **outHidlSession, TEEC_ContextHidl **outHidlContext)
|
|
{
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) || (halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
if (getBnContextProxy == nullptr || putBnContextProxy == nullptr) {
|
|
ALOGE("call get bn context proxy: missing proxy in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
outContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service.\n", __func__);
|
|
return TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
TEEC_Session *outSession = reinterpret_cast<TEEC_Session *>(malloc(sizeof(TEEC_Session)));
|
|
if (outSession == nullptr) {
|
|
ALOGE("%s: outSession malloc failed!\n", __func__);
|
|
putBnContextProxy(outContext);
|
|
return TEEC_FAIL;
|
|
}
|
|
(void)memset_s(outSession, sizeof(TEEC_Session), 0x00, sizeof(TEEC_Session));
|
|
|
|
*outHidlSession = outSession;
|
|
*outHidlContext = outContext;
|
|
return TEEC_SUCCESS;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::SubOpenSession(const TaFileInfo *taFile,
|
|
const hidl_vec<uint8_t> &halOptPtr, const android::hardware::hidl_memory &opMem,
|
|
const hidl_vec<uint8_t> &halUuidPtr, const hidl_vec<uint8_t> &haConnData, InOutPara *paraInOut)
|
|
{
|
|
int tempRet;
|
|
sp<IMemory> memory;
|
|
TEEC_ContextHidl *outContext = paraInOut->outContextPtr;
|
|
TEEC_Session *outSession = paraInOut->outSessionPtr;
|
|
paraInOut->ret = TEEC_FAIL;
|
|
paraInOut->originRet = TEEC_ORIGIN_API;
|
|
|
|
TEEC_Operation *operation = paraInOut->operationPtr;
|
|
operation->started = 1;
|
|
TEEC_SharedMemory shm[PARAM_NUM];
|
|
TEEC_SharedMemoryHidl *shmHidl[PARAM_NUM];
|
|
|
|
(void)memset_s(&shm, sizeof(shm), 0, sizeof(shm));
|
|
(void)memset_s(&shmHidl, sizeof(shmHidl), 0x00, sizeof(shmHidl));
|
|
|
|
int tmpCheckStatus = ((halOptPtr.data() != nullptr) && (halOptPtr.size() == sizeof(TEEC_Operation)));
|
|
int tmpCheckStatus2 = ((opMem.size() != 0) && (opMem.handle() != nullptr));
|
|
|
|
if (tmpCheckStatus) {
|
|
tempRet = GetOperationFromHidlVec(halOptPtr, operation);
|
|
if (tempRet != TEE_HIDL_SUCCESS) {
|
|
ALOGE("get oper from hidl vec failed.\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
if (tmpCheckStatus2) {
|
|
memory = mapMemory(opMem);
|
|
if (memory == nullptr) {
|
|
ALOGD("%s: memory is nullptr.\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
uint8_t *data = static_cast<uint8_t *>(static_cast<void *>(memory->getPointer()));
|
|
memory->update();
|
|
size_t memSize = (size_t)memory->getSize();
|
|
|
|
TEEC_Result ret = DecodeHidlMemory(outContext, operation,
|
|
shm, shmHidl, PARAM_NUM, data, memSize);
|
|
if (ret) {
|
|
paraInOut->ret = ret;
|
|
ALOGE("open session: decode hidl memory failed\n");
|
|
PutAllocShrMem(shmHidl, PARAM_NUM);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
} else {
|
|
ALOGD("%s: opMem is nullptr or size is 0\n", __func__);
|
|
}
|
|
}
|
|
|
|
tempRet = CallOpenSessionProxy(halUuidPtr, taFile, outContext, outSession, paraInOut, haConnData);
|
|
PutAllocShrMem(shmHidl, PARAM_NUM);
|
|
if (tempRet != TEE_HIDL_SUCCESS) {
|
|
ALOGE("%s: callInvokeCommandProxy failed, ret is %x.\n", __func__, tempRet);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
int tmpCheckStatus3 = (memory != nullptr);
|
|
tmpCheckStatus = (tmpCheckStatus && tmpCheckStatus2 && tmpCheckStatus3);
|
|
if (tmpCheckStatus) {
|
|
memory->update();
|
|
memory->commit();
|
|
} else {
|
|
ALOGD("%s: memory maybe nullptr, status is %x...\n", __func__, tmpCheckStatus3);
|
|
ALOGD("%s: opMem maybe nullptr or size maybe 0, status is %x...\n", __func__, tmpCheckStatus2);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallOpenSessionProxy(const hidl_vec<uint8_t> &halUuidPtr,
|
|
const TaFileInfo *taFile, TEEC_ContextHidl *outContext, TEEC_Session *outSession,
|
|
InOutPara *paraInOut, const hidl_vec<uint8_t> &haConnData)
|
|
{
|
|
int ret;
|
|
int32_t originRet = 0;
|
|
TidData *tidData = nullptr;
|
|
uint32_t halConnMth = (uint32_t)paraInOut->cmdId;
|
|
int pid = paraInOut->pid;
|
|
TEEC_Operation *operation = (paraInOut->operationPtr);
|
|
|
|
if (openSessionProxy == nullptr) {
|
|
ALOGE("no openSession in this handle!\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
ret = AddTidData(&tidData, pid);
|
|
if (ret) {
|
|
ALOGE("%s: AddTidData failed\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
ret = openSessionProxy(pid, taFile, reinterpret_cast<TEEC_ContextHidl *>(outContext),
|
|
reinterpret_cast<TEEC_Session *>(outSession), reinterpret_cast<const TEEC_UUID *>(halUuidPtr.data()),
|
|
halConnMth, reinterpret_cast<const void *>(haConnData.data()), reinterpret_cast<TEEC_Operation *>(operation),
|
|
reinterpret_cast<uint32_t *>(&originRet));
|
|
ALOGD("%s: tid %d return from TEE.\n", __func__, tidData->tid);
|
|
RemoveTidFromList(tidData);
|
|
tidData = nullptr;
|
|
|
|
paraInOut->ret = ret; /* return code from teeos or tzdriver, such as TEEC_FAIL */
|
|
paraInOut->originRet = originRet; /* return origin code from teeos or tzdriver, such as TEE_ORIGIN_TEE */
|
|
if (ret != TEEC_SUCCESS) {
|
|
ALOGD("open session proxy return failed from TEE: 0x%x \n", ret);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::closeSession(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halSessPtr)
|
|
{
|
|
ALOGD("%s: get Calling Pid=%d", __func__, pid);
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) || (halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (getBnContextProxy == nullptr ||
|
|
putBnContextProxy == nullptr ||
|
|
putBnSessionProxy == nullptr ||
|
|
findAndRemoveBnSessionProxy == nullptr) {
|
|
ALOGE("close session: missing proxy in this handle!\n");
|
|
return Void();
|
|
}
|
|
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
outContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
TEEC_Session *outSession = nullptr;
|
|
tmpCheckStatus = ((halSessPtr.data() != nullptr) &&
|
|
(halSessPtr.size() == sizeof(TEEC_Session)));
|
|
if (!tmpCheckStatus) {
|
|
ALOGE("receive session struct failed!\n");
|
|
putBnContextProxy(outContext);
|
|
return Void();
|
|
}
|
|
|
|
const TEEC_Session *inSession =
|
|
reinterpret_cast<const TEEC_Session *>(halSessPtr.data());
|
|
outSession = findAndRemoveBnSessionProxy(inSession, outContext);
|
|
if (outSession == nullptr) {
|
|
ALOGE("%s: no session found in hidl service!\n", __func__);
|
|
putBnContextProxy(outContext);
|
|
return Void();
|
|
}
|
|
|
|
CallCloseSessionProxy(outSession, outContext, pid);
|
|
putBnSessionProxy(outSession); /* pair with open session */
|
|
putBnContextProxy(outContext);
|
|
|
|
return Void();
|
|
}
|
|
|
|
Return<void> LibteecGlobal::CallCloseSessionProxy(TEEC_Session *outSession,
|
|
TEEC_ContextHidl *outContext, int pid)
|
|
{
|
|
TidData *tidData = nullptr;
|
|
|
|
if (closeSessionProxy == nullptr) {
|
|
ALOGE("no closeSession in this handle!\n");
|
|
return Void();
|
|
}
|
|
|
|
int ret = AddTidData(&tidData, pid);
|
|
if (ret) {
|
|
ALOGE("%s: add_tid_data failed\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
closeSessionProxy(reinterpret_cast<TEEC_Session *>(outSession),
|
|
reinterpret_cast<TEEC_ContextHidl *>(outContext));
|
|
ALOGD("%s: tid %d return from TEE\n", __func__, tidData->tid);
|
|
RemoveTidFromList(tidData);
|
|
tidData = nullptr;
|
|
|
|
return Void();
|
|
}
|
|
|
|
Return<void> LibteecGlobal::invokeCommandHidl(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halSessPtr, uint32_t cmdId, const hidl_vec<uint8_t> &halOptPtr,
|
|
const android::hardware::hidl_memory &opMem, invokeCommandHidl_cb hidlCallBackPtr)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_FAIL;
|
|
hidl_vec<uint8_t> sessionOutPtr;
|
|
hidl_vec<uint8_t> optOutPtr;
|
|
int32_t originRet = TEEC_ORIGIN_API;
|
|
TEEC_Operation operation;
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
TEEC_Session *outSession = nullptr;
|
|
InOutPara paraInOut; /* just for transfer params */
|
|
int32_t tempRet;
|
|
|
|
if (hidlCallBackPtr == nullptr) {
|
|
ALOGE("%s: hidlCallBackPtr is nullptr\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (putBnSessionProxy == nullptr || putBnContextProxy == nullptr) {
|
|
ALOGE("invoke command: missing proxy in this handle!\n");
|
|
goto INVOKEEND;
|
|
}
|
|
|
|
ALOGD("%s: getCallingPid=%d", __func__, pid);
|
|
|
|
(void)memset_s(&operation, sizeof(TEEC_Operation), 0x00, sizeof(TEEC_Operation)); /* clear operation */
|
|
operation.started = 1;
|
|
|
|
tempRet = CallGetBnProxy(pid, halCxtPtr, halSessPtr, &outContext, &outSession);
|
|
if (tempRet != 0) {
|
|
ret = tempRet;
|
|
goto INVOKEEND;
|
|
}
|
|
|
|
paraInOut.cmdId = (int32_t)cmdId;
|
|
paraInOut.pid = pid;
|
|
paraInOut.operationPtr = &operation;
|
|
paraInOut.outContextPtr = outContext;
|
|
paraInOut.outSessionPtr = outSession;
|
|
|
|
tempRet = SubInvokeCommand(halOptPtr, opMem, ¶InOut);
|
|
/* tempRet=0, meas TEEC_SUCCESS */
|
|
if (tempRet == 0) {
|
|
ret = paraInOut.ret;
|
|
originRet = paraInOut.originRet;
|
|
sessionOutPtr.setToExternal(reinterpret_cast<uint8_t *>(outSession), sizeof(TEEC_Session));
|
|
optOutPtr.setToExternal(reinterpret_cast<uint8_t *>(&operation), sizeof(TEEC_Operation));
|
|
} else {
|
|
ALOGE("%s: call SubInvokeCommand return, ret is %x.\n", __func__, tempRet);
|
|
}
|
|
|
|
putBnSessionProxy(outSession);
|
|
putBnContextProxy(outContext);
|
|
|
|
INVOKEEND:
|
|
hidlCallBackPtr(ret, sessionOutPtr, optOutPtr, originRet);
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallGetBnProxy(int pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halSessPtr, TEEC_ContextHidl **outHidlContext, TEEC_Session **outHidlSession)
|
|
{
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
TEEC_Session *outSession = nullptr;
|
|
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) || (halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
if (getBnContextProxy == nullptr ||
|
|
putBnContextProxy == nullptr ||
|
|
getBnSessionProxy == nullptr) {
|
|
ALOGE("call get bn proxy: missing proxy in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
outContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!\n", __func__);
|
|
return TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
tmpCheckStatus = ((halSessPtr.data() != nullptr) &&
|
|
(halSessPtr.size() == sizeof(TEEC_Session)));
|
|
if (!tmpCheckStatus) {
|
|
ALOGE("receive session struct failed!\n");
|
|
putBnContextProxy(outContext);
|
|
return TEEC_FAIL;
|
|
}
|
|
outSession = getBnSessionProxy(reinterpret_cast<const TEEC_Session *>(halSessPtr.data()), outContext);
|
|
if (outSession == nullptr) {
|
|
ALOGE("%s: no session found in hidl service!\n", __func__);
|
|
putBnContextProxy(outContext);
|
|
return TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
*outHidlContext = outContext;
|
|
*outHidlSession = outSession;
|
|
return TEEC_SUCCESS;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::SubInvokeCommand(const hidl_vec<uint8_t> &halOptPtr,
|
|
const android::hardware::hidl_memory &opMem, InOutPara *paraInOut)
|
|
{
|
|
int tempRet;
|
|
sp<IMemory> memory;
|
|
TEEC_Operation *operation = (paraInOut->operationPtr);
|
|
TEEC_ContextHidl *outContext = paraInOut->outContextPtr;
|
|
TEEC_Session *outSession = paraInOut->outSessionPtr;
|
|
TEEC_SharedMemory shm[PARAM_NUM];
|
|
TEEC_SharedMemoryHidl *shmHidl[PARAM_NUM];
|
|
|
|
(void)memset_s(&shm, sizeof(shm), 0x00, sizeof(shm));
|
|
(void)memset_s(&shmHidl, sizeof(shmHidl), 0x00, sizeof(shmHidl));
|
|
|
|
int tmpCheckStatus = ((halOptPtr.data() != nullptr) && (halOptPtr.size() == sizeof(TEEC_Operation)));
|
|
int tmpCheckStatus2 = ((opMem.size() != 0) && (opMem.handle() != nullptr));
|
|
|
|
if (tmpCheckStatus) {
|
|
tempRet = GetOperationFromHidlVec(halOptPtr, operation);
|
|
if (tempRet != TEE_HIDL_SUCCESS) {
|
|
ALOGE("get oper from hidl vec failed.\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
if (tmpCheckStatus2) {
|
|
memory = mapMemory(opMem);
|
|
if (memory == nullptr) {
|
|
ALOGD("%s: memory is nullptr\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
uint8_t *dataPtr = static_cast<uint8_t *>(static_cast<void *>(memory->getPointer()));
|
|
memory->update();
|
|
size_t memSize = (size_t)memory->getSize();
|
|
|
|
TEEC_Result ret = DecodeHidlMemory(outContext, operation,
|
|
shm, shmHidl, PARAM_NUM, dataPtr, memSize);
|
|
if (ret) {
|
|
ALOGE("invoke command: decode hidl memory failed\n");
|
|
PutAllocShrMem(shmHidl, PARAM_NUM);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
} else {
|
|
ALOGD("%s: opMem is nullptr or size is 0\n", __func__);
|
|
}
|
|
}
|
|
|
|
tempRet = CallInvokeCommandProxy(outContext, outSession, operation, paraInOut);
|
|
PutAllocShrMem(shmHidl, PARAM_NUM);
|
|
if (tempRet != TEE_HIDL_SUCCESS) {
|
|
ALOGE("%s: callInvokeCommandProxy failed, ret is %x.\n", __func__, tempRet);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
int tmpCheckStatus3 = (memory != nullptr);
|
|
tmpCheckStatus = (tmpCheckStatus2 && tmpCheckStatus3 && tmpCheckStatus);
|
|
if (tmpCheckStatus) {
|
|
memory->update();
|
|
memory->commit();
|
|
} else {
|
|
ALOGD("%s: memory maybe nullptr, status is %x.\n", __func__, tmpCheckStatus3);
|
|
ALOGD("%s: opMem maybe nullptr or size maybe 0, status is %x.\n", __func__, tmpCheckStatus2);
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallInvokeCommandProxy(TEEC_ContextHidl *outContext,
|
|
TEEC_Session *outSession, TEEC_Operation *operation, InOutPara *paraInOut)
|
|
{
|
|
int ret;
|
|
int32_t originRet = 0;
|
|
TidData *tidData = nullptr;
|
|
|
|
if (invokeCommandProxy == nullptr) {
|
|
ALOGE("no invoke command in this handle!\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
ret = AddTidData(&tidData, paraInOut->pid);
|
|
if (ret) {
|
|
ALOGE("%s: AddTidData failed\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
ret = invokeCommandProxy(reinterpret_cast<TEEC_ContextHidl *>(outContext),
|
|
reinterpret_cast<TEEC_Session *>(outSession), paraInOut->cmdId,
|
|
reinterpret_cast<TEEC_Operation *>(operation), reinterpret_cast<uint32_t *>(&originRet));
|
|
ALOGD("%s: tid %d return from TEE\n", __func__, tidData->tid);
|
|
RemoveTidFromList(tidData);
|
|
tidData = nullptr;
|
|
|
|
paraInOut->ret = ret; /* return code from teeos or tzdriver, such as TEEC_FAIL */
|
|
paraInOut->originRet = originRet; /* return origin code from teeos or tzdriver, such as TEE_ORIGIN_TEE */
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::registerSharedMemory(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halMemPtr, registerSharedMemory_cb hidlCallBackPtr)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_FAIL;
|
|
hidl_vec<uint8_t> outShmPtr;
|
|
|
|
if (hidlCallBackPtr == nullptr) {
|
|
ALOGE("%s: hidlCallBackPtr is nullptr\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) || (halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
hidlCallBackPtr(ret, outShmPtr);
|
|
return Void();
|
|
}
|
|
(void)CheckAndOpenHandle();
|
|
|
|
if (getBnContextProxy == nullptr || putBnContextProxy == nullptr) {
|
|
ALOGE("missing proxy in this handle!\n");
|
|
hidlCallBackPtr(ret, outShmPtr);
|
|
return Void();
|
|
}
|
|
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
outContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!\n", __func__);
|
|
ret = TEEC_ERROR_BAD_PARAMETERS;
|
|
hidlCallBackPtr(ret, outShmPtr);
|
|
return Void();
|
|
}
|
|
|
|
TEEC_SharedMemoryHidl outShm;
|
|
(void)memset_s((void *)(&outShm), sizeof(TEEC_SharedMemoryHidl), 0, sizeof(TEEC_SharedMemoryHidl));
|
|
ret = CallRegisterSharedMemoryProxy(halMemPtr, outContext, &outShm);
|
|
if (ret) {
|
|
ALOGE("%s: callRegisterSharedMemoryProxy failed, ret is %x.\n", __func__, ret);
|
|
putBnContextProxy(outContext);
|
|
hidlCallBackPtr(ret, outShmPtr);
|
|
return Void();
|
|
}
|
|
|
|
putBnContextProxy(outContext);
|
|
outShmPtr.setToExternal(reinterpret_cast<uint8_t *>(&outShm), sizeof(TEEC_SharedMemoryHidl));
|
|
hidlCallBackPtr(ret, outShmPtr);
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallRegisterSharedMemoryProxy(const hidl_vec<uint8_t> &halMemPtr,
|
|
TEEC_ContextHidl *outContext, TEEC_SharedMemoryHidl *outRegShm)
|
|
{
|
|
int32_t ret;
|
|
TEEC_SharedMemoryHidl *outShm = nullptr;
|
|
|
|
if (registerSharedMemoryProxy == nullptr || putBnShmProxy == nullptr) {
|
|
ALOGE("call register shrmem proxy: missing proxy in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
outShm = reinterpret_cast<TEEC_SharedMemoryHidl *>(malloc(sizeof(TEEC_SharedMemoryHidl)));
|
|
if (outShm == nullptr) {
|
|
ALOGE("%s: outShm malloc failed.\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
(void)memset_s(outShm, sizeof(TEEC_SharedMemoryHidl), 0x00, sizeof(TEEC_SharedMemoryHidl));
|
|
|
|
int tmpCheckStatus = ((halMemPtr.data() != nullptr) && (halMemPtr.size() == sizeof(TEEC_SharedMemory)));
|
|
if (tmpCheckStatus) {
|
|
if (memcpy_s(outShm, sizeof(TEEC_SharedMemoryHidl), halMemPtr.data(), sizeof(TEEC_SharedMemory))) {
|
|
ALOGE("%s: memcpy failed when copy data to shm[]!\n", __func__);
|
|
free(outShm);
|
|
return TEEC_FAIL;
|
|
}
|
|
}
|
|
|
|
ret = registerSharedMemoryProxy(reinterpret_cast<TEEC_ContextHidl *>(outContext),
|
|
reinterpret_cast<TEEC_SharedMemoryHidl *>(outShm));
|
|
if (ret) {
|
|
free(outShm);
|
|
return ret;
|
|
}
|
|
outRegShm->ops_cnt = outShm->ops_cnt;
|
|
outRegShm->is_allocated = outShm->is_allocated;
|
|
outRegShm->offset = outShm->offset;
|
|
putBnShmProxy(outShm); /* pair with ops_cnt++ when add to list */
|
|
return ret; /* maybe ok, maybe failed */
|
|
}
|
|
|
|
Return<void> LibteecGlobal::allocateSharedMemory(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halMemPtr, allocateSharedMemory_cb hidlCallBackPtr)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_ERROR_BAD_PARAMETERS;
|
|
hidl_vec<uint8_t> outShmPtr;
|
|
android::hardware::hidl_handle handle;
|
|
int tempFd = -1;
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
|
|
if (hidlCallBackPtr == nullptr) {
|
|
ALOGE("%s: hidlCallBackPtr is nullptr\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (putBnContextProxy == nullptr) {
|
|
ALOGE("allocate sharemem : missing proxy in this handle!!!\n");
|
|
ret = TEEC_FAIL;
|
|
hidlCallBackPtr(ret, outShmPtr, handle);
|
|
return Void();
|
|
}
|
|
|
|
ret = GetSharedMemoryContextAndFd(halCxtPtr, pid, &outContext, &tempFd);
|
|
if (ret != TEEC_SUCCESS) {
|
|
ALOGE("get shm contex failed , or get fd failed when Ashm\n");
|
|
hidlCallBackPtr(ret, outShmPtr, handle);
|
|
return Void();
|
|
}
|
|
|
|
native_handle_t *nativeHandle = native_handle_create(1, 0); /* 2params: means: nFds & nInts */
|
|
if (nativeHandle == nullptr) {
|
|
ALOGE("create nativehandle failed when Ashm\n");
|
|
ret = TEEC_FAIL;
|
|
close(tempFd);
|
|
goto ALLOCEND;
|
|
}
|
|
nativeHandle->data[0] = tempFd;
|
|
|
|
TEEC_SharedMemoryHidl outShm;
|
|
(void)memset_s((void *)(&outShm), sizeof(TEEC_SharedMemoryHidl), 0, sizeof(TEEC_SharedMemoryHidl));
|
|
ret = CallAllocateSharedMemoryProxy(halMemPtr, outContext, &outShm);
|
|
if (ret) {
|
|
ALOGE("%s: callAllocateSharedMemoryProxy failed, ret is %x.\n", __func__, ret);
|
|
native_handle_close(nativeHandle);
|
|
native_handle_delete(nativeHandle);
|
|
goto ALLOCEND;
|
|
}
|
|
|
|
/* 2nd param: true: means take ownership */
|
|
handle.setTo(nativeHandle, true);
|
|
|
|
outShmPtr.setToExternal(reinterpret_cast<uint8_t *>(&outShm), sizeof(TEEC_SharedMemoryHidl));
|
|
|
|
ALLOCEND:
|
|
hidlCallBackPtr(ret, outShmPtr, handle);
|
|
putBnContextProxy(outContext);
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::GetSharedMemoryContextAndFd(const hidl_vec<uint8_t> &halCxtPtr,
|
|
int32_t pid, TEEC_ContextHidl **outContext, int *fd)
|
|
{
|
|
TEEC_ContextHidl *shmContext = nullptr;
|
|
|
|
int tmpCheckStatus = (getBnContextProxy == nullptr || putBnContextProxy == nullptr);
|
|
if (tmpCheckStatus) {
|
|
ALOGE("allocate sharemem : missing proxy in this handle!!!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
tmpCheckStatus = ((halCxtPtr.data() == nullptr) || (halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
shmContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (shmContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!!!\n", __func__);
|
|
return TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
*fd = dup(shmContext->fd);
|
|
if (*fd < 0) {
|
|
ALOGE("get fd failed when Ashm \n");
|
|
putBnContextProxy(shmContext);
|
|
return TEEC_FAIL;
|
|
}
|
|
*outContext = shmContext;
|
|
return TEEC_SUCCESS;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CallAllocateSharedMemoryProxy(const hidl_vec<uint8_t> &halMemPtr,
|
|
TEEC_ContextHidl *outContext, TEEC_SharedMemoryHidl *outAllocShm)
|
|
{
|
|
TEEC_SharedMemoryHidl *outShm = nullptr;
|
|
int checkStat = (allocateSharedMemoryProxy == nullptr || putBnShmProxy == nullptr);
|
|
if (checkStat) {
|
|
ALOGE("call allocate sharemem proxy:missing proxy in this handle!!!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
outShm = reinterpret_cast<TEEC_SharedMemoryHidl *>(malloc(sizeof(TEEC_SharedMemoryHidl)));
|
|
if (outShm == nullptr) {
|
|
ALOGE("%s: outShm malloc failed\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
(void)memset_s(outShm, sizeof(TEEC_SharedMemoryHidl), 0x00, sizeof(TEEC_SharedMemoryHidl));
|
|
|
|
int tmpCheckStatus = ((halMemPtr.data() != nullptr) && (halMemPtr.size() == sizeof(TEEC_SharedMemory)));
|
|
if (tmpCheckStatus) {
|
|
if (memcpy_s(outShm, sizeof(TEEC_SharedMemoryHidl), halMemPtr.data(), sizeof(TEEC_SharedMemory))) {
|
|
ALOGE("%s: memcpy failed when copy data to shm[]\n", __func__);
|
|
free(outShm);
|
|
return TEEC_FAIL;
|
|
}
|
|
}
|
|
|
|
int32_t ret = allocateSharedMemoryProxy(reinterpret_cast<TEEC_ContextHidl *>(outContext),
|
|
reinterpret_cast<TEEC_SharedMemoryHidl *>(outShm));
|
|
if (ret) {
|
|
ALOGE("%s: allocate shared memory failed\n", __func__);
|
|
free(outShm);
|
|
return ret;
|
|
}
|
|
outAllocShm->ops_cnt = outShm->ops_cnt;
|
|
outAllocShm->is_allocated = outShm->is_allocated;
|
|
outAllocShm->offset = outShm->offset;
|
|
putBnShmProxy(outShm); /* pair with ops_cnt++ when add to list */
|
|
return ret; /* maybe ok, maybe failed */
|
|
}
|
|
|
|
Return<void> LibteecGlobal::releaseSharedMemory(int32_t pid, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halMemPtr,
|
|
uint32_t shmOffset)
|
|
{
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) || (halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("%s: invalid context!\n", __func__);
|
|
return Void();
|
|
}
|
|
(void)CheckAndOpenHandle();
|
|
|
|
TEEC_SharedMemoryHidl outShm;
|
|
tmpCheckStatus = ((halMemPtr.data() != nullptr) && (halMemPtr.size() == sizeof(TEEC_SharedMemory)));
|
|
if (tmpCheckStatus) {
|
|
if (memcpy_s(&outShm, sizeof(TEEC_SharedMemoryHidl), halMemPtr.data(), sizeof(TEEC_SharedMemory))) {
|
|
ALOGE("%s: memcpy failed when copy data to outShm \n", __func__);
|
|
return Void();
|
|
}
|
|
outShm.offset = shmOffset;
|
|
}
|
|
|
|
CallReleaseSharedMemoryProxy(halCxtPtr, &outShm);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> LibteecGlobal::CallReleaseSharedMemoryProxy(const hidl_vec<uint8_t> &halCxtPtr,
|
|
TEEC_SharedMemoryHidl *outShm)
|
|
{
|
|
if (getBnContextProxy == nullptr ||
|
|
putBnContextProxy == nullptr ||
|
|
releaseSharedMemoryProxy == nullptr) {
|
|
ALOGE("call release sharemem proxy:missing proxy in this handle!!!\n");
|
|
return Void();
|
|
}
|
|
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
outContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
outShm->context = outContext;
|
|
releaseSharedMemoryProxy(outShm);
|
|
putBnContextProxy(outContext);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> LibteecGlobal::requestCancellation(const hidl_vec<uint8_t> &halOptPtr)
|
|
{
|
|
ALOGI("%s: hidl requestCancellation not support\n", __func__);
|
|
(void)halOptPtr;
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::extTuiSendEvent(int32_t pid, int32_t uid,
|
|
const hidl_vec<uint8_t> &halTuiPtr)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_ERROR_BAD_PARAMETERS;
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (extTuiSendEventProxy == nullptr) {
|
|
ALOGE("no TEEC_EXT_TuiSendEvent in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
CaAuthInfo *caAuth = reinterpret_cast<CaAuthInfo *>(malloc(sizeof(CaAuthInfo)));
|
|
if (caAuth == nullptr) {
|
|
ALOGE("%s: malloc ca auth failed\n", __func__);
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
caAuth->uid = (uid_t)uid;
|
|
caAuth->pid = pid;
|
|
caAuth->type = SYSTEM_CA;
|
|
caAuth->fromHidlSide = HIDL_SIDE;
|
|
int tmpCheckStatus = ((halTuiPtr.data() != nullptr) &&
|
|
(halTuiPtr.size() == sizeof(TEEC_TUI_Parameter)));
|
|
if (!tmpCheckStatus) {
|
|
ALOGE("no TEEC_EXT_TuiSendEvent for this handle!\n");
|
|
goto freeBuffer;
|
|
}
|
|
ret = extTuiSendEventProxy(reinterpret_cast<const TEEC_TUI_Parameter *>(halTuiPtr.data()), caAuth);
|
|
freeBuffer:
|
|
free(caAuth);
|
|
return ret;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::setCallBack(const ::android::sp<ILibteecGlobalNotify> ¬ify)
|
|
{
|
|
if (notify == nullptr) {
|
|
ALOGE("%s: Notify is NULL\n", __func__);
|
|
return Void();
|
|
}
|
|
|
|
g_teecNotify = notify;
|
|
int pid = android::hardware::IPCThreadState::self()->getCallingPid();
|
|
int result = g_teecNotify->linkToDeath(this, pid);
|
|
if (!result) {
|
|
ALOGE("%s: linkToDeath failed %d\n", __func__, result);
|
|
}
|
|
ALOGW("%s: receive notify from teec service pid=%d\n", __func__, pid);
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::extSendSystemHashXml(const hidl_vec<uint8_t> &halXmlPtr,
|
|
const hidl_vec<uint8_t> &authInfo)
|
|
{
|
|
int32_t ret = (int32_t)TEEC_ERROR_BAD_PARAMETERS;
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (extSendSysHashXmlProxy == nullptr) {
|
|
ALOGE("no SendSysHashXml for this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
int tmpCheckStatus = ((authInfo.data() != nullptr) && (authInfo.size() == sizeof(CaAuthInfo)));
|
|
if (!tmpCheckStatus) {
|
|
ALOGE("%s: authInfo is nullptr or size is 0.\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
CaAuthInfo *caAuth = reinterpret_cast<CaAuthInfo *>(malloc(sizeof(CaAuthInfo)));
|
|
if (caAuth == nullptr) {
|
|
ALOGE("%s: malloc ca auth failed\n", __func__);
|
|
return TEEC_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (memcpy_s(caAuth, sizeof(CaAuthInfo), authInfo.data(), sizeof(CaAuthInfo))) {
|
|
ALOGE("%s: memcpy failed.\n", __func__);
|
|
free(caAuth);
|
|
return ret;
|
|
}
|
|
if ((halXmlPtr.data() == nullptr) ||
|
|
(halXmlPtr.size() != sizeof(TEEC_XmlParameter))) {
|
|
ALOGE("no TEEC_EXT_Set_Native_CAHash for this handle!\n");
|
|
free(caAuth);
|
|
return ret;
|
|
}
|
|
ret = (int32_t)extSendSysHashXmlProxy(reinterpret_cast<const TEEC_XmlParameter *>(halXmlPtr.data()), caAuth);
|
|
free(caAuth);
|
|
return ret;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::secfileSendEvent(int32_t pid,
|
|
const android::hardware::hidl_handle &handle,
|
|
const hidl_string &libPath, const hidl_vec<uint8_t> &halCxtPtr,
|
|
const hidl_vec<uint8_t> &halSessPtr)
|
|
{
|
|
TEEC_ContextHidl *outContext = nullptr;
|
|
FILE *fp = nullptr;
|
|
|
|
(void)halSessPtr;
|
|
(void)CheckAndOpenHandle();
|
|
if (sendSecfileProxy == nullptr || getBnContextProxy == nullptr) {
|
|
ALOGE("missing proxy in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
int tmpCheckStatus = ((halCxtPtr.data() == nullptr) ||
|
|
(halCxtPtr.size() != sizeof(TEEC_Context)) ||
|
|
(!IsValidContext(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()), pid)));
|
|
if (tmpCheckStatus) {
|
|
ALOGE("invalid context!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
outContext = getBnContextProxy(reinterpret_cast<const TEEC_Context *>(halCxtPtr.data()));
|
|
if (outContext == nullptr) {
|
|
ALOGE("no context found in hidl service!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
native_handle_t *tempHandle = nullptr;
|
|
fp = GetFpFromHandle(handle, tempHandle);
|
|
|
|
int32_t ret = sendSecfileProxy(reinterpret_cast<const char *>(libPath.c_str()),
|
|
outContext->fd, fp);
|
|
putBnContextProxy(outContext);
|
|
if (fp != nullptr) {
|
|
fclose(fp);
|
|
fp = nullptr;
|
|
}
|
|
native_handle_delete(tempHandle);
|
|
return ret;
|
|
}
|
|
|
|
void LibteecGlobal::serviceDied(uint64_t cookie, const ::android::wp<::android::hidl::base::V1_0::IBase> &who)
|
|
{
|
|
(void)who;
|
|
ALOGW("%s: teec service died pid=%d\n", __func__, static_cast<int>(cookie));
|
|
|
|
Mutex::Autolock _l(mProcDataLock);
|
|
if (!list_empty(&g_teecHidlProcDataList)) {
|
|
struct listnode *handNode = nullptr;
|
|
struct listnode *tempNode = nullptr;
|
|
list_for_each_safe(handNode, tempNode, &g_teecHidlProcDataList) {
|
|
DaemonProcdata *handProcdata = node_to_item(handNode, DaemonProcdata, procdataHead);
|
|
ALOGW("%s: cleaning pid=%d", __func__, handProcdata->callingPid);
|
|
SendSigToTzdriver(handProcdata->callingPid);
|
|
CleanProcDataForOneCa(handProcdata);
|
|
list_remove(&handProcdata->procdataHead);
|
|
free(handProcdata);
|
|
handProcdata = nullptr;
|
|
}
|
|
}
|
|
|
|
ALOGW("%s: clean done", __func__);
|
|
return;
|
|
}
|
|
|
|
Return<uint32_t> LibteecGlobal::iGetTEEVersionHidl()
|
|
{
|
|
uint32_t version;
|
|
|
|
(void)CheckAndOpenHandle();
|
|
if (getTEEVersionProxy == nullptr) {
|
|
ALOGE("no TEEC_GetTEEVersionHidl for this handle!\n");
|
|
return 0;
|
|
}
|
|
|
|
version = getTEEVersionProxy();
|
|
if (version == 0) {
|
|
ALOGE("fail to get tee version\n");
|
|
}
|
|
return version;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::processCaDied(int32_t pid)
|
|
{
|
|
ALOGW("%s: getCallingPid=%d\n", __func__, pid);
|
|
DaemonProcdata *outProcData = NULL;
|
|
{
|
|
Mutex::Autolock _l(mProcDataLock);
|
|
outProcData = GetProcdataByPid(pid);
|
|
if (outProcData == nullptr) {
|
|
ALOGW("%s: outProcdata[%d] not in the list\n", __func__, pid);
|
|
return Void();
|
|
}
|
|
list_remove(&outProcData->procdataHead);
|
|
}
|
|
SendSigToTzdriver(pid);
|
|
CleanProcDataForOneCa(outProcData);
|
|
|
|
free(outProcData);
|
|
ALOGW("%s: clean done", __func__);
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::CheckInputPidUid(int pid, uid_t uid)
|
|
{
|
|
char *context = nullptr;
|
|
if (uid != AID_ROOT) {
|
|
ALOGE("invalid access client(uid = %u pid = %d) will be rejected\n", uid, pid);
|
|
return TEEC_FAIL;
|
|
}
|
|
if (::getpidcon(pid, &context) < 0) {
|
|
ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", pid);
|
|
return TEEC_FAIL;
|
|
}
|
|
if (strcmp(context, "u:r:system_teecd:s0")) {
|
|
ALOGE("invalid access client(uid = %u pid = %d SELinux %s) will be rejected\n", uid, pid, context);
|
|
::freecon(context);
|
|
return TEEC_FAIL;
|
|
}
|
|
::freecon(context);
|
|
return TEEC_SUCCESS;
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::handleMultiUserMsg(const hidl_vec<uint8_t> &multiUserRecvMsg)
|
|
{
|
|
int pid = android::hardware::IPCThreadState::self()->getCallingPid();
|
|
uid_t uid = android::hardware::IPCThreadState::self()->getCallingUid();
|
|
if (CheckInputPidUid(pid, uid)) {
|
|
ALOGE("%s: checkInputPidUid failed!!\n", __func__);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
int tmpCheckStatus = ((multiUserRecvMsg.data() == nullptr) || (multiUserRecvMsg.size() != sizeof(RecvMsg)));
|
|
if (tmpCheckStatus) {
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
const RecvMsg *multiUserMsg = reinterpret_cast<const RecvMsg *>(multiUserRecvMsg.data());
|
|
uint32_t magic = (unsigned int)multiUserMsg->magic;
|
|
uint32_t status = (unsigned int)multiUserMsg->status;
|
|
int userid = (int)multiUserMsg->userid;
|
|
|
|
tmpCheckStatus = (userid > MU_MSG_USERID_OWNER && userid < MU_MSG_USERID_MAX);
|
|
|
|
/* check magic, and then status, and userid validate value */
|
|
if (magic != MU_MSG_MAGIC) {
|
|
/* do nothing */
|
|
ALOGE("cmd no define to handle\n\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
if (status == MU_MSG_STAT_NEW_USER) {
|
|
return MakeDirAndLinkUser(userid, status, tmpCheckStatus);
|
|
} else if (status == MU_MSG_STAT_RM_USER) {
|
|
return UnlinkUser(userid, status, tmpCheckStatus);
|
|
} else if (status == MU_MSG_STAT_SWITCH_USER) {
|
|
/* switch user */
|
|
ALOGE("switch user cmd do not handle now, status %x.\n", status);
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
/* not in all conditions we can handle, do nothing */
|
|
ALOGE("cmd no define to handle, status is %x.\n", status);
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
static bool CheckSizeStatus(uint32_t shmInfoOffset, uint32_t refSize,
|
|
uint32_t totalSize, uint32_t memSize)
|
|
{
|
|
return ((shmInfoOffset + refSize < shmInfoOffset) || (shmInfoOffset + refSize < refSize) ||
|
|
(shmInfoOffset + refSize > totalSize) || (refSize > memSize));
|
|
}
|
|
|
|
Return<TEEC_Result> LibteecGlobal::DecodeHidlMemory(TEEC_ContextHidl *outContext,
|
|
TEEC_Operation *operation, TEEC_SharedMemory *shm, TEEC_SharedMemoryHidl *shmHidl[],
|
|
uint32_t shmNum, uint8_t *data, size_t memSize)
|
|
{
|
|
uint32_t paramType[PARAM_NUM];
|
|
uint32_t shmInfoOffset = 0;
|
|
uint32_t totalHidlMemSize = memSize;
|
|
TEEC_Operation *tmpOperation = operation;
|
|
|
|
if (shmNum != PARAM_NUM) {
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
for (uint32_t paramCnt = 0; paramCnt < PARAM_NUM; paramCnt++) {
|
|
paramType[paramCnt] = TEEC_PARAM_TYPE_GET(tmpOperation->paramTypes, paramCnt);
|
|
bool tmpCheckStatus1 = ((paramType[paramCnt] == TEEC_MEMREF_TEMP_INPUT) ||
|
|
(paramType[paramCnt] == TEEC_MEMREF_TEMP_OUTPUT) ||
|
|
(paramType[paramCnt] == TEEC_MEMREF_TEMP_INOUT));
|
|
bool tmpCheckStatus2 = ((paramType[paramCnt] == TEEC_MEMREF_WHOLE) ||
|
|
(paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INPUT) ||
|
|
(paramType[paramCnt] == TEEC_MEMREF_PARTIAL_OUTPUT) ||
|
|
(paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INOUT));
|
|
if (tmpCheckStatus1) {
|
|
uint32_t refSize = tmpOperation->params[paramCnt].tmpref.size;
|
|
tmpCheckStatus1 = CheckSizeStatus(shmInfoOffset, refSize, totalHidlMemSize, memSize);
|
|
if (tmpCheckStatus1) {
|
|
ALOGE("%s: temp mem:%x greater than hidl mem:%x:%x:%x\n",
|
|
__func__, refSize, shmInfoOffset, (uint32_t)memSize, totalHidlMemSize);
|
|
return TEEC_FAIL;
|
|
}
|
|
tmpOperation->params[paramCnt].tmpref.buffer = data + shmInfoOffset;
|
|
memSize -= refSize;
|
|
shmInfoOffset += refSize;
|
|
} else if (tmpCheckStatus2) {
|
|
InputPara tmpInputPara;
|
|
tmpInputPara.paraType = paramType[paramCnt];
|
|
tmpInputPara.offset = shmInfoOffset;
|
|
tmpInputPara.memSize = memSize;
|
|
tmpInputPara.totalSize = totalHidlMemSize;
|
|
TEEC_Result retCode = FillShareMemoryBuffer(&(shm[paramCnt]), &(shmHidl[paramCnt]), data,
|
|
&tmpInputPara, outContext, &(tmpOperation->params[paramCnt]));
|
|
if (retCode) {
|
|
return retCode;
|
|
}
|
|
shmInfoOffset = tmpInputPara.offset;
|
|
memSize = tmpInputPara.memSize;
|
|
}
|
|
}
|
|
|
|
return TEEC_SUCCESS;
|
|
}
|
|
|
|
#define STRUCT_SIZE (4 * (sizeof(uint32_t)) + 1 * (sizeof(bool)))
|
|
Return<TEEC_Result> LibteecGlobal::FillShareMemoryBuffer(TEEC_SharedMemory *shareMemBuf,
|
|
TEEC_SharedMemoryHidl **shmHidl, uint8_t *data, InputPara *inputPara,
|
|
TEEC_ContextHidl *outContext, TEEC_Parameter *params)
|
|
{
|
|
uint32_t shmInfoOffset = inputPara->offset;
|
|
uint32_t memSize = inputPara->memSize;
|
|
uint32_t shmOffset = 0;
|
|
uint32_t refSize = STRUCT_SIZE;
|
|
|
|
if (CheckSizeStatus(shmInfoOffset, refSize, inputPara->totalSize, memSize)) {
|
|
goto FILLBUFFEREND;
|
|
}
|
|
|
|
CopyToShareMemory(shareMemBuf, data, shmInfoOffset, &shmOffset);
|
|
memSize -= refSize;
|
|
shmInfoOffset += refSize;
|
|
|
|
refSize = params->memref.size;
|
|
if (inputPara->paraType == TEEC_MEMREF_WHOLE)
|
|
refSize = shareMemBuf->size;
|
|
|
|
if (CheckSizeStatus(shmInfoOffset, refSize, inputPara->totalSize, memSize)) {
|
|
goto FILLBUFFEREND;
|
|
}
|
|
|
|
if (!shareMemBuf->is_allocated) {
|
|
shareMemBuf->buffer = data + shmInfoOffset;
|
|
params->memref.offset = 0;
|
|
} else {
|
|
if (getBnShmByOffsetProxy == nullptr) {
|
|
ALOGE("no GetBnShmAddr in this handle!\n");
|
|
return TEEC_FAIL;
|
|
}
|
|
TEEC_SharedMemoryHidl *shmTemp = getBnShmByOffsetProxy(shmOffset, outContext);
|
|
if (shmTemp == nullptr || shmTemp->buffer == nullptr) {
|
|
ALOGE("%s: no shm buffer found in hidl service!\n", __func__);
|
|
return TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
shareMemBuf->buffer = shmTemp->buffer;
|
|
*shmHidl = shmTemp;
|
|
}
|
|
params->memref.parent = shareMemBuf;
|
|
memSize -= refSize;
|
|
shmInfoOffset += refSize;
|
|
|
|
inputPara->offset = shmInfoOffset;
|
|
inputPara->memSize = memSize;
|
|
return TEEC_SUCCESS;
|
|
|
|
FILLBUFFEREND:
|
|
ALOGE("%s: partial mem:%x greater than hidl mem:%x:%x:%x\n",
|
|
__func__, refSize, shmInfoOffset, memSize, inputPara->totalSize);
|
|
return TEEC_FAIL;
|
|
}
|
|
|
|
void LibteecGlobal::PutAllocShrMem(TEEC_SharedMemoryHidl *shmHidl[], uint32_t shmNum)
|
|
{
|
|
if (putBnShmProxy == nullptr) {
|
|
ALOGE("no PutBnShm in this handle!\n");
|
|
return;
|
|
}
|
|
|
|
uint32_t paramCnt;
|
|
for (paramCnt = 0; paramCnt < shmNum; paramCnt++) {
|
|
if (shmHidl[paramCnt] != nullptr) {
|
|
putBnShmProxy(shmHidl[paramCnt]);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
Return<FILE *> LibteecGlobal::GetFpFromHandle(const android::hardware::hidl_handle &handle,
|
|
native_handle_t *&tempHandle) const
|
|
{
|
|
FILE *fp = nullptr;
|
|
|
|
if (handle == nullptr || handle.getNativeHandle() == nullptr) {
|
|
return fp;
|
|
}
|
|
|
|
tempHandle = native_handle_clone(handle);
|
|
if (tempHandle == nullptr) {
|
|
ALOGE("get fp failed caused by native handle clone failed!\n");
|
|
return fp;
|
|
}
|
|
|
|
int flag = tempHandle->data[1];
|
|
if (flag == 1) {
|
|
int fd = tempHandle->data[0];
|
|
fp = fdopen(fd, "r");
|
|
}
|
|
return fp;
|
|
}
|
|
|
|
Return<void> LibteecGlobal::CleanProcDataForOneCa(DaemonProcdata *procData)
|
|
{
|
|
if ((findAndRemoveBnContextProxy == nullptr) ||
|
|
(putBnContextProxy == nullptr)) {
|
|
ALOGE("missing proxy in this handle!\n");
|
|
return Void();
|
|
}
|
|
|
|
for (int i = 0; i < MAX_CXTCNT_ONECA; i++) {
|
|
if (procData->cxtFd[i] == -1) {
|
|
continue;
|
|
}
|
|
|
|
TEEC_Context context;
|
|
context.fd = procData->cxtFd[i];
|
|
procData->cxtFd[i] = -1;
|
|
|
|
TEEC_ContextHidl *outContext = findAndRemoveBnContextProxy(&context);
|
|
if (outContext == nullptr) {
|
|
ALOGE("%s: no context found in hidl service!\n", __func__);
|
|
continue;
|
|
}
|
|
putBnContextProxy(outContext); /* pair with initialize context */
|
|
}
|
|
|
|
return Void();
|
|
}
|
|
|
|
Return<int32_t> LibteecGlobal::GetOperationFromHidlVec(const hidl_vec<uint8_t> &halOptPtr,
|
|
TEEC_Operation *operation)
|
|
{
|
|
uint32_t paramCnt;
|
|
uint32_t paramType;
|
|
bool tempType = false;
|
|
bool partialType = false;
|
|
|
|
if (memcpy_s(operation, sizeof(TEEC_Operation), halOptPtr.data(), sizeof(TEEC_Operation))) {
|
|
ALOGE("memcpy failed...\n");
|
|
return TEE_HIDL_FAILURE;
|
|
}
|
|
|
|
/* clear the pointer from ca to avoid access to invalid address */
|
|
operation->session = nullptr;
|
|
for (paramCnt = 0; paramCnt < PARAM_NUM; paramCnt++) {
|
|
paramType = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
|
|
tempType = ((paramType == TEEC_MEMREF_TEMP_INPUT) ||
|
|
(paramType == TEEC_MEMREF_TEMP_OUTPUT) ||
|
|
(paramType == TEEC_MEMREF_TEMP_INOUT));
|
|
partialType = ((paramType == TEEC_MEMREF_WHOLE) ||
|
|
(paramType == TEEC_MEMREF_PARTIAL_INPUT) ||
|
|
(paramType == TEEC_MEMREF_PARTIAL_OUTPUT) ||
|
|
(paramType == TEEC_MEMREF_PARTIAL_INOUT));
|
|
if (tempType) {
|
|
operation->params[paramCnt].tmpref.buffer = nullptr;
|
|
} else if (partialType) {
|
|
operation->params[paramCnt].memref.parent = nullptr;
|
|
}
|
|
}
|
|
return TEE_HIDL_SUCCESS;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* fetch method */
|
|
/**************************************************************************/
|
|
using::vendor::huanglong::hardware::libteec::V3_0::ILibteecGlobal;
|
|
ILibteecGlobal *HIDL_FETCH_ILibteecGlobal(const char *)
|
|
{
|
|
ALOGI("------------------ ILibteecGlobal ------------------\n");
|
|
LibteecGlobal *libteecGp = new (std::nothrow) LibteecGlobal();
|
|
if (libteecGp == nullptr) {
|
|
ALOGE("cannot allocate for libteecGp! \n");
|
|
}
|
|
|
|
/* ignore SIGPIPE(when teecd is killed, libteec hidl will not restart). */
|
|
signal(SIGPIPE, SIG_IGN);
|
|
return libteecGp;
|
|
}
|
|
} // namespace implementation
|
|
} // namespace V3_0
|
|
} // namespace libteec
|
|
} // namespace hardware
|
|
} // namespace huanglong
|
|
} // namespace vendor
|