CPP_SRCS += \
$(SIMDAEMON_SOURCE)/src/ConnectionSession.cpp \
$(SIMDAEMON_SOURCE)/src/Session.cpp \
+$(SIMDAEMON_SOURCE)/src/SecurityChecker.cpp \
$(SIMDAEMON_SOURCE)/src/SimulatorDaemon.cpp \
$(SIMDAEMON_SOURCE)/src/SimulatorDaemonServer.cpp \
$(SIMDAEMON_SOURCE)/src/TAFactory.cpp \
$(SIMDAEMON_SOURCE)/src/TAInstance.cpp \
$(SIMDAEMON_SOURCE)/src/TEEContext.cpp \
-$(SIMDAEMON_SOURCE)/src/ioService.cpp
+$(SIMDAEMON_SOURCE)/src/ioService.cpp \
+$(SIMDAEMON_SOURCE)/src/security.c
OBJS += \
./src/ConnectionSession.o \
./src/TAFactory.o \
./src/TAInstance.o \
./src/TEEContext.o \
-./src/ioService.o
+./src/ioService.o \
+./src/SecurityChecker.o \
+./src/security.o
CPP_DEPS += \
./src/ConnectionSession.d \
./src/TAFactory.d \
./src/TAInstance.d \
./src/TEEContext.d \
-./src/ioService.d
+./src/ioService.d \
+./src/SecurityChecker.d \
+./src/security.d
# Each subdirectory must supply rules for building sources it contributes
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: SecurityChecker.h
+ *
+ * Description: Class to check if client application has access to TEE
+ *
+ * Version: 1.0
+ * Created: 19 June 2017 14:00:03 IST
+ * Revision: Original
+ * Compiler: gcc
+ *
+ * Author: Uladzislau Harbuz, u.harbuz@samsung.com
+ * Organization: Samsung Electronics
+ *
+ * =====================================================================================
+ */
+
+#ifndef SECURITYCHECKER_H
+#define SECURITYCHECKER_H
+
+#include <string>
+#include "ConnectionSession.h"
+#include "log.h"
+#include "security.h"
+
+
+using std::string;
+
+class SecurityChecker{
+private:
+ ConnectionSession* mConnSess;
+
+public:
+
+ SecurityChecker(ConnectionSession* ses);
+
+ static bool clientHasAccessToTa(ConnectionSession *ses, string taName);
+ static bool clientHasCynaraPermission(ConnectionSession *ses, string privelege);
+
+ bool clientHasAccessToTa(string taName);
+ bool clientHasCynaraPermission(string privelege);
+
+ ~SecurityChecker();
+
+};
+#endif /* SECURITYCHECKER_H */
#include "Session.h"
#include "tee_command.h"
#include "IConnectionSession.h"
+#include "ConnectionSession.h"
+#include "SecurityChecker.h"
using namespace std;
/*-----------------------------------------------------------------------------
IConnectionSession* mConnSess;
// ContextID assigned to the instance
uint32_t mContextID;
+ /* Security checker wich can tell us if client has different Tizen's policy permissions*/
+ SecurityChecker mConnSecChecker;
+
/* For TA internal APIs support, dummy Context is created and for recognizing
* the context as dummy isInternal member variable is used
*/
bool isInternal;
- TEEContext(uint32_t contextID, IConnectionSession* connSession);
+ TEEContext(uint32_t contextID, ConnectionSession* connSession);
TEEC_Result initContext(InitContextData* data);
void finContext(FinalizeContextData data);
TEEC_Result openSession(OpenSessionData data);
--- /dev/null
+/*
+ * security.h
+ *
+ * Copyright (C) 2017 Samsung Electronics
+ * Uladzislau Harbuz <u.harbuz@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef SECURITY_H
+#define SECURITY_H
+
+#include <stdbool.h>
+#include <cynara/cynara-creds-socket.h>
+#include <cynara/cynara-client.h>
+#include <cynara/cynara-session.h>
+#include <security-manager/app-runtime.h>
+
+#define MAX_PATH_LENGTH 100
+#define MAX_TA_NAME_LENGTH 36
+
+#define FILE_WAS_FOUND 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* TODO: */
+const char* system_ta_paths[]= {
+ "/usr/lib/optee_armtz/",
+}
+#define N_SYS_TA_PATHS 1
+
+bool ca_has_access_to_ta(int ca_fd, const char* ta_name);
+bool client_has_cynara_permission(int ca_fd, const char* privelege);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* SECURITY_H */
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: SecurityChecker.cpp
+ *
+ * Description: Class to check if client application has access to TEE
+ *
+ * Version: 1.0
+ * Created: 19 June 2017 14:37:03 IST
+ * Revision: Original
+ * Compiler: gcc
+ *
+ * Author: Uladzislau Harbuz, u.harbuz@samsung.com
+ * Organization: Samsung Electronics
+ *
+ * =====================================================================================
+ */
+
+#include "SecurityChecker.h"
+
+
+SecurityChecker(ConnectionSession* ses){
+ mConnSess = ses;
+}
+
+
+bool SecurityChecker::clientHasAccessToTa(ConnectionSession *ses, string taName){
+ return ca_has_access_to_ta(ses->socket().native(), taName.c_str());
+}
+
+
+bool SecurityChecker::clientHasCynaraPermission(ConnectionSession *ses, string privelege){
+ return client_has_cynara_permission(ses->socket().native(), privelege.c_str());
+}
+
+
+bool SecurityChecker::clientHasCynaraPermission(string privelege){
+ return SecurityChecker::clientHasCynaraPermission(mConnSess, privelege);
+}
+
+
+bool SecurityChecker::clientHasAccessToTa(string taName){
+ return SecurityChecker::clientHasAccessToTa(mConnSess, taName);
+}
+
+
+~SecurityChecker(){
+}
string TAUUID = TABin->getUUIDAsString(data.uuid);
string argvPort = TABin->getPort(TAUUID);
+ if(!mContext->nConnSecChecker.clientHasAccessToTa(TAUUID)){
+ LOGE(SIM_DAEMON, "Client has no permission for access TA: %s ", TAUUID.c_str());
+ return TEEC_ERROR_ACCESS_DENIED;
+ }
+
if (argvPort != "") {
pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock);
multimap<string, TAInstancePtr>::iterator itr;
* Include files
*-----------------------------------------------------------------------------*/
#include "SimulatorDaemonServer.h"
+#include "SecurityChecker.h"
/*-----------------------------------------------------------------------------
* Member functions
ConnectionSession::session_ptr new_session = ConnectionSession::create(
acceptor.get_io_service());
+
acceptor.async_accept(new_session->socket(),
boost::bind(&SimulatorDaemonServer::handleAccept, this, new_session,
boost::asio::placeholders::error));
void SimulatorDaemonServer::handleAccept(
ConnectionSession::session_ptr new_session,
const boost::system::error_code& error) {
+
+ const string privelege("http://tizen.org/privilege/account.read");
LOGD(SIM_DAEMON, "Entry");
+ if (!SecurityChecker::clientHasCynaraPermission(new_session.get(), privelege)){
+ LOGE("Client has no permission to use TEE");
+ return;
+ }
+
if (!error) {
new_session->start();
}
* @param contextID ID for Context reference
* @param connSession ConnectionSession instance associated with the context
*/
-TEEContext::TEEContext(uint32_t contextID, IConnectionSession* connSession) {
+TEEContext::TEEContext(uint32_t contextID, ConnectionSession* connSession)
+ :mConnSecChecker(connSession)
+{
LOGD(SIM_DAEMON, "ContextID: %d", contextID);
--- /dev/null
+/*
+ * security.c
+ *
+ * Copyright (C) 2017 Samsung Electronics
+ * Uladzislau Harbuz <u.harbuz@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <teec_trace.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <ftw.h>
+#include "security.h"
+
+/* This variable is for nftw searching of ta */
+static const char* g_ta_name = NULL;
+
+
+static bool file_exists(const char* fname){
+ struct stat st;
+ return stat(fname, &st) == 0;
+}
+
+
+static bool get_ca_full_path_from_socket(int fd, char* path){
+ /* How to get full path from pkgid? */
+ pid_t ca_pid = -1;
+ cynara *cynara = NULL;
+ int ret = -1;
+
+ ret = cynara_initialize(&cynara, NULL);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Cynara initialization failed with error code %d", ret);
+ return false;
+ }
+
+ ret = cynara_creds_socket_get_pid(ca_fd, &ca_pid);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Couldn't get pid of the client. Error code: %d", ret);
+ cynara_finish(cynara);
+ return false;
+ }
+
+ char ca_path[MAX_PATH_LENGTH] = {0};
+ snprintf(ca_path, MAX_PATH_LENGTH, "/proc/%d/exe", ca_pid);
+ ret = readlink(ca_path, path, MAX_PATH_LENGTH);
+
+ if(ret == -1){
+ EMSG("readlink() failed");
+ cynara_finish(cynara);
+ return false;
+ }
+
+ cynara_finish(cynara);
+
+ return true;
+}
+
+
+static int cmp_ta_name(const char *fpath, const struct stat *sb,
+ int tflag, struct FTW *ftwbuf)
+{
+ if(tflag == FTW_D){
+ char ta_full_path[MAX_PATH_LENGTH] = {0};
+ snprintf(ta_full_name, MAX_PATH_LENGTH, "%s/%s", fpath, g_ta_name);
+
+ if(file_exists(ta_full_path)){
+ return FILE_WAS_FOUND;
+ }
+ }
+
+ return 0;
+}
+
+
+bool ca_has_access_to_ta(int ca_fd, const char* ta_name){
+ int ret;
+ g_ta_name = ta_name;
+
+ char *pkg_id_ca;
+
+ ret = security_manager_identify_app_from_socket(ca_fd, &pkg_id_ca, NULL);
+ if(ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT){
+ DMSG("Owner of socket has no pkgid");
+
+ char ta_full_path[MAX_PATH_LENGTH] = {0};
+
+ /* Check if any of system ta directories contains our ta */
+ for(int i = 0; i < N_SYS_TA_PATHS; ++i){
+ strcpy(ta_full_path, system_ta_paths[i]);
+ strcat(ta_full_path, ta_name);
+
+ if(file_exists(ta_full_name)){
+ return true;
+ }
+
+ memset(ta_full_path, 0, MAX_PATH_LENGTH);
+ }
+
+ return false;
+ }
+
+ if(ret != SECURITY_MANAGER_SUCCESS){
+ EMSG("security_manager_identify_app_from_cynara_client() failed with CA");
+ return false;
+ }
+
+ char ca_pkg_path[MAX_PATH_LENGTH];
+ if(!get_full_ca_path_from_socket(ca_fd, ca_pkg_path)){
+ EMSG("Error while loading client's path");
+ free(pkg_id_ca);
+ return false;
+ }
+
+ ret = nftw(ca_pkg_path, cmp_ta_name, MAX_OPENED_FD, 0);
+ if(ret == FILE_WAS_FOUND){
+ free(pkg_id_ca);
+ return true;
+ }
+
+ free(pkg_id_ca);
+ return false;
+}
+
+
+bool client_has_cynara_permission(int ca_fd, const char *privelege){
+ cynara *cynara = NULL;
+ int ret = -1;
+ char *user;
+ char *session = NULL;
+ char *label;
+ pid_t ca_pid = -1;
+
+ ret = cynara_initialize(&cynara, NULL);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Cynara initialization failed with error code %d", ret);
+ return false;
+ }
+
+ ret = cynara_creds_socket_get_client(ca_fd, CLIENT_METHOD_SMACK, &label);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Couldn't get smack label of the client. Error code: %d", ret);
+ goto exit_error3;
+ }
+
+ ret = cynara_creds_socket_get_pid(ca_fd, &ca_pid);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Couldn't get pid of the client. Error code: %d", ret);
+ goto exit_error2;
+ }
+
+ session = cynara_session_from_pid(ca_pid);
+ if(!session){
+ EMSG("Couldn't get client's cynara session.");
+ goto exit_error2;
+ }
+
+ ret = cynara_creds_socket_get_user(ca_fd, CLIENT_METHOD_SMACK, &user);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Couldn't get user. Error code: %d", ret);
+ goto exit_error1;
+ }
+
+ ret = cynara_check(cynara, label, session, user, privelege);
+ if(ret == CYNARA_API_ACCESS_DENIED){
+ EMSG("Cynara access denied.");
+ goto exit_error0;
+ }
+ else if(ret != CYNARA_API_ACCESS_ALLOWED){
+ EMSG("Error during cynara_check(). Error code: %d", ret);
+ goto exit_error0;
+ }
+
+
+ ret = cynara_finish(cynara);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Cynara finish failed with error code %d", ret);
+ }
+
+ free(session);
+ free(label);
+ free(user);
+
+ return true;
+
+
+exit_error0:
+ free(user);
+
+exit_error1:
+ free(session);
+
+exit_error2:
+ free(label);
+
+exit_error3:
+ ret = cynara_finish(cynara);
+ if(ret != CYNARA_API_SUCCESS){
+ EMSG("Cynara finish failed with error code %d", ret);
+ }
+
+ return false;
+}