diff options
Diffstat (limited to 'security/tee_client_api')
-rw-r--r-- | security/tee_client_api/Android.mk | 25 | ||||
-rw-r--r-- | security/tee_client_api/s_version.h | 113 | ||||
-rw-r--r-- | security/tee_client_api/schannel6_logins.h | 97 | ||||
-rw-r--r-- | security/tee_client_api/schannel6_protocol.h | 425 | ||||
-rw-r--r-- | security/tee_client_api/tee_client_api_linux_driver.c | 929 |
5 files changed, 1589 insertions, 0 deletions
diff --git a/security/tee_client_api/Android.mk b/security/tee_client_api/Android.mk new file mode 100644 index 0000000..bfd92f4 --- /dev/null +++ b/security/tee_client_api/Android.mk @@ -0,0 +1,25 @@ +ifeq ($(TARGET_BOARD_PLATFORM),omap4) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm + +LOCAL_SRC_FILES:= \ + tee_client_api_linux_driver.c + +LOCAL_CFLAGS += -DLINUX +LOCAL_CFLAGS += -D__ANDROID32__ + +ifdef S_VERSION_BUILD +LOCAL_CFLAGS += -DS_VERSION_BUILD=$(S_VERSION_BUILD) +endif + +LOCAL_CFLAGS += -I $(LOCAL_PATH)/../tf_sdk/include/ + +LOCAL_MODULE:= libtee_client_api_driver +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/security/tee_client_api/s_version.h b/security/tee_client_api/s_version.h new file mode 100644 index 0000000..d112ea0 --- /dev/null +++ b/security/tee_client_api/s_version.h @@ -0,0 +1,113 @@ +/** + * Copyright(c) 2011 Trusted Logic. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Trusted Logic nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __S_VERSION_H__ +#define __S_VERSION_H__ + +/* + * Usage: define S_VERSION_BUILD on the compiler's command line. + * + * Then set: + * - S_VERSION_OS + * - S_VERSION_PLATFORM + * - S_VERSION_MAIN + * - S_VERSION_ENG is optional + * - S_VERSION_PATCH is optional + * - S_VERSION_BUILD = 0 if S_VERSION_BUILD not defined or empty + */ +#if defined(WIN32) +#define S_VERSION_OS "W" /* "W" for Windows PC (XP, Vista…) */ +#define S_VERSION_PLATFORM "X" /* "X" for ix86 PC simulators */ +#elif defined(__ANDROID32__) +#define S_VERSION_OS "A" /* "A" for Android */ +#define S_VERSION_PLATFORM "G" /* "G" for 4430 */ +#elif defined(LINUX) +#define S_VERSION_OS "L" /* "L" for Linux */ +#define S_VERSION_PLATFORM "X" /* "X" for ix86 PC simulators */ +#else +#define S_VERSION_OS "X" /* "X" for Secure-World */ +#define S_VERSION_PLATFORM "G" /* "G" for 4430 */ +#endif + +/* + * This version number must be updated for each new release + */ +#define S_VERSION_MAIN "01.04" +#define S_VERSION_RESOURCE 1,4,0,S_VERSION_BUILD + +/* +* If this is a patch or engineering version use the following +* defines to set the version number. Else set these values to 0. +*/ +#define S_VERSION_PATCH 11 +#define S_VERSION_ENG 0 + +#ifdef S_VERSION_BUILD +/* TRICK: detect if S_VERSION is defined but empty */ +#if 0 == S_VERSION_BUILD-0 +#undef S_VERSION_BUILD +#define S_VERSION_BUILD 0 +#endif +#else +/* S_VERSION_BUILD is not defined */ +#define S_VERSION_BUILD 0 +#endif + +#define __STRINGIFY(X) #X +#define __STRINGIFY2(X) __STRINGIFY(X) + +#if S_VERSION_ENG != 0 +#define _S_VERSION_ENG "e" __STRINGIFY2(S_VERSION_ENG) +#else +#define _S_VERSION_ENG "" +#endif + +#if S_VERSION_PATCH != 0 +#define _S_VERSION_PATCH "p" __STRINGIFY2(S_VERSION_PATCH) +#else +#define _S_VERSION_PATCH "" +#endif + +#if !defined(NDEBUG) || defined(_DEBUG) +#define S_VERSION_VARIANT "D " +#else +#define S_VERSION_VARIANT " " +#endif + +#define S_VERSION_STRING \ + "SMC" \ + S_VERSION_OS \ + S_VERSION_PLATFORM \ + S_VERSION_MAIN \ + _S_VERSION_PATCH \ + _S_VERSION_ENG \ + "." __STRINGIFY2(S_VERSION_BUILD) " " \ + S_VERSION_VARIANT + +#endif /* __S_VERSION_H__ */ diff --git a/security/tee_client_api/schannel6_logins.h b/security/tee_client_api/schannel6_logins.h new file mode 100644 index 0000000..ca0cddd --- /dev/null +++ b/security/tee_client_api/schannel6_logins.h @@ -0,0 +1,97 @@ +/** + * Copyright(c) 2011 Trusted Logic. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Trusted Logic nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCHANNEL6_LOGINS_H__ +#define __SCHANNEL6_LOGINS_H__ + +#define SCX_LOGIN_PUBLIC 0x00000000 +#define SCX_LOGIN_USER 0x00000001 +#define SCX_LOGIN_GROUP 0x00000002 +#define SCX_LOGIN_APPLICATION 0x00000004 +#define SCX_LOGIN_APPLICATION_USER 0x00000005 +#define SCX_LOGIN_APPLICATION_GROUP 0x00000006 +#define SCX_LOGIN_AUTHENTICATION 0x80000000 +#define SCX_LOGIN_PRIVILEGED 0x80000002 + +/* Login variants */ + +#define SCX_LOGIN_VARIANT(mainType, os, variant) \ + ((mainType) | (1 << 27) | ((os) << 16) | ((variant) << 8)) + +#define SCX_LOGIN_GET_MAIN_TYPE(type) ((type) & ~SCX_LOGIN_VARIANT(0, 0xFF, 0xFF)) + +#define SCX_LOGIN_OS_ANY 0x00 +#define SCX_LOGIN_OS_LINUX 0x01 +#define SCX_LOGIN_OS_WINMOBILE 0x02 +#define SCX_LOGIN_OS_SYMBIAN 0x03 +#define SCX_LOGIN_OS_ANDROID 0x04 + +/* OS-independent variants */ +#define SCX_LOGIN_USER_NONE SCX_LOGIN_VARIANT(SCX_LOGIN_USER, SCX_LOGIN_OS_ANY, 0xFF) +#define SCX_LOGIN_GROUP_NONE SCX_LOGIN_VARIANT(SCX_LOGIN_GROUP, SCX_LOGIN_OS_ANY, 0xFF) +#define SCX_LOGIN_APPLICATION_USER_NONE \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_USER, SCX_LOGIN_OS_ANY, 0xFF) +#define SCX_LOGIN_AUTHENTICATION_BINARY_SHA1_HASH \ + SCX_LOGIN_VARIANT(SCX_LOGIN_AUTHENTICATION, SCX_LOGIN_OS_ANY, 0x01) +#define SCX_LOGIN_PRIVILEGED_KERNEL \ + SCX_LOGIN_VARIANT(SCX_LOGIN_PRIVILEGED, SCX_LOGIN_OS_ANY, 0x01) + +/* Linux variants */ +#define SCX_LOGIN_USER_LINUX_EUID SCX_LOGIN_VARIANT(SCX_LOGIN_USER, SCX_LOGIN_OS_LINUX, 0x01) +#define SCX_LOGIN_GROUP_LINUX_GID SCX_LOGIN_VARIANT(SCX_LOGIN_GROUP, SCX_LOGIN_OS_LINUX, 0x01) +#define SCX_LOGIN_APPLICATION_LINUX_PATH_SHA1_HASH \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION, SCX_LOGIN_OS_LINUX, 0x01) +#define SCX_LOGIN_APPLICATION_USER_LINUX_PATH_EUID_SHA1_HASH \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_USER, SCX_LOGIN_OS_LINUX, 0x01) +#define SCX_LOGIN_APPLICATION_GROUP_LINUX_PATH_GID_SHA1_HASH \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_GROUP, SCX_LOGIN_OS_LINUX, 0x01) + +/* Android variants */ +#define SCX_LOGIN_USER_ANDROID_EUID SCX_LOGIN_VARIANT(SCX_LOGIN_USER, SCX_LOGIN_OS_ANDROID, 0x01) +#define SCX_LOGIN_GROUP_ANDROID_GID SCX_LOGIN_VARIANT(SCX_LOGIN_GROUP, SCX_LOGIN_OS_ANDROID, 0x01) +#define SCX_LOGIN_APPLICATION_ANDROID_UID \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION, SCX_LOGIN_OS_ANDROID, 0x01) +#define SCX_LOGIN_APPLICATION_USER_ANDROID_UID_EUID \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_USER, SCX_LOGIN_OS_ANDROID, 0x01) +#define SCX_LOGIN_APPLICATION_GROUP_ANDROID_UID_GID \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_GROUP, SCX_LOGIN_OS_ANDROID, 0x01) + +/* Symbian variants */ +#define SCX_LOGIN_APPLICATION_SYMBIAN_UIDS \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION, SCX_LOGIN_OS_SYMBIAN, 0x01) +#define SCX_LOGIN_APPLICATION_USER_SYMBIAN_UIDS \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_USER, SCX_LOGIN_OS_SYMBIAN, 0x01) +#define SCX_LOGIN_APPLICATION_GROUP_SYMBIAN_UIDS \ + SCX_LOGIN_VARIANT(SCX_LOGIN_APPLICATION_GROUP, SCX_LOGIN_OS_SYMBIAN, 0x01) +#define SCX_LOGIN_AUTHENTICATION_SYMBIAN_UIDS \ + SCX_LOGIN_VARIANT(SCX_LOGIN_AUTHENTICATION, SCX_LOGIN_OS_SYMBIAN, 0x01) + + +#endif /* __SCHANNEL6_LOGINS_H__ */ diff --git a/security/tee_client_api/schannel6_protocol.h b/security/tee_client_api/schannel6_protocol.h new file mode 100644 index 0000000..66ed12c --- /dev/null +++ b/security/tee_client_api/schannel6_protocol.h @@ -0,0 +1,425 @@ +/** + * Copyright(c) 2011 Trusted Logic. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Trusted Logic nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCHANNEL6_PROTOCOL_H__ +#define __SCHANNEL6_PROTOCOL_H__ + +#include "s_type.h" + +/** + * This header file defines some structures needed for the secure channel + * protocol. See your Product Reference Manual for a specification of the + * SChannel protocol. + */ +// jroux to do : remove +#undef SMC_PROTOCOL_VERSION +#define SMC_PROTOCOL_VERSION 0x06000000 + +/** + * Time representation. + */ +typedef uint64_t SCTIME; + +#define SCTIME_IMMEDIATE ((uint64_t) 0x0000000000000000ULL) +#define SCTIME_INFINITE ((uint64_t) 0xFFFFFFFFFFFFFFFFULL) + +/* + * Message types + */ +#define SCX_CREATE_DEVICE_CONTEXT 0x02 +#define SCX_DESTROY_DEVICE_CONTEXT 0xFD +#define SCX_REGISTER_SHARED_MEMORY 0xF7 +#define SCX_RELEASE_SHARED_MEMORY 0xF9 +#define SCX_OPEN_CLIENT_SESSION 0xF0 +#define SCX_CLOSE_CLIENT_SESSION 0xF2 +#define SCX_INVOKE_CLIENT_COMMAND 0xF5 +#define SCX_CANCEL_CLIENT_OPERATION 0xF4 +#define SCX_MANAGEMENT 0xFE + +/* + * Shared mem flags + */ +#define SCX_SHARED_MEM_FLAG_INPUT 1 +#define SCX_SHARED_MEM_FLAG_OUTPUT 2 +#define SCX_SHARED_MEM_FLAG_INOUT 3 + +/* + * Parameter types + */ +#define SCX_PARAM_TYPE_NONE 0x0 +#define SCX_PARAM_TYPE_VALUE_INPUT 0x1 +#define SCX_PARAM_TYPE_VALUE_OUTPUT 0x2 +#define SCX_PARAM_TYPE_VALUE_INOUT 0x3 +#define SCX_PARAM_TYPE_MEMREF_TEMP_INPUT 0x5 +#define SCX_PARAM_TYPE_MEMREF_TEMP_OUTPUT 0x6 +#define SCX_PARAM_TYPE_MEMREF_TEMP_INOUT 0x7 +#define SCX_PARAM_TYPE_MEMREF_INPUT 0xD +#define SCX_PARAM_TYPE_MEMREF_OUTPUT 0xE +#define SCX_PARAM_TYPE_MEMREF_INOUT 0xF + +#define SCX_PARAM_TYPE_INPUT_FLAG 0x1 +#define SCX_PARAM_TYPE_OUTPUT_FLAG 0x2 +#define SCX_PARAM_TYPE_MEMREF_FLAG 0x4 +#define SCX_PARAM_TYPE_REGISTERED_MEMREF_FLAG 0x8 + +#define SCX_PARAM_TYPE_IS_TMPREF(nParamType) (((nParamType) & (SCX_PARAM_TYPE_MEMREF_FLAG | SCX_PARAM_TYPE_REGISTERED_MEMREF_FLAG)) == SCX_PARAM_TYPE_MEMREF_FLAG) + +#define SCX_MAKE_PARAM_TYPES(t0, t1, t2, t3) ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12)) +#define SCX_GET_PARAM_TYPE(t, i) (((t) >> (4*i)) & 0xF) + +/* + * return origins + */ +#define SCX_ORIGIN_COMMS 2 +#define SCX_ORIGIN_TEE 3 +#define SCX_ORIGIN_TRUSTED_APP 4 + +/* + * Login types + */ +#include "schannel6_logins.h" + +/** + * Command parameters. + */ +typedef struct +{ + uint32_t a; + uint32_t b; +}SCHANNEL6_COMMAND_PARAM_VALUE; + +typedef struct +{ + uint32_t nDescriptor; + uint32_t nSize; + uint32_t nOffset; /* Socket: 4 weak bits of the address (for alignement checks) */ + +}SCHANNEL6_COMMAND_PARAM_TEMP_MEMREF; + +typedef struct +{ + S_HANDLE hBlock; + uint32_t nSize; + uint32_t nOffset; + +}SCHANNEL6_COMMAND_PARAM_MEMREF; + +typedef union +{ + SCHANNEL6_COMMAND_PARAM_VALUE sValue; + SCHANNEL6_COMMAND_PARAM_TEMP_MEMREF sTempMemref; + SCHANNEL6_COMMAND_PARAM_MEMREF sMemref; + +} SCHANNEL6_COMMAND_PARAM; + +typedef struct +{ + uint32_t a; + uint32_t b; +} SCHANNEL6_ANSWER_PARAM_VALUE; + +typedef struct +{ + uint32_t _ignored; + uint32_t nSize; +} SCHANNEL6_ANSWER_PARAM_SIZE; + +typedef union +{ + SCHANNEL6_ANSWER_PARAM_SIZE sSize; + SCHANNEL6_ANSWER_PARAM_VALUE sValue; +} SCHANNEL6_ANSWER_PARAM; + +/** + * Command messages. + */ + typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ +}SCHANNEL6_COMMAND_HEADER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + uint32_t nDeviceContextID; /* an opaque Normal World identifier for the device context */ +}SCHANNEL6_CREATE_DEVICE_CONTEXT_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nParamTypes; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + S_HANDLE hClientSession; + uint64_t sTimeout; + uint32_t nCancellationID; + uint32_t nClientCommandIdentifier; + SCHANNEL6_COMMAND_PARAM sParams[4]; +}SCHANNEL6_INVOKE_CLIENT_COMMAND_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nParamTypes; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + uint32_t nCancellationID; + SCTIME sTimeout; + S_UUID sDestinationUUID; + SCHANNEL6_COMMAND_PARAM sParams[4]; + uint32_t nLoginType; + uint8_t sLoginData[20]; /* Size depends on the login type. */ + +}SCHANNEL6_OPEN_CLIENT_SESSION_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMemoryFlags; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + uint32_t nBlockID; + uint32_t nSharedMemSize; + uint32_t nSharedMemStartOffset; + uint32_t nSharedMemDescriptors[8]; + +}SCHANNEL6_REGISTER_SHARED_MEMORY_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + S_HANDLE hBlock; + +}SCHANNEL6_RELEASE_SHARED_MEMORY_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + S_HANDLE hClientSession; + uint32_t nCancellationID; + +}SCHANNEL6_CANCEL_CLIENT_OPERATION_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + S_HANDLE hClientSession; + +}SCHANNEL6_CLOSE_CLIENT_SESSION_COMMAND; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + S_HANDLE hDeviceContext; + +}SCHANNEL6_DESTROY_DEVICE_CONTEXT_COMMAND; + +#define SCHANNEL6_MANAGEMENT_COMMAND_HIBERNATE 1 +#define SCHANNEL6_MANAGEMENT_COMMAND_SHUTDOWN 2 +#define SCHANNEL6_MANAGEMENT_COMMAND_PREPARE_FOR_CORE_OFF 3 +#define SCHANNEL6_MANAGEMENT_COMMAND_RESUME_FROM_CORE_OFF 4 + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nCommand; + uint32_t nOperationID; /* an opaque Normal World identifier for the operation */ + uint32_t nW3BSize; + uint32_t nW3BStartOffset; +#ifdef SCHANNEL_TRUSTZONE + uint32_t nSharedMemDescriptors[128]; +#endif +}SCHANNEL6_MANAGEMENT_COMMAND; + +typedef union +{ + SCHANNEL6_COMMAND_HEADER sHeader; + SCHANNEL6_CREATE_DEVICE_CONTEXT_COMMAND sCreateDeviceContext; + SCHANNEL6_DESTROY_DEVICE_CONTEXT_COMMAND sDestroyDeviceContext; + SCHANNEL6_OPEN_CLIENT_SESSION_COMMAND sOpenClientSession; + SCHANNEL6_CLOSE_CLIENT_SESSION_COMMAND sCloseClientSession; + SCHANNEL6_REGISTER_SHARED_MEMORY_COMMAND sRegisterSharedMemory; + SCHANNEL6_RELEASE_SHARED_MEMORY_COMMAND sReleaseSharedMemory; + SCHANNEL6_INVOKE_CLIENT_COMMAND_COMMAND sInvokeClientCommand; + SCHANNEL6_CANCEL_CLIENT_OPERATION_COMMAND sCancelClientOperation; + SCHANNEL6_MANAGEMENT_COMMAND sManagement; + +}SCHANNEL6_COMMAND; + +/** + * Answer messages. + */ +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo; + uint32_t nOperationID; + uint32_t nErrorCode; +}SCHANNEL6_ANSWER_HEADER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; + S_HANDLE hDeviceContext; +}SCHANNEL6_CREATE_DEVICE_CONTEXT_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint8_t nReturnOrigin; + uint8_t __nReserved; + uint32_t nOperationID; + uint32_t nErrorCode; + SCHANNEL6_ANSWER_PARAM sAnswers[4]; + +}SCHANNEL6_INVOKE_CLIENT_COMMAND_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint8_t nReturnOrigin; + uint8_t __nReserved; + uint32_t nOperationID; + uint32_t nErrorCode; + S_HANDLE hClientSession; + SCHANNEL6_ANSWER_PARAM sAnswers[4]; +}SCHANNEL6_OPEN_CLIENT_SESSION_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; +}SCHANNEL6_CLOSE_CLIENT_SESSION_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; + S_HANDLE hBlock; + +}SCHANNEL6_REGISTER_SHARED_MEMORY_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; + uint32_t nBlockID; + +}SCHANNEL6_RELEASE_SHARED_MEMORY_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; + uint32_t nDeviceContextID; + +}SCHANNEL6_DESTROY_DEVICE_CONTEXT_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; + +}SCHANNEL6_CANCEL_CLIENT_OPERATION_ANSWER; + +typedef struct +{ + uint8_t nMessageSize; + uint8_t nMessageType; + uint16_t nMessageInfo_RFU; + uint32_t nOperationID; + uint32_t nErrorCode; + +}SCHANNEL6_MANAGEMENT_ANSWER; + +typedef union +{ + SCHANNEL6_ANSWER_HEADER sHeader; + SCHANNEL6_CREATE_DEVICE_CONTEXT_ANSWER sCreateDeviceContext; + SCHANNEL6_OPEN_CLIENT_SESSION_ANSWER sOpenClientSession; + SCHANNEL6_REGISTER_SHARED_MEMORY_ANSWER sRegisterSharedMemory; + SCHANNEL6_RELEASE_SHARED_MEMORY_ANSWER sReleaseSharedMemory; + SCHANNEL6_INVOKE_CLIENT_COMMAND_ANSWER sInvokeClientCommand; + SCHANNEL6_DESTROY_DEVICE_CONTEXT_ANSWER sDestroyDeviceContext; + SCHANNEL6_CANCEL_CLIENT_OPERATION_ANSWER sCancelClientOperation; + SCHANNEL6_CLOSE_CLIENT_SESSION_ANSWER sCloseClientSession; + SCHANNEL6_MANAGEMENT_ANSWER sManagement; + +}SCHANNEL6_ANSWER; + + +#endif /* __SCHANNEL6_PROTOCOL_H__ */ diff --git a/security/tee_client_api/tee_client_api_linux_driver.c b/security/tee_client_api/tee_client_api_linux_driver.c new file mode 100644 index 0000000..08a8210 --- /dev/null +++ b/security/tee_client_api/tee_client_api_linux_driver.c @@ -0,0 +1,929 @@ +/** + * Copyright(c) 2011 Trusted Logic. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Trusted Logic nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tee_client_api.h" +#include "schannel6_protocol.h" +#include "s_error.h" +#include "s_version.h" + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdarg.h> +#include <assert.h> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <linux/limits.h> +#include <time.h> +#include <sys/time.h> + +/* + * SCX_VERSION_INFORMATION_BUFFER structure description + * Description of the sVersionBuffer handed over from user space to kernel space + * This field is filled after an IOCTL call and handed back to user space + */ +typedef struct +{ + uint8_t sDriverDescription[65]; + uint8_t sSecureWorldDescription[65]; +} SCX_VERSION_INFORMATION_BUFFER; + + +/* The IOCTLs to the driver */ +#define IOCTL_SCX_GET_VERSION \ + _IO('z', 0) + +#define IOCTL_SCX_EXCHANGE \ + _IOWR('z', 1, SCHANNEL6_COMMAND) + +#define IOCTL_SCX_GET_DESCRIPTION \ + _IOR('z', 2, SCX_VERSION_INFORMATION_BUFFER) + + +/* Expected driver interface version. */ +#define SM_DRIVER_VERSION 0x04000000 + +#define SCX_DEFAULT_DEVICE_NAME "tf_driver" + +#define SCX_PARAM_TYPE_GET(nParamTypes, i) (((nParamTypes) >> (4*i)) & 0xF) + +#define VAR_NOT_USED(variable) do{(void)(variable);}while(0); + +#define SIZE_4KB 0x1000 +#define SIZE_1MB 0x100000 + +/* ------------------------------------------------------------------------ */ +/* UTILS */ +/* ------------------------------------------------------------------------ */ +#ifdef NDEBUG +/* Compile-out the traces */ +#define TRACE_ERROR(...) +#define TRACE_WARNING(...) +#define TRACE_INFO(...) +#else +static void TRACE_ERROR(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + fprintf(stderr, "TRACE: ERROR: "); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void TRACE_WARNING(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + fprintf(stderr, "TRACE: WARNING: "); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void TRACE_INFO(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + fprintf(stderr, "TRACE: "); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); +} +#endif /* NDEBUG */ + + +/* + * ==================================================== + * Internal functions + * ===================================================== +*/ + +static void scxYield(void) +{ + sleep(0); +} + +/* ------------------------------------------------------------------------ */ + + +/* + * Exchange a message with the Secure World + * by calling the ioctl command of the linux driver + * + * @param pContext + * @param pCommand a SChannel command message that must have been filled except for the operation parameters + * @param pAnswer a placeholder for the SChannel answer + * @param pOperation a TEEC_Operation structure that contains the operation parameters (and types) + * and is updated with the SChannel answer data as appropriate. This parameter is + * used only for the open and invoke operations + */ +static TEEC_Result scxExchangeMessage( + IN TEEC_Context* pContext, + IN SCHANNEL6_COMMAND* pCommand, + OUT SCHANNEL6_ANSWER* pAnswer, + IN TEEC_Operation* pOperation) +{ + TEEC_Result nResult = TEEC_SUCCESS; + + TRACE_INFO("scxExchangeMessage[0x%X]\n",pContext); + + if (pOperation != NULL) + { + /* Determine message parameters from operation parameters */ + uint32_t i; + SCHANNEL6_COMMAND_PARAM* pSCXParams; + + /* Note that nParamType is at the same position in an open and an invoke message */ + pCommand->sHeader.nMessageInfo = pOperation->paramTypes; + + if (pCommand->sHeader.nMessageType == SCX_OPEN_CLIENT_SESSION) + { + pSCXParams = pCommand->sOpenClientSession.sParams; + } + else + { + /* An invoke-command */ + pSCXParams = pCommand->sInvokeClientCommand.sParams; + } + + for (i = 0; i < 4; i++) + { + uint32_t nTEECParamType = SCX_PARAM_TYPE_GET(pOperation->paramTypes, i); + TEEC_Parameter* pTEECParam = &pOperation->params[i]; + SCHANNEL6_COMMAND_PARAM* pSCXParam = &pSCXParams[i]; + + if (nTEECParamType & SCX_PARAM_TYPE_MEMREF_FLAG) + { + if (nTEECParamType & SCX_PARAM_TYPE_REGISTERED_MEMREF_FLAG) + { + /* A registered memref */ + pSCXParam->sMemref.hBlock = pTEECParam->memref.parent->imp._hBlock; + if (nTEECParamType == TEEC_MEMREF_WHOLE) + { + /* A memref on the whole shared memory */ + /* Set the direction from the shared memory flags */ + pCommand->sInvokeClientCommand.nParamTypes |= + (pTEECParam->memref.parent->flags & (SCX_PARAM_TYPE_INPUT_FLAG | SCX_PARAM_TYPE_OUTPUT_FLAG)) + << (4*i); + pSCXParam->sMemref.nSize = pTEECParam->memref.parent->size; + pSCXParam->sMemref.nOffset = 0; + } + else + { + /* A partial memref */ + pSCXParam->sMemref.nSize = pTEECParam->memref.size; + pSCXParam->sMemref.nOffset = pTEECParam->memref.offset; + } + } + else + { + /* A temporary memref */ + /* Set nOffset to the address in the client. This allows the server + to allocate a block with the same alignment and also to + detect a NULL tmpref. + */ + pSCXParam->sTempMemref.nOffset = (uint32_t)pTEECParam->tmpref.buffer; + pSCXParam->sTempMemref.nDescriptor = (uint32_t)pTEECParam->tmpref.buffer; + pSCXParam->sTempMemref.nSize = pTEECParam->tmpref.size; + } + } + else if (nTEECParamType & SCX_PARAM_TYPE_INPUT_FLAG) + { + /* An input value */ + pSCXParam->sValue.a = pTEECParam->value.a; + pSCXParam->sValue.b = pTEECParam->value.b; + } + } + } + + pCommand->sHeader.nOperationID = (uint32_t)pAnswer; + + nResult = ioctl((S_HANDLE)pContext->imp._hConnection, IOCTL_SCX_EXCHANGE, pCommand); + if (nResult != S_SUCCESS) + { + TRACE_INFO("scxExchangeMessage[0x%X]: Ioctl returned error: 0x%x (0x%x - %d)\n",pContext,nResult,errno,errno); + switch(errno) + { + case ENOMEM: + nResult=TEEC_ERROR_OUT_OF_MEMORY; + break; + case EACCES: + nResult=TEEC_ERROR_ACCESS_DENIED; + break; + default: + nResult=TEEC_ERROR_COMMUNICATION; + break; + } + } + + if (pOperation != NULL) + { + /* Update the operation parameters from the answer message */ + uint32_t i; + SCHANNEL6_ANSWER_PARAM * pSCXAnswers; + if (pAnswer->sHeader.nMessageType == SCX_OPEN_CLIENT_SESSION) + { + /* Open session */ + pSCXAnswers = pAnswer->sOpenClientSession.sAnswers; + } + else + { + /* Invoke case */ + pSCXAnswers = pAnswer->sInvokeClientCommand.sAnswers; + } + + for (i = 0; i < 4; i++) + { + uint32_t nSCXParamType; + nSCXParamType = SCX_GET_PARAM_TYPE(pCommand->sHeader.nMessageInfo, i); + if (nSCXParamType & SCX_PARAM_TYPE_OUTPUT_FLAG) + { + if (nSCXParamType & SCX_PARAM_TYPE_MEMREF_FLAG) + { + /* Trick: the size field is at the same position in a memref or a tmpref */ + pOperation->params[i].memref.size = pSCXAnswers[i].sSize.nSize; + } + else + { + /* An output value */ + pOperation->params[i].value.a = pSCXAnswers[i].sValue.a; + pOperation->params[i].value.b = pSCXAnswers[i].sValue.b; + } + } + } + } + + return nResult; +} + +/* ------------------------------------------------------------------------ */ + +static void* scxAllocateSharedMemory( + IN uint32_t nLength) +{ + if (nLength == 0) + { + /* This is valid, although we don't want to call mmap. + Just return a dummy non-NULL pointer */ + return (void*)0x10; + } + else + { + return mmap( + 0,nLength, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + 0,0); + } +} + +/* ------------------------------------------------------------------------ */ + +static void scxReleaseSharedMemory(IN void* pBuffer, + IN uint32_t nLength) +{ + if (nLength == 0) + { + return; + } + if (munmap(pBuffer, nLength)!= 0) + { + TRACE_WARNING("scxReleaseSharedMemory returned 0x%x \n",errno); + } +} +/* ------------------------------------------------------------------------ */ + +uint64_t scxGetCurrentTime(void) +{ + uint64_t currentTime = 0; + struct timeval now; + + gettimeofday(&now,NULL); + currentTime = now.tv_sec; + currentTime = (currentTime * 1000) + (now.tv_usec / 1000); + + return currentTime; +} +/* ------------------------------------------------------------------------ */ + +/* + * ==================================================== + * TEE Client API + * ===================================================== +*/ + +/** + * Get a time-limit equal to now + relative timeout expressed in milliseconds. + **/ +void TEEC_GetTimeLimit( + TEEC_Context* sContext, + uint32_t nTimeout, + TEEC_TimeLimit* sTimeLimit) +{ + uint64_t nTimeLimit = 0; + VAR_NOT_USED(sContext); + + TRACE_INFO("TEEC_GetTimeLimit(0x%X, %u ms)", sContext, nTimeout); + + if (nTimeout == 0xFFFFFFFF ) + { + /* Infinite timeout */ + nTimeLimit = SCTIME_INFINITE; + } + else + { + nTimeLimit = scxGetCurrentTime() + nTimeout; + } + TRACE_INFO("GetTimeLimit %ld\n",nTimeLimit); + memcpy(sTimeLimit, &nTimeLimit, sizeof(TEEC_TimeLimit)); +} + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_InitializeContext( + const char* pDeviceName, + TEEC_Context* pContext) +{ + + TEEC_Result nError = TEEC_SUCCESS; + S_HANDLE hDriver = S_HANDLE_NULL; + char sFullDeviceName[PATH_MAX]; + uint32_t nVersion; + + if(pDeviceName == NULL) + { + pDeviceName = SCX_DEFAULT_DEVICE_NAME; + } + strcpy(sFullDeviceName, "/dev/"); + strcat(sFullDeviceName, pDeviceName); + + hDriver = open(sFullDeviceName, O_RDWR, 0); + + if (hDriver == (uint32_t)-1) + { + TRACE_ERROR("scxOpen: open() failed 0x%x\n", errno); + switch(errno) + { + case ENOMEM: + nError = TEEC_ERROR_OUT_OF_MEMORY; + goto error; + case EINTR: + break; + default: + nError = TEEC_ERROR_COMMUNICATION; + goto error; + } + } + fcntl(hDriver, F_SETFD, FD_CLOEXEC); + nVersion = ioctl(hDriver, IOCTL_SCX_GET_VERSION); + if (nVersion != SM_DRIVER_VERSION) + { + TRACE_ERROR("scxOpen: Not expected driver version: 0x%x instead of 0x%x\n", nVersion,SM_DRIVER_VERSION); + switch(errno) + { + case ENOMEM: + nError=TEEC_ERROR_OUT_OF_MEMORY; + break; + default: + nError=TEEC_ERROR_COMMUNICATION; + break; + } + close(hDriver); + } +error: + if(nError == TEEC_SUCCESS) + { + pContext->imp._hConnection = hDriver; + } + else + { + TRACE_ERROR("scxOpen failed 0x%x\n", nError); + pContext->imp._hConnection = 0; + } + + return nError; +} + +//----------------------------------------------------------------------------------------------------- +void TEEC_FinalizeContext(TEEC_Context* pContext) +{ + TRACE_INFO("TEEC_FinalizeContext[0x%X]", pContext); + + if (pContext == NULL) return; + + close(pContext->imp._hConnection); + pContext->imp._hConnection = 0; +} + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_OpenSession ( + TEEC_Context* context, + TEEC_Session* session, /* OUT */ + const TEEC_UUID* destination, /* The trusted application UUID we want to open the session with */ + uint32_t connectionMethod, /* LoginType*/ + void* connectionData, /* LoginData */ + TEEC_Operation* operation, /* payload. If operation is NULL then no data buffers are exchanged with the Trusted Application, and the operation cannot be cancelled by the Client Application */ + uint32_t* errorOrigin) +{ + return TEEC_OpenSessionEx(context, + session, + NULL, + destination, + connectionMethod, + connectionData, + operation, + errorOrigin); +} + +//----------------------------------------------------------------------------------------------------- +void TEEC_CloseSession (TEEC_Session* session) +{ + TEEC_Context* context; + SCHANNEL6_ANSWER sAnswer; + SCHANNEL6_COMMAND sCommand; + if (session == NULL) return; + context = session->imp._pContext; + memset(&sCommand,0,sizeof(sCommand)); + sCommand.sHeader.nMessageType = SCX_CLOSE_CLIENT_SESSION; + sCommand.sHeader.nMessageSize = (sizeof(SCHANNEL6_CLOSE_CLIENT_SESSION_COMMAND) + - sizeof(SCHANNEL6_COMMAND_HEADER))/sizeof(uint32_t); + sCommand.sCloseClientSession.hClientSession = session->imp._hClientSession; + scxExchangeMessage(context, &sCommand, &sAnswer, NULL); + /* we ignore the error code of scxExchangeMessage */ + session->imp._hClientSession = S_HANDLE_NULL; + session->imp._pContext = NULL; +} + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_InvokeCommand( + TEEC_Session* session, + uint32_t commandID, + TEEC_Operation* operation, + uint32_t* errorOrigin) +{ + return TEEC_InvokeCommandEx(session, + NULL, + commandID, + operation, + errorOrigin); +} + + +//----------------------------------------------------------------------------------------------------- +/* Used to implement both register and allocate */ +static TEEC_Result TEEC_RegisterSharedMemory0( + TEEC_Context* context, + TEEC_SharedMemory* sharedMem) +{ + TEEC_Result nResult; + SCHANNEL6_COMMAND sCommand; + SCHANNEL6_ANSWER sAnswer; + + TRACE_INFO("TEEC_RegisterSharedMemory0 (%p, %p)",context, sharedMem); + memset(&sCommand, 0, sizeof(sCommand)); + + sCommand.sRegisterSharedMemory.nMessageSize = (sizeof(SCHANNEL6_REGISTER_SHARED_MEMORY_COMMAND) - sizeof(SCHANNEL6_COMMAND_HEADER))/4; + sCommand.sRegisterSharedMemory.nMessageType = SCX_REGISTER_SHARED_MEMORY; + sCommand.sRegisterSharedMemory.nMemoryFlags = sharedMem->flags; + sCommand.sRegisterSharedMemory.nSharedMemSize = sharedMem->size; + sCommand.sRegisterSharedMemory.nSharedMemStartOffset = 0; + sCommand.sRegisterSharedMemory.nSharedMemDescriptors[0] = (uint32_t)sharedMem->buffer; + nResult = scxExchangeMessage(context, + &sCommand, + &sAnswer, + NULL); + if (nResult == TEEC_SUCCESS) + { + nResult = sAnswer.sRegisterSharedMemory.nErrorCode; + } + if (nResult == TEEC_SUCCESS) + { + sharedMem->imp._pContext = context; + sharedMem->imp._hBlock = sAnswer.sRegisterSharedMemory.hBlock; + } + return nResult; +} + + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_RegisterSharedMemory( + TEEC_Context* context, + TEEC_SharedMemory* sharedMem) +{ + TRACE_INFO("TEEC_RegisterSharedMemory (%p)",context); + sharedMem->imp._pContext = NULL; + sharedMem->imp._hBlock = S_HANDLE_NULL; + sharedMem->imp._bAllocated = false; + return TEEC_RegisterSharedMemory0(context, sharedMem); +} + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_AllocateSharedMemory( + TEEC_Context* context, + TEEC_SharedMemory* sharedMem) +{ + TEEC_Result nResult; + TRACE_INFO("TEEC_AllocateSharedMemory (%p)",context); + + sharedMem->imp._pContext = NULL; + sharedMem->imp._hBlock = S_HANDLE_NULL; + sharedMem->buffer = scxAllocateSharedMemory(sharedMem->size); + if (sharedMem->buffer == NULL) + { + return TEEC_ERROR_OUT_OF_MEMORY; + } + sharedMem->imp._bAllocated = true; + nResult = TEEC_RegisterSharedMemory0(context, sharedMem); + if (nResult != TEEC_SUCCESS) + { + scxReleaseSharedMemory(sharedMem->buffer,sharedMem->size); + sharedMem->buffer = NULL; + } + return nResult; +} + +//----------------------------------------------------------------------------------------------------- +void TEEC_ReleaseSharedMemory ( + TEEC_SharedMemory* sharedMem) +{ + SCHANNEL6_ANSWER sAnswer; + SCHANNEL6_COMMAND sMessage; + TEEC_Context* context; + + context = (TEEC_Context *)sharedMem->imp._pContext; + memset(&sMessage, 0, sizeof(SCHANNEL6_COMMAND)); + sMessage.sReleaseSharedMemory.nMessageType = SCX_RELEASE_SHARED_MEMORY; + sMessage.sReleaseSharedMemory.nMessageSize = (sizeof(SCHANNEL6_RELEASE_SHARED_MEMORY_COMMAND) + - sizeof(SCHANNEL6_COMMAND_HEADER))/sizeof(uint32_t); + sMessage.sReleaseSharedMemory.hBlock = sharedMem->imp._hBlock; + scxExchangeMessage(context,&sMessage, &sAnswer, NULL); + if (sharedMem->imp._bAllocated) + { + scxReleaseSharedMemory(sharedMem->buffer,sharedMem->size); + /* Update parameters: + * In this case the Implementation MUST set the buffer and size fields of the sharedMem structure + * to NULL and 0 respectively before returning. + */ + sharedMem->buffer = NULL; + sharedMem->size = 0; + } + sharedMem->imp._pContext = NULL; + sharedMem->imp._hBlock = S_HANDLE_NULL; +} + +//----------------------------------------------------------------------------------------------------- +void TEEC_RequestCancellation(TEEC_Operation* operation) +{ + uint32_t nOperationState; + TEEC_Result nResult; + + if (operation == NULL) return; + +retry: + nOperationState = operation->started; + if (nOperationState == 2) + { + /* Operation already finished. Return immediately */ + return; + } + else if (nOperationState == 1) + { + /* Operation is in progress */ + TEEC_Context* context; + SCHANNEL6_ANSWER sAnswer; + SCHANNEL6_COMMAND sMessage; + + context = operation->imp._pContext; + + memset(&sMessage,0,sizeof(sMessage)); + sMessage.sHeader.nMessageType = SCX_CANCEL_CLIENT_OPERATION; + sMessage.sHeader.nMessageSize = (sizeof(SCHANNEL6_CANCEL_CLIENT_OPERATION_COMMAND) - sizeof(SCHANNEL6_COMMAND_HEADER))/4; + sMessage.sCancelClientOperation.hClientSession = operation->imp._hSession; + sMessage.sCancelClientOperation.nCancellationID = (uint32_t)operation; + nResult = scxExchangeMessage(context,&sMessage, &sAnswer, NULL); + + if (nResult != TEEC_SUCCESS) + { + /* Communication failure. Ignore the error: the operation is already cancelled anyway */ + return; + } + if (sAnswer.sCancelClientOperation.nErrorCode == S_SUCCESS) + { + /* Command was successfully cancelled */ + return; + } + /* Otherwise, the command has not yet reached the secure world or has already finished and we must retry */ + } + /* This applies as well when nOperationState == 0. In this case, the operation has not yet + started yet and we don't even have a pointer to the context */ + scxYield(); + goto retry; +} + + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_ReadSignatureFile( + void** ppSignatureFile, + uint32_t* pnSignatureFileLength) +{ + TEEC_Result nErrorCode = TEEC_SUCCESS; + + uint32_t nBytesRead; + uint32_t nSignatureSize = 0; + uint8_t* pSignature = NULL; + FILE* pSignatureFile = NULL; + char sFileName[PATH_MAX + 1 + 5]; /* Allocate room for the signature extension */ + long nFileSize; + + *pnSignatureFileLength = 0; + *ppSignatureFile = NULL; + + if (realpath("/proc/self/exe", sFileName) == NULL) + { + TRACE_ERROR("TEEC_ReadSignatureFile: realpath failed [%d]", errno); + return TEEC_ERROR_OS; + } + + /* Work out the signature file name */ + strcat(sFileName, ".ssig"); + + pSignatureFile = fopen(sFileName, "rb"); + if (pSignatureFile == NULL) + { + /* Signature doesn't exist */ + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + if (fseek(pSignatureFile, 0, SEEK_END) != 0) + { + TRACE_ERROR("TEEC_ReadSignatureFile: fseek(%s) failed [%d]", + sFileName, errno); + nErrorCode = TEEC_ERROR_OS; + goto error; + } + + nFileSize = ftell(pSignatureFile); + if (nFileSize < 0) + { + TRACE_ERROR("TEEC_ReadSignatureFile: ftell(%s) failed [%d]", + sFileName, errno); + nErrorCode = TEEC_ERROR_OS; + goto error; + } + + nSignatureSize = (uint32_t)nFileSize; + + if (nSignatureSize != 0) + { + pSignature = malloc(nSignatureSize); + if (pSignature == NULL) + { + TRACE_ERROR("TEEC_ReadSignatureFile: Heap - Out of memory for %u bytes", + nSignatureSize); + nErrorCode = TEEC_ERROR_OUT_OF_MEMORY; + goto error; + } + + rewind(pSignatureFile); + + nBytesRead = fread(pSignature, 1, nSignatureSize, pSignatureFile); + if (nBytesRead < nSignatureSize) + { + TRACE_ERROR("TEEC_ReadSignatureFile: fread failed [%d]", errno); + nErrorCode = TEEC_ERROR_OS; + goto error; + } + } + + fclose(pSignatureFile); + + *pnSignatureFileLength = nSignatureSize; + *ppSignatureFile = pSignature; + + return S_SUCCESS; + +error: + fclose(pSignatureFile); + free(pSignature); + + return nErrorCode; +} + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_OpenSessionEx ( + TEEC_Context* context, + TEEC_Session* session, /* OUT */ + const TEEC_TimeLimit* timeLimit, + const TEEC_UUID* destination, /* The trusted application UUID we want to open the session with */ + uint32_t connectionMethod, /* LoginType*/ + void* connectionData, /* LoginData */ + TEEC_Operation* operation, /* payload. If operation is NULL then no data buffers are exchanged with the Trusted Application, and the operation cannot be cancelled by the Client Application */ + uint32_t* returnOrigin) +{ + TEEC_Result nError; + uint32_t nReturnOrigin; + SCHANNEL6_ANSWER sAnswer; + SCHANNEL6_COMMAND sCommand; + + memset(&sCommand, 0, sizeof(SCHANNEL6_COMMAND)); + + sCommand.sHeader.nMessageType = SCX_OPEN_CLIENT_SESSION; + sCommand.sHeader.nMessageSize = (sizeof(SCHANNEL6_OPEN_CLIENT_SESSION_COMMAND) - 20 -sizeof(SCHANNEL6_COMMAND_HEADER))/sizeof(uint32_t); + if (timeLimit == NULL) + { + sCommand.sOpenClientSession.sTimeout = SCTIME_INFINITE; + } + else + { + sCommand.sOpenClientSession.sTimeout = *(uint64_t*)timeLimit; + } + sCommand.sOpenClientSession.sDestinationUUID = *((S_UUID*)destination); + sCommand.sOpenClientSession.nLoginType = connectionMethod; + if ((connectionMethod == TEEC_LOGIN_GROUP)||(connectionMethod == TEEC_LOGIN_GROUP_APPLICATION)) + { + /* connectionData MUST point to a uint32_t which contains the group + * which this Client Application wants to connect as. The Linux Driver + * is responsible for securely ensuring that the Client Application + * instance is actually a member of this group. + */ + if (connectionData != NULL) + { + *(uint32_t*)sCommand.sOpenClientSession.sLoginData = *(uint32_t*)connectionData; + sCommand.sHeader.nMessageSize += sizeof(uint32_t); + } + } + sCommand.sOpenClientSession.nCancellationID = (uint32_t)operation; // used for TEEC_RequestCancellation + + if (operation != NULL) + { + operation->imp._pContext = context; + operation->imp._hSession = S_HANDLE_NULL; + operation->started = 1; + } + + nError = scxExchangeMessage(context, &sCommand, &sAnswer, operation); + + if (operation != NULL) operation->started = 2; + + if (nError != TEEC_SUCCESS) + { + nReturnOrigin = TEEC_ORIGIN_COMMS; + } + else + { + nError = sAnswer.sOpenClientSession.nErrorCode; + nReturnOrigin = sAnswer.sOpenClientSession.nReturnOrigin; + } + + if (returnOrigin != NULL) *returnOrigin = nReturnOrigin; + + if (nError == S_SUCCESS) + { + session->imp._hClientSession = sAnswer.sOpenClientSession.hClientSession; + session->imp._pContext = context; + } + + return nError; +} + +//----------------------------------------------------------------------------------------------------- +TEEC_Result TEEC_InvokeCommandEx( + TEEC_Session* session, + const TEEC_TimeLimit* timeLimit, + uint32_t commandID, + TEEC_Operation* operation, + uint32_t* returnOrigin) +{ + TEEC_Result nError; + SCHANNEL6_ANSWER sAnswer; + SCHANNEL6_COMMAND sCommand; + uint32_t nReturnOrigin; + TEEC_Context * context; + + context = (TEEC_Context *)session->imp._pContext; + memset(&sCommand, 0, sizeof(SCHANNEL6_COMMAND)); + + sCommand.sHeader.nMessageType = SCX_INVOKE_CLIENT_COMMAND; + sCommand.sHeader.nMessageSize = (sizeof(SCHANNEL6_INVOKE_CLIENT_COMMAND_COMMAND) - sizeof(SCHANNEL6_COMMAND_HEADER))/sizeof(uint32_t); + sCommand.sInvokeClientCommand.nClientCommandIdentifier = commandID; + if (timeLimit == NULL) + { + sCommand.sInvokeClientCommand.sTimeout = SCTIME_INFINITE; + } + else + { + sCommand.sInvokeClientCommand.sTimeout = *(uint64_t*)timeLimit; + } + sCommand.sInvokeClientCommand.hClientSession = session->imp._hClientSession; + sCommand.sInvokeClientCommand.nCancellationID = (uint32_t)operation; // used for TEEC_RequestCancellation + + if (operation != NULL) + { + operation->imp._pContext = session->imp._pContext; + operation->imp._hSession = session->imp._hClientSession; + operation->started = 1; + } + + nError = scxExchangeMessage(context, &sCommand, &sAnswer, operation); + + if (operation != NULL) + { + operation->started = 2; + operation->imp._hSession = S_HANDLE_NULL; + operation->imp._pContext = NULL; + } + + if (nError != TEEC_SUCCESS) + { + nReturnOrigin = TEEC_ORIGIN_COMMS; + } + else + { + nError = sAnswer.sInvokeClientCommand.nErrorCode; + nReturnOrigin = sAnswer.sInvokeClientCommand.nReturnOrigin; + } + + if (returnOrigin != NULL) *returnOrigin = nReturnOrigin; + + return nError; + +} + +//----------------------------------------------------------------------------------------------------- +/* + * Retrieves information about the implementation + */ +void TEEC_GetImplementationInfo( + TEEC_Context* context, + TEEC_ImplementationInfo* description) +{ + TRACE_INFO("TEEC_GetImplementationInfo"); + + memset(description, 0, sizeof(TEEC_ImplementationInfo)); + + strcpy(description->apiDescription, S_VERSION_STRING); + + if (context != NULL) + { + SCX_VERSION_INFORMATION_BUFFER sInfoBuffer; + uint32_t nResult; + + nResult = ioctl((S_HANDLE)context->imp._hConnection, IOCTL_SCX_GET_DESCRIPTION, &sInfoBuffer); + if (nResult != S_SUCCESS) + { + TRACE_ERROR("TEEC_GetImplementationInfo[0x%X]: ioctl returned error: 0x%x ( %d)\n",context, nResult, errno); + return; + } + + memcpy(description->commsDescription, sInfoBuffer.sDriverDescription, 64); + description->commsDescription[64] = 0; + memcpy(description->TEEDescription, sInfoBuffer.sSecureWorldDescription, 64); + description->TEEDescription[64] = 0; + } +} + +void TEEC_GetImplementationLimits( + TEEC_ImplementationLimits* limits) +{ + memset(limits, 0, sizeof(TEEC_ImplementationLimits)); + + /* A temp mem ref can not be mapped on more than 1Mb */ + limits->pageSize = SIZE_4KB; + limits->tmprefMaxSize = SIZE_1MB; + limits->sharedMemMaxSize = SIZE_1MB * 8; + } |