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

/*
* 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, &paraInOut)) {
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, &paraInOut);
/* 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> &notify)
{
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