From: DongJin Park <djpax.park@samsung.com> Date: Wed, 1 Aug 2012 06:44:23 +0000 (+0900) Subject: manta: add MobiCore userspace daemon and libraries X-Git-Tag: cm-10.1-M1~252^2~1 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=4e9e8c9c0169b40318386436d762c3d73cf4c328;p=GitHub%2FLineageOS%2Fandroid_hardware_samsung_slsi_exynos5.git manta: add MobiCore userspace daemon and libraries Change-Id: Ide5a137050bf384a5409bec6806018ae84d34767 Signed-off-by: DongJin Park <djpax.park@samsung.com> --- diff --git a/Android.mk b/Android.mk index 3656a1e..399a89a 100644 --- a/Android.mk +++ b/Android.mk @@ -29,7 +29,8 @@ exynos5_dirs := \ libv4l2 \ libhwjpeg \ libhwc \ - libcamera2 + libcamera2 \ + mobicore BOARD_USE_V4L2 := true BOARD_USE_V4L2_ION := true diff --git a/exynos5.mk b/exynos5.mk index ecef01b..2776260 100644 --- a/exynos5.mk +++ b/exynos5.mk @@ -30,3 +30,11 @@ PRODUCT_PACKAGES += \ # hw composer HAL PRODUCT_PACKAGES += \ hwcomposer.exynos5 + +# MobiCore +PRODUCT_PACKAGES += \ + libMcClient \ + libMcRegistry \ + libPaApi \ + mcDriverDaemon \ + gdmcprov diff --git a/mobicore/Android.mk b/mobicore/Android.mk new file mode 100755 index 0000000..9d7f28c --- /dev/null +++ b/mobicore/Android.mk @@ -0,0 +1,25 @@ +# ============================================================================= +# +# Makefile pointing to all makefiles within the project. +# +# ============================================================================= +MOBICORE_PROJECT_PATH := $(call my-dir) +# Setup common variables +COMP_PATH_Logwrapper := $(MOBICORE_PROJECT_PATH)/common/LogWrapper +COMP_PATH_MobiCore := $(MOBICORE_PROJECT_PATH)/common/MobiCore +COMP_PATH_MobiCoreDriverMod := $(MOBICORE_PROJECT_PATH)/include + + +# Include the Daemon +include $(MOBICORE_PROJECT_PATH)/daemon/Android.mk + +MC_INCLUDE_DIR := $(COMP_PATH_MobiCore)/inc \ + $(COMP_PATH_MobiCore)/inc/TlCm \ + $(MOBICORE_PROJECT_PATH)/daemon/ClientLib/public \ + $(MOBICORE_PROJECT_PATH)/daemon/Registry/Public +MC_DEBUG := _DEBUG +SYSTEM_LIB_DIR=/system/lib +GDM_PROVLIB_SHARED_LIBS=libMcClient +# Include the provisioning lib +include $(MOBICORE_PROJECT_PATH)/provlib/Android.mk + diff --git a/mobicore/common/LogWrapper/Android.mk b/mobicore/common/LogWrapper/Android.mk new file mode 100644 index 0000000..b869c2b --- /dev/null +++ b/mobicore/common/LogWrapper/Android.mk @@ -0,0 +1,15 @@ +# ============================================================================= +# +# MobiCore log wrapper to be included by Android components / products +# +# ============================================================================= + +# This is not a separate module. +# Only for inclusion by other modules. + +LOCAL_SHARED_LIBRARIES += liblog + +# Enable logging to logcat per default +LOCAL_CFLAGS += -DLOG_ANDROID + +LOCAL_C_INCLUDES += $(call my-dir) \ No newline at end of file diff --git a/mobicore/common/LogWrapper/log.h b/mobicore/common/LogWrapper/log.h new file mode 100644 index 0000000..f289b73 --- /dev/null +++ b/mobicore/common/LogWrapper/log.h @@ -0,0 +1,191 @@ +/** Log wrapper for Android. + * @{ + * @file + * + * Maps LOG_*() macros to __android_log_print() if LOG_ANDROID is defined. + * Adds some extra info to log output like LOG_TAG, file name and line number. + * + * <!-- Copyright Giesecke & Devrient GmbH 2010 - 2011 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 TLCWRAPPERANDROIDLOG_H_ +#define TLCWRAPPERANDROIDLOG_H_ + +#include <unistd.h> +#include <stdio.h> +#include <android/log.h> + + +#define EOL "\n" +#define DUMMY_FUNCTION() do{}while(0) + + +#ifdef LOG_ANDROID + +#ifdef NDEBUG + #define LOG_I(fmt, args...) DUMMY_FUNCTION() + #define LOG_W(fmt, args...) DUMMY_FUNCTION() +#else + #define LOG_I(fmt, args...) LOG_i("%d : "fmt , __LINE__ , ## args) + #define LOG_W(fmt, args...) LOG_w("%d : "fmt , __LINE__ , ## args) +#endif + #define _LOG_E(fmt, args...) LOG_e("%d : "fmt , __LINE__ , ## args) + + #define LOG_i(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) + #define LOG_w(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) + #define LOG_e(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) + +#else //!defined(LOG_ANDROID) + + // #level / #LOG_TAG ( process_id): __VA_ARGS__ + // Example: + // I/McDrvBasicTest_0_1( 4075): setUp + #define _LOG_x(_x_,...) \ + do \ + { \ + printf("%s/%s(%d): ",_x_,LOG_TAG,getpid()); \ + printf(__VA_ARGS__); \ + printf(EOL); \ + } while(1!=1) + + +#ifdef NDEBUG + #define LOG_I(fmt, args...) DUMMY_FUNCTION() + #define LOG_W(fmt, args...) DUMMY_FUNCTION() +#else + #define LOG_I(...) _LOG_x("I",__VA_ARGS__) + #define LOG_W(...) _LOG_x("W",__VA_ARGS__) +#endif + #define _LOG_E(...) _LOG_x("E",__VA_ARGS__) + +#endif //defined(LOG_ANDROID) + + +/** LOG_E() needs to be more prominent: + * Display "*********** ERROR ***********" before actual error message. + */ +#define LOG_E(...) \ + do \ + { \ + _LOG_E("*****************************"); \ + _LOG_E("********* ERROR *********"); \ + _LOG_E(__VA_ARGS__); \ + } while(1!=1) + + +#define LOG_I_BUF LOG_I_Buf + +__attribute__ ((unused)) +static void LOG_I_Buf( + const char * szDescriptor, + const void * blob, + size_t sizeOfBlob +) { + + #define CPL 0x10 // chars per line + #define OVERHEAD 20 + + char buffer[CPL * 4 + OVERHEAD]; + + uint32_t index = 0; + + uint32_t moreThanOneLine = (sizeOfBlob > CPL); + uint32_t blockLen = CPL; + uint32_t addr = 0; + uint32_t i = 0; + + if (NULL != szDescriptor) + { + index += sprintf(&buffer[index], "%s", szDescriptor); + } + + if (moreThanOneLine) + { + if (NULL == szDescriptor) + { + index += sprintf(&buffer[index], "memory dump"); + } + index += sprintf(&buffer[index], " (0x%08x, %d bytes)", (uint32_t)blob,sizeOfBlob); + LOG_I("%s", buffer); + index = 0; + } + else if (NULL == szDescriptor) + { + index += sprintf(&buffer[index], "Data at 0x%08x: ", (uint32_t)blob); + } + + if(sizeOfBlob == 0) { + LOG_I("%s", buffer); + } + else + { + while (sizeOfBlob > 0) + { + if (sizeOfBlob < blockLen) + { + blockLen = sizeOfBlob; + } + + // address + if (moreThanOneLine) + { + index += sprintf(&buffer[index], "0x%08X | ",addr); + addr += CPL; + } + // bytes as hex + for (i=0; i<blockLen; ++i) + { + index += sprintf(&buffer[index], "%02x ", ((const char *)blob)[i] ); + } + // spaces if necessary + if ((blockLen < CPL) && (moreThanOneLine)) + { + // add spaces + for (i=0; i<(3*(CPL-blockLen)); ++i) { + index += sprintf(&buffer[index], " "); + } + } + // bytes as ASCII + index += sprintf(&buffer[index], "| "); + for (i=0; i<blockLen; ++i) + { + char c = ((const char *)blob)[i]; + index += sprintf(&buffer[index], "%c",(c>32)?c:'.'); + } + + blob = &(((const char *)blob)[blockLen]); + sizeOfBlob -= blockLen; + + // print line to logcat / stdout + LOG_I("%s", buffer); + index = 0; + } + } +} + +#endif /** TLCWRAPPERANDROIDLOG_H_ */ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/Mci/mci.h b/mobicore/common/MobiCore/inc/Mci/mci.h new file mode 100644 index 0000000..6bd6f10 --- /dev/null +++ b/mobicore/common/MobiCore/inc/Mci/mci.h @@ -0,0 +1,96 @@ +/** @mainpage MobiCore Control Interface - MCI + * + * <h2>Introduction</h2> + * The MobiCore Control Interface (MCI) is the interface for integrating G&D MobiCore technology into the + * rich operating system running in the non-secure part of an ARM TrustZone enabled platform. + * + * <h2>Interface overview</h2> + * The Structure of the MobiCore control interface is depicted in the figure below: + * @image html DoxyOverviewMci500x.png "MobiCore control interface" + * @image latex DoxyOverviewMci500x.png "MobiCore control interface" width=12cm + * + * The MCI is composed of the following interfaces: + * <ul> + * + * <li><b>MobiCore control protocol (MCP) interface.</b></li><br> + * The MCP interface is responsible for the main communicating with the MobiCore. This involves sending commands for starting + * and stopping of Trustlets as well as checking their corresponding answers. MCP information is exchanged in a + * world shared memory buffer which needs to be initially established between NWd and SWd using the FastCall interface.<br> + * + * <li><b>Notification queue interface.</b></li><br> + * Notifications inform the MobiCore runtime environment that information is pending in a WSM buffer. + * The Trustlet Connector (TLC) and the corresponding Trustlet also utilize this buffer to + * notify each other about new data within the Trustlet Connector Interface (TCI). Therefore the TLC writes + * a notification including the session ID to the buffer. The driver informs the MobiCore + * about the availability of a notification with the use of a SIQ. On the secure side the Runtime Management + * notifies the Trustlet, according to the given session ID, about the availability of new data. + * The same mechanism is used vice versa for writing data back to the None-secure world. + * + * <li><b>FastCall interface.</b></li><br> + * The FastCall interface of the MobiCore system is used to transfer control from the Non-secure World (NWd) to the + * Secure World (SWd) and back. There are three mechanisms the NWd shall use to interact with the MobiCore Monitor: + * FastCall, N-SIQ and NQ-IRQ (Notification IRQ). FastCall and N-SIQ operations are used to hand over control + * to the MobiCore. Both functions make use of the SMC [ARM11] operation. + * + * </ul> + * + * You can find more information about the interfaces in the respective modules description. + * + * <h2>Version history</h2> + * <table class="customtab"> + * <tr><td width="100px"><b>Date</b></td><td width="80px"><b>Version</b></td><td><b>Changes</b></td></tr> + * <tr><td>2009-06-25</td><td>0.1</td><td>Initial Release</td></tr> + * <tr><td>2009-07-01</td><td>0.2</td><td>Major rewrite</td></tr> + * <tr><td>2009-08-06</td><td>0.3</td><td>Added documentation for FastCall helper functions</td></tr> + * <tr><td>2009-09-10</td><td>0.4</td><td>Update of constant naming. Modification of doxygen config.</td></tr> + * <tr><td>2010-03-09</td><td>0.5</td><td>Added fastCallPower() helper function for MC_FC_POWER.</td></tr> + * <tr><td>2010-05-10</td><td>0.6</td><td>Restructuring of load format header.</td></tr> + * <tr><td>2011-07-19</td><td>0.7</td><td>update to reflect current code changes.</td></tr> + * </table> + * + * + * @file + * @defgroup FCI FastCall Interface + * + * @defgroup NQ Notification Queue + * + * @defgroup MCP MobiCore Control Protocol + * + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCI_H_ +#define MCI_H_ + +#include "version.h" +#include "mcifc.h" +#include "mcinq.h" +#include "mcimcp.h" + +#endif /** MCI_H_ */ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/Mci/mcifc.h b/mobicore/common/MobiCore/inc/Mci/mcifc.h new file mode 100644 index 0000000..696e41c --- /dev/null +++ b/mobicore/common/MobiCore/inc/Mci/mcifc.h @@ -0,0 +1,129 @@ +/** @addtogroup FCI + * @{ + * @file + * FastCall declarations. + * + * Holds the functions for SIQ, YIELD and FastCall for switching to the secure world. + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCIFC_H_ +#define MCIFC_H_ + +/** @name MobiCore FastCall Defines + * Defines for the two different FastCall's. + */ +/** @{ */ + +// --- global ---- +#define MC_FC_INVALID ((uint32_t) 0 ) /**< Invalid FastCall ID */ +#define MC_FC_INIT ((uint32_t)(-1)) /**< Initializing FastCall. */ +#define MC_FC_INFO ((uint32_t)(-2)) /**< Info FastCall. */ + +// following defines are currently frozen, so they will candidate for later big-change +// --- sleep modes --- +#define MC_FC_SLEEP ((uint32_t)(-3)) /**< enter power-sleep */ +#define MC_FC_AFTR ((uint32_t)(-5)) /**< enter AFTR-sleep (called from core-0) */ +// --- wake-up access --- +#define MC_FC_CORE_X_WAKEUP ((uint32_t)(-4)) /**< wakeup/boot core-x (optional core-number in r1, not "0" ) */ +#define MC_FC_C15_RESUME ((uint32_t)(-11)) /**< Write power control & diag registers */ +#define MC_FC_CMD_SAVE ((uint32_t)(-6)) /**< Save core context to CP15 table(r1 is core number) */ +#define MC_FC_CMD_SHUTDOWN ((uint32_t)(-7)) /**< Shutdown core(r1 is core number, cache flush is expected) */ +// --- L2 cache access --- +#define MC_FC_L2X0_CTRL ((uint32_t)(-21)) /**< Write to L2X0 control register */ +#define MC_FC_L2X0_SETUP1 ((uint32_t)(-22)) /**< Setup L2X0 register - part 1 */ +#define MC_FC_L2X0_SETUP2 ((uint32_t)(-23)) /**< Setup L2X0 register - part 2 */ +#define MC_FC_L2X0_INVALL ((uint32_t)(-24)) /**< Invalidate all L2 cache */ +#define MC_FC_L2X0_DEBUG ((uint32_t)(-25)) /**< Write L2X0 debug register */ +// --- MEM traces --- +#define MC_FC_MEM_TRACE ((uint32_t)(-31)) /**< Enable SWd tracing via memory */ +// --- write access to CP15 regs --- +#define MC_FC_CP15_REG ((uint32_t)(-101)) /**< general CP15/cache register update */ +// --- store value in sDDRRAM --- +#define MC_FC_STORE_BINFO ((uint32_t)(-201)) /**< write a 32bit value in secure DDRRAM in incremented art (max 2kB) */ + +#define MC_FC_MAX_ID ((uint32_t)(0xFFFF0000)) /**< Maximum allowed FastCall ID */ + +// r1 is requested status (0,1,2), on return r2 holds this status value + +/** @} */ + +/** @name MobiCore SMC Defines + * Defines the different secure monitor calls (SMC) for world switching. + * @{ */ +#define MC_SMC_N_YIELD 0x3 /**< Yield to switch from NWd to SWd. */ +#define MC_SMC_N_SIQ 0x4 /**< SIQ to switch from NWd to SWd. */ +/** @} */ + +/** @name MobiCore status + * MobiCore status information. + * @{ */ +#define MC_STATUS_NOT_INITIALIZED 0 /**< MobiCore is not yet initialized. FastCall FcInit() has to be used function to set up MobiCore.*/ +#define MC_STATUS_BAD_INIT 1 /**< Bad parameters have been passed in FcInit(). */ +#define MC_STATUS_INITIALIZED 2 /**< MobiCore did initialize properly. */ +#define MC_STATUS_HALT 3 /**< MobiCore kernel halted due to an unrecoverable exception. Further information is available extended info */ +/** @} */ + +/** @name Extended Info Identifiers + * Extended info parameters for MC_FC_INFO to obtain further information depending on MobiCore state. + * @{ */ +#define MC_EXT_INFO_ID_MCI_VERSION 0 /**< Version of the MobiCore Control Interface (MCI) */ +#define MC_EXT_INFO_ID_FLAGS 1 /**< MobiCore control flags */ +#define MC_EXT_INFO_ID_HALT_CODE 2 /**< MobiCore halt condition code */ +#define MC_EXT_INFO_ID_HALT_IP 3 /**< MobiCore halt condition instruction pointer */ +#define MC_EXT_INFO_ID_FAULT_CNT 4 /**< MobiCore fault counter */ +#define MC_EXT_INFO_ID_FAULT_CAUSE 5 /**< MobiCore last fault cause */ +#define MC_EXT_INFO_ID_FAULT_META 6 /**< MobiCore last fault meta */ +#define MC_EXT_INFO_ID_FAULT_THREAD 7 /**< MobiCore last fault threadid */ +#define MC_EXT_INFO_ID_FAULT_IP 8 /**< MobiCore last fault instruction pointer */ +#define MC_EXT_INFO_ID_FAULT_SP 9 /**< MobiCore last fault stack pointer */ +#define MC_EXT_INFO_ID_FAULT_ARCH_DFSR 10 /**< MobiCore last fault ARM arch information */ +#define MC_EXT_INFO_ID_FAULT_ARCH_ADFSR 11 /**< MobiCore last fault ARM arch information */ +#define MC_EXT_INFO_ID_FAULT_ARCH_DFAR 12 /**< MobiCore last fault ARM arch information */ +#define MC_EXT_INFO_ID_FAULT_ARCH_IFSR 13 /**< MobiCore last fault ARM arch information */ +#define MC_EXT_INFO_ID_FAULT_ARCH_AIFSR 14 /**< MobiCore last fault ARM arch information */ +#define MC_EXT_INFO_ID_FAULT_ARCH_IFAR 15 /**< MobiCore last fault ARM arch information */ +#define MC_EXT_INFO_ID_MC_CONFIGURED 16 /**< MobiCore configured by Daemon via fc_init flag */ +#define MC_EXT_INFO_ID_MC_SCHED_STATUS 17 /**< MobiCore scheduling status: idle/non-idle */ +#define MC_EXT_INFO_ID_MC_STATUS 18 /**< MobiCore runtime status: initialized, halted */ +#define MC_EXT_INFO_ID_MC_EXC_PARTNER 19 /**< MobiCore exception handler last partner */ +#define MC_EXT_INFO_ID_MC_EXC_IPCPEER 20 /**< MobiCore exception handler last peer */ +#define MC_EXT_INFO_ID_MC_EXC_IPCMSG 21 /**< MobiCore exception handler last IPC message */ +#define MC_EXT_INFO_ID_MC_EXC_IPCDATA 22 /**< MobiCore exception handler last IPC data */ + +/** @} */ + +/** @name FastCall return values + * Return values of the MobiCore FastCalls. + * @{ */ +#define MC_FC_RET_OK 0 /**< No error. Everything worked fine. */ +#define MC_FC_RET_ERR_INVALID 1 /**< FastCall was not successful. */ +#define MC_FC_RET_ERR_ALREADY_INITIALIZED 5 /**< MobiCore has already been initialized. */ +/** @} */ + +#endif /** MCIFC_H_ */ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/Mci/mcifcfunc.h b/mobicore/common/MobiCore/inc/Mci/mcifcfunc.h new file mode 100644 index 0000000..69fbbc1 --- /dev/null +++ b/mobicore/common/MobiCore/inc/Mci/mcifcfunc.h @@ -0,0 +1,187 @@ +/** @addtogroup FCI + * @{ + * @file + * Declaration of FastCall helper functions. + * + * @attention Helper functions are mostly RealView (ARM CC) specific. + * + * Holds the functions for SIQ, YIELD and FastCall for switching to the secure world. + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCIFCFUNC_H_ +#define MCIFCFUNC_H_ + +#include "mcifc.h" +/** + * Execute a secure monitor call (SMC). + * + * @param mode SMC mode affects the way SMC is handled + * + * @attention This function shall not be used directly. Use N_Siq() or Yield() instead. + */ +__smc(0) void smc(int32_t mode); + +/** + * N-SIQ switch from NWd to SWd. + * Execution will continue in the SWd. The notification queue will be drained by the MC4 and MC4 system schedules its services. + */ +inline void N_Siq(void) { smc(MC_SMC_N_SIQ); } + +/** + * Yield switch from NWd to SWd. + * Execution will continue in the SWd without scheduling MC4 services. + */ +inline void Yield(void) { smc(MC_SMC_N_YIELD); } + +/** Wrapper structure for parameter passing in registers. + * This structure is used as a "wrapper" return value for functions that + * return data in the registers r0 to r3. With the RealView compiler such + * function are declare as: _value_in_regs reg_r0_r1_r2_r3_t foo() + + */ +typedef struct { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; +} reg_r0_r1_r2_r3_t; + +/** Parameterized SMC for FastCalls. + * @attention This function shall not be used directly. + */ +__smc(0) __value_in_regs reg_r0_r1_r2_r3_t smcFc( + uint32_t r0, + uint32_t r1, + uint32_t r2, + uint32_t r3 +); + +/** FastCall helper function. + * @attention This function shall not be used directly. + */ +inline static __value_in_regs reg_r0_r1_r2_r3_t fastCall( + uint32_t r0, + uint32_t r1, + uint32_t r2, + uint32_t r3 +) { + return smcFc(r0,r1,r2,r3); +} + +/** + * Initialize the MobiCore. + * The FcMc4init FastCall shall be used to set up the MCI. The function passes the message buffers used in the MCI to the MC4 system. + * As long as the buffers are not set up the MC4 message passing mechanisms (notifications, MCP commands) are not available. + * NQ buffer and MCP buffer as well as length calculations are described in the "MobiCore4 Driver Interface Specification". + * <br> The fastCallInit() will not check the parameters for validity. Instead the MC4 will perform a check on first usage of the parameters. + * + * @image html DoxyMciBuffer.png "MCI buffer" + * @image latex DoxyMciBuffer.png "MCI buffer" width=12cm + * + * @param base Physical start address of the MCI buffer. Must be 4kB aligned. + * @param nqOffset Offset in bytes to the beginning of the NQ buffer. + * @param nqLength Length of the NQ buffer in bytes. + * @param mcpOffset Offset in bytes to the beginning of the MCP buffer. + * @param mcpLength Length of the MCP buffer in bytes + * + */ +inline static uint32_t fastCallInit( + uint8_t *base, + uint32_t nqOffset, + uint32_t nqLength, + uint32_t mcpOffset, + uint32_t mcpLength +) { + + reg_r0_r1_r2_r3_t ret; + + ret = fastCall( + MC_FC_INIT, + (uint32_t)base, + ((nqOffset << 16) | (nqLength & 0xFFFF)), + ((mcpOffset << 16) | (mcpLength & 0xFFFF)) ); + + + return ret.r1; +} + + +/** Get status information about MobiCore. + * The FcMcGetInfo FastCall provides information about the current state of the MobiCore. + * In certain states extended information is provided. + * + * @param extInfoId Extended info word to be obtained. + * @param mc4state Current state of the MobiCore. + * @param extInfo Extended information depending on state. + */ +inline static uint32_t fastCallGetInfo( + uint32_t extInfoId, + uint32_t *mc4state, + uint32_t *extInfo +) { + reg_r0_r1_r2_r3_t ret; + + ret = fastCall(MC_FC_INFO,extInfoId,0,0); + + if (MC_FC_RET_OK == ret.r1) + { + *mc4state = ret.r2; + *extInfo = ret.r3; + } + + return ret.r1; +} + +/** + * Power management. + * The power management FastCall is platform specific. + * + * @param param0 platform specific parameter. + * @param param1 platform specific parameter. + * @param param2 platform specific parameter. + */ +inline static uint32_t fastCallPower( + uint32_t param0, + uint32_t param1, + uint32_t param2 +) { + + reg_r0_r1_r2_r3_t ret; + + ret = fastCall( + MC_FC_POWER, + param0, + param1, + param2 ); + + return ret.r1; +} + +#endif /* MCIFCFUNC_H_ */ +/** + * @}*/ diff --git a/mobicore/common/MobiCore/inc/Mci/mcimcp.h b/mobicore/common/MobiCore/inc/Mci/mcimcp.h new file mode 100644 index 0000000..e2eb1b6 --- /dev/null +++ b/mobicore/common/MobiCore/inc/Mci/mcimcp.h @@ -0,0 +1,404 @@ +/** @addtogroup MCP + * @{ + * The MCP defines commands and responses which are used to control the MobiCore system. + * MCP information is exchanged in a world share memory buffer which has been established prior between NWd + * and SWd using the FastCall interface. The buffer needs to be provided by the MobiCore driver and is utilized + * to send MCP commands to the MobiCore as well as receiving responses from the MobiCore. + * The command of the normal world will be overwritten with the response from the secure side. + * + * @file + * MCP command interface definitions. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCP_H_ +#define MCP_H_ + +#include "mcUuid.h" +#include "mcLoadFormat.h" +#include "mcVersionInfo.h" + +/** MobiCore Return Code Defines. + * List of the possible MobiCore return codes. + */ +typedef enum { + MC_MCP_RET_OK = 0, /**< Memory has successfully been mapped. */ + MC_MCP_RET_ERR_INVALID_SESSION = 1, /**< The session ID is invalid. */ + MC_MCP_RET_ERR_UNKNOWN_UUID = 2, /**< The UUID of the Trustlet is unknown. */ + MC_MCP_RET_ERR_UNKNOWN_DRIVER_ID = 3, /**< The ID of the driver is unknown. */ + MC_MCP_RET_ERR_NO_MORE_SESSIONS = 4, /**< No more session are allowed. */ + MC_MCP_RET_ERR_CONTAINER_INVALID = 5, /**< The container is invalid. */ + MC_MCP_RET_ERR_TRUSTLET_INVALID = 6, /**< The Trustlet is invalid. */ + MC_MCP_RET_ERR_ALREADY_MAPPED = 7, /**< The memory block has already been mapped before. */ + MC_MCP_RET_ERR_INVALID_PARAM = 8, /**< Alignment or length error in the command parameters. */ + MC_MCP_RET_ERR_OUT_OF_RESOURCES = 9, /**< No space left in the virtual address space of the session. */ + MC_MCP_RET_ERR_INVALID_WSM = 10, /**< WSM type unknown or broken WSM */ + MC_MCP_RET_ERR_UNKNOWN = 11, /**< unknown error. */ + MC_MCP_RET_ERR_INVALID_MAPPING_LENGTH = 12, /**< Lenght of map invalid */ + MC_MCP_RET_ERR_MAPPING_TARGET = 13, /**< Map can only be applied to Trustlet session */ + MC_MCP_RET_ERR_OUT_OF_CRYPTO_RESSOURCES = 14, /**< Couldn't open crypto session. */ + MC_MCP_RET_ERR_SIGNATURE_VERIFICATION_FAILED = 15, /**< System Trustlet signature verification failed. */ + MC_MCP_RET_ERR_WRONG_PUBLIC_KEY = 16, /**< System Trustlet public key is wrong. */ + MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH = 17, /**< Wrong containter type(s). */ + MC_MCP_RET_ERR_CONTAINER_LOCKED = 18, /**< Container is locked (or not activated). */ + MC_MCP_RET_ERR_SP_NO_CHILD = 19, /**< SPID is not registered with root container. */ + MC_MCP_RET_ERR_TL_NO_CHILD = 20, /**< UUID is not registered with sp container. */ + MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED = 21, /**< Unwrapping of root container failed. */ + MC_MCP_RET_ERR_UNWRAP_SP_FAILED = 22, /**< Unwrapping of service provider container failed. */ + MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED = 23, /**< Unwrapping of Trustlet container failed. */ + MC_MCP_RET_ERR_CONTAINER_VERSION_MISMATCH = 24, /**< Container version mismatch. */ + MC_MCP_RET_ERR_SP_TL_DECRYPTION_FAILED = 25, /**< Decryption of service provider trustlet failed. */ + MC_MCP_RET_ERR_SP_TL_HASH_CHECK_FAILED = 26, /**< Hash check of service provider trustlet failed. */ + MC_MCP_RET_ERR_LAUNCH_TASK_FAILED = 27, /**< Activation/starting of task failed. */ + + // used for command verification + MC_MCP_RET_ERR_UNKNOWN_COMMAND = 50, /**< The command is unknown. */ + MC_MCP_RET_ERR_INVALID_DATA = 51 /**< The command data is invalid. */ +} mcpResult_t; + +/** Possible MCP Command IDs + * Command ID must be between 0 and 0x7FFFFFFF. + */ +typedef enum { + MC_MCP_CMD_ID_INVALID = 0x00000000, /**< Invalid command ID. */ + // Session commands + MC_MCP_CMD_OPEN_SESSION = 0x00000001, /**< Open a session to a service. */ + MC_MCP_CMD_CLOSE_SESSION = 0x00000003, /**< Close an existing service session. */ + MC_MCP_CMD_MAP = 0x00000004, /**< Map a block of WSM to a session. */ + MC_MCP_CMD_UNMAP = 0x00000005, /**< Unmap a block of WSM from a session. */ + MC_MCP_CMD_SUSPEND = 0x00000006, /**< Prepare MobiCore for suspend. */ + MC_MCP_CMD_RESUME = 0x00000007, /**< Resume MobiCore from suspension. */ + MC_MCP_CMD_DONATE_RAM = 0x00000008, /**< Donate RAM to MobiCore. */ + MC_MCP_CMD_GET_MOBICORE_VERSION = 0x00000009, /**< Get MobiCore version information. */ +} mcpCmdId_t; + + +#define FLAG_RESPONSE (1U << 31) /**< Flag to indicate that this is the response to a MCP command. */ + + +/** Types of WSM known to the MobiCore. + */ +typedef enum { + WSM_INVALID = 0, /**< Invalid memory type */ + WSM_CONTIGUOUS = 1, /**< Reference to WSM points to a contiguous region of pages. */ + WSM_L2 = 2, /**< Reference to WSM points to an L2 table describing the memory region to share */ +}wsmType_t; + +/** Types of RAM known to the MobiCore. + */ +typedef enum { + RAM_INVALID = 0, /**< Invalid memory type */ + RAM_GENERIC = 1, /**< Generic RAM of no special type. */ +}ramType_t; + +/** Command header. + * It just contains the command ID. Only values specified in mcpCmdId_t are allowed as command IDs. + * If the command ID is unspecified the MobiCore returns an empty response with the result set to MC_MCP_RET_ERR_UNKNOWN_COMMAND . + */ +typedef struct { + mcpCmdId_t cmdId; /**< Command ID of the command */ +} commandHeader_t, *commandHeader_ptr; + +/** Response header. + * MobiCore will reply to every MCP command with an MCP response. Like the MCP command the response consists of a + * header followed by response data. The response is written to the same memory location as the MCP command. + */ +typedef struct { + uint32_t rspId; /**< Command ID | FLAG_RESPONSE. */ + mcpResult_t result; /**< Result informs about the execution result of the command associated with the response. */ +} responseHeader_t, *responseHeader_ptr; + + + +/** @defgroup CMD MCP Commands + * @{ */ + +/** @defgroup ASMCMD Administrative Commands + * @{ */ + +/** @defgroup MCPDONATERAM DONATE_RAM + * Donate NWd RAM to MobiCore. + * This is a debug feature that is not available in release version. + * + * @{ */ + +/** Donate RAM Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ + ramType_t ramType; /**< Type of RAM used for memory pool */ + uint32_t adrBuffer; /**< Physical address of the page range*/ + uint32_t numPages; /**< Number of pages contained in the donation. */ +} mcpCmdDonateRam_t, *mcpCmdDonateRam_ptr; + +/** Donate RAM Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ +} mcpRspDonateRam_t, *mcpRspDonateRam_ptr; +/** @} */// End MCPDONATERAM + + +/** @defgroup MCPGETMOBICOREVERSION GET_MOBICORE_VERSION + * Get MobiCore version info. + * + * @{ */ + +/** Get MobiCore Version Command. */ +typedef struct { + commandHeader_t cmdHeader; /** Command header. */ +} mcpCmdGetMobiCoreVersion_t, *mcpCmdGetMobiCoreVersion_ptr; + +/** Get MobiCore Version Command Response. */ +typedef struct { + responseHeader_t rspHeader; /** Response header. */ + mcVersionInfo_t versionInfo; /** MobiCore version info. */ +} mcpRspGetMobiCoreVersion_t, *mcpRspGetMobiCoreVersion_ptr; + +/** @} */// End MCPGETMOBICOREVERSION + +/** @} */// End ASMCMD + + +/** @defgroup POWERCMD Power Management Commands + * @{ */ + +/** @defgroup MCPSUSPEND SUSPEND + * Prepare MobiCore suspension. + * This command allows MobiCore and MobiCore drivers to release or clean resources and save device state. + * + * @{ */ + +/** Suspend Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ +} mcpCmdSuspend_t, *mcpCmdSuspend_ptr; + +/** Suspend Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ +} mcpRspSuspend_t, *mcpRspSuspend_ptr; +/** @} */// End MCPSUSPEND + + +/** @defgroup MCPRESUME RESUME + * Resume MobiCore from suspension. + * This command allows MobiCore and MobiCore drivers to reinitialize hardware affected by suspension. + * + * @{ */ + +/** Resume Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ +} mcpCmdResume_t, *mcpCmdResume_ptr; + +/** Resume Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ +} mcpRspResume_t, *mcpRspResume_ptr; + +/** @} */// End MCPRESUME + +/** @} */// End POWERCMD + + + +/** @defgroup SESSCMD Session Management Commands + * @{ */ + +/** @defgroup MCPOPEN OPEN + * Load and open a session to a Trustlet. + * The OPEN command loads Trustlet data to the MobiCore context and opens a session to the Trustlet. + * If wsmTypeLoadData is WSM_INVALID MobiCore tries to start a pre-installed Trustlet + * associated with the uuid passed. + * The uuid passed must match the uuid contained in the load data (if available). + * On success, MobiCore returns the session ID which can be used for further communication. + * @{ */ + +/** Open Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ + mcUuid_t uuid; /**< Byte array containing the service UUID. */ + wsmType_t wsmTypeTci; /**< Type of WSM used for the TCI */ + uint32_t adrTciBuffer; /**< Physical address of the TCI */ + uint32_t ofsTciBuffer; /**< Offset to the data. */ + uint32_t lenTciBuffer; /**< Length of the TCI. */ + wsmType_t wsmTypeLoadData; /**< Type of the memory containing the data to load. */ + uint32_t adrLoadData; /**< Physical address of the data to load. */ + uint32_t ofsLoadData; /**< Offset to the data. */ + uint32_t lenLoadData; /**< Length of the data to load. */ + mclfHeader_t tlHeader; /**< Service header. */ +} mcpCmdOpen_t, *mcpCmdOpen_ptr; + +/** Open Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ + uint32_t sessionId; /**< Session ID used for further communication. */ +} mcpRspOpen_t, *mcpRspOpen_ptr; + +/** @} */// End MCPOPEN + + +/** @defgroup MCPCLOSE CLOSE + * Close an existing session to a Trustlet. + * The CLOSE command terminates a session and frees all resources in the MobiCore system which + * are currently occupied by the session. Before closing the session, the MobiCore runtime + * management waits until all pending operations, like calls to drivers, invoked by the Trustlet + * have been terminated. + * Mapped memory will automatically be unmapped from the MobiCore context. The NWd is responsible for + * processing the freed memory according to the Rich-OS needs. + * + * @{ */ + +/** Close Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ + uint32_t sessionId; /**< Session ID. */ +} mcpCmdClose_t, *mcpCmdClose_ptr; + +/** Close Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ +} mcpRspClose_t, *mcpRspClose_ptr; + +/** @} */// End MCPCLOSE + + +/** @defgroup MCPMAP MAP + * Map a portion of memory to a session. + * The MAP command provides a block of memory to the context of a service. + * The memory then becomes world-shared memory (WSM). + * The WSM can either be normal anonymous memory from malloc() or be a + * block of page aligned, contiguous memory. + * The only allowed memory type here is WSM_L2. + * @{ */ + +/** Map Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ + uint32_t sessionId; /**< Session ID of a valid session */ + wsmType_t wsmType; /**< Type of WSM used of the memory*/ + uint32_t adrBuffer; /**< Physical address of the memory */ + uint32_t ofsBuffer; /**< Offset to the payload. */ + uint32_t lenBuffer; /**< Length of the buffer. */ +} mcpCmdMap_t, *mcpCmdMap_ptr; + +#define MCP_MAP_MAX 0x100000 /**< Maximum allowed length for MCP map. */ + +/** Map Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ + uint32_t secureVirtualAdr; /**< Virtual address in the context of the service the WSM is mapped to, already includes a possible offset! */ +} mcpRspMap_t, *mcpRspMap_ptr; + +/** @} *///End MCPMAP + + +/** @defgroup MCPUNMAP UNMAP + * Unmap a portion of world-shared memory from a session. + * The UNMAP command is used to unmap a previously mapped block of + * world shared memory from the context of a session. + * + * Attention: The memory block will be immediately unmapped from the specified session. + * If the service is still accessing the memory, the service will trigger a segmentation fault. + * @{ */ + +/** Unmap Command */ +typedef struct { + commandHeader_t cmdHeader; /**< Command header. */ + uint32_t sessionId; /**< Session ID of a valid session */ + wsmType_t wsmType; /**< Type of WSM used of the memory*/ + uint32_t secureVirtualAdr; /**< Virtual address in the context of the service the WSM has been mapped to, already includes a possible offset! */ + uint32_t lenVirtualBuffer; /**< Length of the virtual buffer. */ +} mcpCmdUnmap_t, *mcpCmdUnmap_ptr; + +/** Unmap Command Response */ +typedef struct { + responseHeader_t rspHeader; /**< Response header. */ +} mcpRspUnmap_t, *mcpRspUnmap_ptr; + +/** @} */// End MCPUNMAP + +/** @} */// End SESSCMD + +/** @} */// End CMD + +/** Structure of the MCP buffer. */ +typedef union { + commandHeader_t cmdHeader; /**< Command header. */ + responseHeader_t rspHeader; /**< Response header. */ + mcpCmdOpen_t cmdOpen; /**< Load and open service. */ + mcpRspOpen_t rspOpen; /**< Response to load and open service. */ + mcpCmdClose_t cmdClose; /**< Close command. */ + mcpRspClose_t rspClose; /**< Response to close command. */ + mcpCmdMap_t cmdMap; /**< Map WSM to service context. */ + mcpRspMap_t rspMap; /**< Response to MAP command. */ + mcpCmdUnmap_t cmdUnmap; /**< Unmap WSM from service context. */ + mcpRspUnmap_t rspUnmap; /**< Response to UNMAP command. */ + mcpCmdSuspend_t cmdSuspend; /**< Suspend MobiCore. */ + mcpRspSuspend_t rspSuspend; /**< Response to SUSPEND command. */ + mcpCmdResume_t cmdResume; /**< Resume MobiCore. */ + mcpRspResume_t rspResume; /**< Response to RESUME command. */ + mcpCmdDonateRam_t cmdDonateRam; /**< Donate RAM to MobiCore. */ + mcpRspDonateRam_t rspDonateRam; /**< Response to DONATE_RAM command. */ + mcpCmdGetMobiCoreVersion_t cmdGetMobiCoreVersion; /**< Get MobiCore Version command. */ + mcpRspGetMobiCoreVersion_t rspGetMobiCoreVersion; /**< Response to GET_MOBICORE_VERSION command. */ +} mcpMessage_t, *mcpMessage_ptr; + + +#define MIN_MCP_LEN sizeof(mcpMessage_t) /**< Minimum MCP buffer length (in bytes). */ + +#define MC_FLAG_NO_SLEEP_REQ 0 +#define MC_FLAG_REQ_TO_SLEEP 1 + +#define MC_STATE_NORMAL_EXECUTION 0 +#define MC_STATE_READY_TO_SLEEP 1 + +typedef struct { + uint16_t SleepReq; + uint16_t ReadyToSleep; +} mcSleepMod_t, *mcSleepMod_ptr; + +/** MobiCore status flags */ +typedef struct { + uint32_t schedule; /**< Scheduling hint: if <> MC_FLAG_SCHEDULE_IDLE, MobiCore should be scheduled by the NWd */ + mcSleepMod_t sleepMode; /**< */ + uint32_t RFU2; /**< Reserved for future use: Must not be interpreted */ + uint32_t RFU3; /**< Reserved for future use: Must not be interpreted */ +} mcFlags_t, *mcFlags_ptr; + +#define MC_FLAG_SCHEDULE_IDLE 0 /**< MobiCore is idle. No scheduling required. */ +#define MC_FLAG_SCHEDULE_NON_IDLE 1 /**< MobiCore is non idle, scheduling is required. */ + + + +/** MCP buffer structure */ +typedef struct { + mcFlags_t mcFlags; /**< MobiCore Flags */ + mcpMessage_t mcpMessage; /**< MCP message buffer */ +} mcpBuffer_t, *mcpBuffer_ptr; + +/** @} */ +#endif /* MCP_H_ */ diff --git a/mobicore/common/MobiCore/inc/Mci/mcinq.h b/mobicore/common/MobiCore/inc/Mci/mcinq.h new file mode 100644 index 0000000..ad2a763 --- /dev/null +++ b/mobicore/common/MobiCore/inc/Mci/mcinq.h @@ -0,0 +1,108 @@ +/** @addtogroup NQ + * @{ + * Notifications inform the MobiCore runtime environment that information is pending in a WSM buffer. + * The Trustlet Connector (TLC) and the corresponding trustlet also utilize this buffer to notify + * each other about new data within the Trustlet Connector Interface (TCI). + * + * The buffer is set up as a queue, which means that more than one notification can be written to the buffer + * before the switch to the other world is performed. Each side therefore facilitates an incoming and an + * outgoing queue for communication with the other side. + * + * Notifications hold the session ID, which is used to reference the communication partner in the other world. + * So if, e.g., the TLC in the normal world wants to notify his trustlet about new data in the TLC buffer + * + * @file + * Notification queue declarations. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 NQ_H_ +#define NQ_H_ + +/** \name NQ Size Defines + * Minimum and maximum count of elements in the notification queue. + * @{ */ +#define MIN_NQ_ELEM 1 /**< Minimum notification queue elements. */ +#define MAX_NQ_ELEM 64 /**< Maximum notification queue elements. */ +/** @} */ + +/** \name NQ Length Defines + * Minimum and maximum notification queue length. + * @{ */ +#define MIN_NQ_LEN (MIN_NQ_ELEM * sizeof(notification_t)) /**< Minimum notification length (in bytes). */ +#define MAX_NQ_LEN (MAX_NQ_ELEM * sizeof(notification_t)) /**< Maximum notification length (in bytes). */ +/** @} */ + +/** \name Session ID Defines + * Standard Session IDs. + * @{ */ +#define SID_MCP 0 /**< MCP session ID is used when directly communicating with the MobiCore (e.g. for starting and stopping of trustlets). */ +#define SID_INVALID 0xffffffff /**< Invalid session id is returned in case of an error. */ +/** @} */ + +/** Notification data structure. */ +typedef struct{ + uint32_t sessionId; /**< Session ID. */ + int32_t payload; /**< Additional notification information. */ +} notification_t; + +/** Notification payload codes. + * 0 indicated a plain simple notification, + * a positive value is a termination reason from the task, + * a negative value is a termination reason from MobiCore. + * Possible negative values are given below. + */ +typedef enum { + ERR_INVALID_EXIT_CODE = -1, /**< task terminated, but exit code is invalid */ + ERR_SESSION_CLOSE = -2, /**< task terminated due to session end, no exit code available */ + ERR_INVALID_OPERATION = -3, /**< task terminated due to invalid operation */ + ERR_INVALID_SID = -4, /**< session ID is unknown */ + ERR_SID_NOT_ACTIVE = -5 /**< session is not active */ +} notificationPayload_t; + +/** Declaration of the notification queue header. + * layout as specified in the data structure specification. + */ +typedef struct { + uint32_t writeCnt; /**< Write counter. */ + uint32_t readCnt; /**< Read counter. */ + uint32_t queueSize; /**< Queue size. */ +} notificationQueueHeader_t; + +/** Queue struct which defines a queue object. + * The queue struct is accessed by the queue<operation> type of + * function. elementCnt must be a power of two and the power needs + * to be smaller than power of uint32_t (obviously 32). + */ +typedef struct { + notificationQueueHeader_t hdr; /**< Queue header. */ + notification_t notification[MIN_NQ_ELEM]; /**< Notification elements. */ +} notificationQueue_t; + +#endif /** NQ_H_ */ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/Mci/version.h b/mobicore/common/MobiCore/inc/Mci/version.h new file mode 100644 index 0000000..c1eab01 --- /dev/null +++ b/mobicore/common/MobiCore/inc/Mci/version.h @@ -0,0 +1,34 @@ +/** + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCI_VERSION_H_ +#define MCI_VERSION_H_ + +#define MCI_VERSION_MAJOR 0 +#define MCI_VERSION_MINOR 4 + +#endif /** MCI_VERSION_H_ */ diff --git a/mobicore/common/MobiCore/inc/TlCm/cmp.h b/mobicore/common/MobiCore/inc/TlCm/cmp.h new file mode 100644 index 0000000..2493669 --- /dev/null +++ b/mobicore/common/MobiCore/inc/TlCm/cmp.h @@ -0,0 +1,1624 @@ +/** @addtogroup CMP + * Content Management Protocol Definitions. + * + * The CMP (Content Management Protocol) is based on the TCI (Trustlet Control + * Interface) and defines commands/responses between the content management + * trustlet (CMTL) and the content management trustlet connector (CMTLC) and/or + * the remote backend. + * + * @{ + * + * @file + * CMP global definitions. + * Various components need access to (sub-)structures defined and used by CMP; + * these common definitions are made available through this header file. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CMP_H_ +#define CMP_H_ + +#include "mcContainer.h" +#include "mcUuid.h" +#include "mcVersionInfo.h" +#include "version.h" + +typedef uint32_t cmpCommandId_t; +typedef uint32_t cmpResponseId_t; +typedef uint32_t cmpReturnCode_t; + +/** Responses have bit 31 set */ +#define RSP_ID_MASK (1U << 31) +#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK) +#define IS_CMD(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == 0) +#define IS_RSP(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == RSP_ID_MASK) + +/** + * CMP command header. + */ +typedef struct { + /** Command ID. */ + cmpCommandId_t commandId; +} cmpCommandHeader_t; + +/** + * CMP response header. + */ +typedef struct{ + /** Response ID (must be command ID | RSP_ID_MASK ). */ + cmpResponseId_t responseId; + /** Return code of command. */ + cmpReturnCode_t returnCode; +} cmpResponseHeader_t; + +/** SHA256 checksum. */ +typedef struct { + uint8_t data[32]; +} cmpSha256_t; + +/** Key size of encryption algorithm used for secure messaging. */ +#define CMP_MSG_KEY_SIZE 32 + +/** Block size of the encryption algorithm used for secure messaging. */ +#define CMP_MSG_CRYPTO_BLOCK_SIZE 16 + +/** Total number of padding bytes required to encrypt data of given size. */ +#define CMP_ED_PADDING(netsize) (CMP_MSG_CRYPTO_BLOCK_SIZE - (netsize) % CMP_MSG_CRYPTO_BLOCK_SIZE) + +/** Total number of bytes used for message authentication code (MAC). */ +#define CMP_MAC_SIZE 32 // HMAC-SHA256 + +/** Total number of bytes used for PSS signature in GENERATE AUTH TOKEN command. */ +#define CMP_GEN_AUTH_TOKEN_PSS_SIZE 256 + +/** Message authentication code. */ +typedef struct { + uint8_t mac[CMP_MAC_SIZE]; +} cmpMac_t; + +/** 64-bit random number. */ +typedef struct { + uint8_t data[8]; +} cmpRnd8_t; + +/** 256-bit random number. */ +typedef struct { + uint8_t data[32]; +} cmpRnd32_t; + +/** Version tags. */ +typedef enum { + CMP_VERSION_TAG1 = 0x00000001, // Deprecated. + CMP_VERSION_TAG2 = 0x00000002, +} cmpVersionTag_t; + +/** Version data for version tag 1. */ +typedef struct { + uint32_t number; +} cmpVersionData1_t; + +/** Version data for version tag 2. */ +typedef struct { + mcVersionInfo_t versionInfo; +} cmpVersionData2_t; + +/** Version data. */ +typedef union { + cmpVersionData1_t versionData1; + cmpVersionData2_t versionData2; +} cmpVersionData_t; + +/** @defgroup MC_CMP_CMD_GET_VERSION +* @{ */ + +/** @defgroup MC_CMP_CMD_GET_VERSION_CMD Command +* @{ */ + +/** GetVersion command. */ +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpCmdGetVersion_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_GET_VERSION_RSP Response +* @{ */ + +/** GetSuid response. */ +typedef struct { +cmpResponseHeader_t rspHeader; + cmpVersionTag_t tag; + cmpVersionData_t data; +} cmpRspGetVersion_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN + * @{ */ + +/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSuid_t suid; + mcSymmetricKey_t kSocAuth; + uint32_t kid; +} cmpGenAuthTokenCmdSdata_t; + +typedef struct { + cmpGenAuthTokenCmdSdata_t sdata; + uint8_t pssSignature[CMP_GEN_AUTH_TOKEN_PSS_SIZE]; +} cmpGenAuthTokenCmd_t; + +/** GenAuthToken command. */ +typedef struct { + cmpGenAuthTokenCmd_t cmd; +} cmpCmdGenAuthToken_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_RSP Response + * @{ */ + +typedef struct { + cmpResponseHeader_t rspHeader; + // No MAC. +} cmpGenAuthTokenRsp_t; + +/** GenAuthToken response. */ +typedef struct { + cmpGenAuthTokenRsp_t rsp; + mcSoAuthTokenCont_t soAuthCont; +} cmpRspGenAuthToken_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION + * @{ */ + +/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpBeginSocAuthenticationCmd_t; + +/** BeginSocAuthentication command. */ +typedef struct { + cmpBeginSocAuthenticationCmd_t cmd; + mcSoAuthTokenCont_t soAuthTokenCont; +} cmpCmdBeginSocAuthentication_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_RSP Response + * @{ */ + +typedef struct { + cmpResponseHeader_t rspHeader; + mcSuid_t suid; + cmpRnd8_t rnd1; +} cmpBeginSocAuthenticationRspSdata_t; + +typedef struct { + cmpBeginSocAuthenticationRspSdata_t sdata; + cmpMac_t mac; +} cmpBeginSocAuthenticationRsp_t; + +/** BeginSocAuthentication response. */ +typedef struct { + cmpBeginSocAuthenticationRsp_t rsp; +} cmpRspBeginSocAuthentication_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION + * @{ */ + +/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpBeginRootAuthenticationCmd_t; + +/** BeginRootAuthentication command. */ +typedef struct { + cmpBeginRootAuthenticationCmd_t cmd; + mcSoRootCont_t soRootCont; +} cmpCmdBeginRootAuthentication_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_RSP Response + * @{ */ + +typedef struct { + cmpResponseHeader_t rspHeader; + mcSuid_t suid; + cmpRnd8_t rnd1; +} cmpBeginRootAuthenticationRspSdata_t; + +typedef struct { + cmpBeginRootAuthenticationRspSdata_t sdata; + cmpMac_t mac; +} cmpBeginRootAuthenticationRsp_t; + +/** BeginRootAuthentication response. */ +typedef struct { + cmpBeginRootAuthenticationRsp_t rsp; +} cmpRspBeginRootAuthentication_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION + * @{ */ + +/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_CMD Command + * @{ */ +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; +} cmpBeginSpAuthenticationCmdSdata_t; + +typedef struct { + cmpBeginSpAuthenticationCmdSdata_t sdata; +} cmpBeginSpAuthenticationCmd_t; + +/** BeginSpAuthentication command. */ +typedef struct { + cmpBeginSpAuthenticationCmd_t cmd; + mcSoRootCont_t soRootCont; + mcSoSpCont_t soSpCont; +} cmpCmdBeginSpAuthentication_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_RSP Response + * @{ */ +typedef struct { + cmpResponseHeader_t rspHeader; + mcSuid_t suid; + mcSpid_t spid; + cmpRnd8_t rnd1; +} cmpBeginSpAuthenticationRspSdata_t; + +typedef struct { + cmpBeginSpAuthenticationRspSdata_t sdata; + cmpMac_t mac; +} cmpBeginSpAuthenticationRsp_t; + +/** BeginSpAuthentication response. */ +typedef struct { + cmpBeginSpAuthenticationRsp_t rsp; +} cmpRspBeginSpAuthentication_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_AUTHENTICATE + * @{ */ + +/** @defgroup MC_CMP_CMD_AUTHENTICATE_CMD Command + * @{ */ +typedef struct { + mcSuid_t suid; + uint32_t entityId; + cmpRnd8_t rnd2; + cmpRnd8_t rnd1; + cmpRnd32_t k2; +} cmpAuthMsgEdata_t; + +typedef struct { + cmpAuthMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthMsgEdata_t))]; +} cmpAuthCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + cmpAuthCmdEd_t ed; +} cmpAuthCmdSdata_t; + +typedef struct { + cmpAuthCmdSdata_t sdata; + cmpMac_t mac; +} cmpAuthenticateCmd_t; + +/** Authenticate command. */ +typedef struct { + cmpAuthenticateCmd_t cmd; +} cmpCmdAuthenticate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_AUTHENTICATE_RSP Response + * @{ */ +typedef struct { + mcSuid_t suid; + uint32_t entityId; + cmpRnd8_t rnd1; + cmpRnd8_t rnd2; + cmpRnd32_t k1; +} cmpAuthRspEdata_t; + +typedef struct { + cmpAuthRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthRspEdata_t))]; +} cmpAuthRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpAuthRspEd_t ed; +} cmpAuthRspSdata_t; + +typedef struct { + cmpAuthRspSdata_t sdata; + cmpMac_t mac; +} cmpAuthenticateRsp_t; + +/** Authenticate response. */ +typedef struct { + cmpAuthenticateRsp_t rsp; +} cmpRspAuthenticate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE + * @{ */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_CMD Command + * @{ */ + +typedef struct { + mcSymmetricKey_t kRootAuth; +} cmpRootRegActMsgEdata_t; + +typedef struct { + cmpRootRegActMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActMsgEdata_t))]; +} cmpRootRegActCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcRootid_t rootid; + cmpRootRegActCmdEd_t ed; +} cmpRootRegActCmdSdata_t; + +typedef struct { + cmpRootRegActCmdSdata_t sdata; + cmpMac_t mac; +} cmpRootContRegisterActivateCmd_t; + +/** RootContRegisterActivate command. */ +typedef struct { + cmpRootContRegisterActivateCmd_t cmd; +} cmpCmdRootContRegisterActivate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_RSP Response + * @{ */ + +typedef struct { + mcSoRootCont_t soRootCont; +} cmpRootRegActRspEdata_t; + +typedef struct { + cmpRootRegActRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActRspEdata_t))]; +} cmpRootRegActRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpRootRegActRspEd_t ed; +} cmpRootRegActRspSdata_t; + +typedef struct { + cmpRootRegActRspSdata_t sdata; + cmpMac_t mac; +} cmpRootContRegisterActivateRsp_t; + +/** RooContRegisterActivate response. */ +typedef struct { + cmpRootContRegisterActivateRsp_t rsp; + mcSoRootCont_t soRootCont; +} cmpRspRootContRegisterActivate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER + * @{ */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_CMD Command + * @{ */ + +typedef struct { + mcSuid_t suid; + mcSoAuthTokenCont_t soAuthTokenCont; +} cmpRootUnregMsgEdata_t; + +typedef struct { + cmpRootUnregMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregMsgEdata_t))]; +} cmpRootUnregCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + cmpRootUnregCmdEd_t ed; +} cmpRootUnregCmdSdata_t; + +typedef struct { + cmpRootUnregCmdSdata_t sdata; + cmpMac_t mac; +} cmpRootContUnregisterCmd_t; + +/** RootContUnregister command. */ +typedef struct { + cmpRootContUnregisterCmd_t cmd; +} cmpCmdRootContUnregister_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_RSP Response + * @{ */ + +typedef struct { + mcSuid_t suid; +} cmpRootUnregRspEdata_t; + +typedef struct { + cmpRootUnregRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregRspEdata_t))]; +} cmpRootUnregRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpRootUnregRspEd_t ed; +} cmpRootUnregRspSdata_t; + +typedef struct { + cmpRootUnregRspSdata_t sdata; + cmpMac_t mac; +} cmpRootContUnregisterRsp_t; + +/** RootContUnregister response. */ +typedef struct { + cmpRootContUnregisterRsp_t rsp; + mcSoAuthTokenCont_t soAuthTokenCont; +} cmpRspRootContUnregister_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT + * @{ */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpRootLockByRootCmdSdata_t; + +typedef struct { + cmpRootLockByRootCmdSdata_t sdata; + cmpMac_t mac; +} cmpRootContLockByRootCmd_t; + +/** RootContLockByRoot command. */ +typedef struct { + cmpRootContLockByRootCmd_t cmd; +} cmpCmdRootContLockByRoot_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_RSP Response + * @{ */ + +typedef struct { + mcSoRootCont_t soRootCont; +} cmpRootLockByRootRspEdata_t; + +typedef struct { + cmpRootLockByRootRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootLockByRootRspEdata_t))]; +} cmpRootLockByRootRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpRootLockByRootRspEd_t ed; +} cmpRootLockByRootRspSdata_t; + +typedef struct { + cmpRootLockByRootRspSdata_t sdata; + cmpMac_t mac; +} cmpRootContLockByRootRsp_t; + +/** RootContLockByRoot response. */ +typedef struct { + cmpRootContLockByRootRsp_t rsp; + mcSoRootCont_t soRootCont; +} cmpRspRootContLockByRoot_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT + * @{ */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpRootUnlockByRootCmdSdata_t; + +typedef struct { + cmpRootUnlockByRootCmdSdata_t sdata; + cmpMac_t mac; +} cmpRootContUnlockByRootCmd_t; + +/** RootContUnlockByRoot command. */ +typedef struct { + cmpRootContUnlockByRootCmd_t cmd; +} cmpCmdRootContUnlockByRoot_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_RSP Response + * @{ */ + +typedef struct { + mcSoRootCont_t soRootCont; +} cmpRootUnlockByRootRspEdata_t; + +typedef struct { + cmpRootUnlockByRootRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnlockByRootRspEdata_t))]; +} cmpRootUnlockByRootRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpRootUnlockByRootRspEd_t ed; +} cmpRootUnlockByRootRspSdata_t; + +typedef struct { + cmpRootUnlockByRootRspSdata_t sdata; + cmpMac_t mac; +} cmpRootContUnlockByRootRsp_t; + +/** RootContUnlockByRoot response. */ +typedef struct { + cmpRootContUnlockByRootRsp_t rsp; + mcSoRootCont_t soRootCont; +} cmpRspRootContUnlockByRoot_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_CMD Command + * @{ */ + +typedef struct { + mcSymmetricKey_t kSpAuth; +} cmpSpRegActMsgEdata_t; + +typedef struct { + cmpSpRegActMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActMsgEdata_t))]; +} cmpSpRegActCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + cmpSpRegActCmdEd_t ed; +} cmpSpRegActCmdSdata_t; + +typedef struct { + cmpSpRegActCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContRegisterActivateCmd_t; + +/** SpContRegisterActivate command. */ +typedef struct { + cmpSpContRegisterActivateCmd_t cmd; +} cmpCmdSpContRegisterActivate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_RSP Response + * @{ */ + +typedef struct { + mcSoRootCont_t soRootCont; + mcSoSpCont_t soSpCont; +} cmpSpRegActRspEdata_t; + +typedef struct { + cmpSpRegActRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActRspEdata_t))]; +} cmpSpRegActRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpRegActRspEd_t ed; +} cmpSpRegActRspSdata_t; + +typedef struct { + cmpSpRegActRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContRegisterActivateRsp_t; + +/** SpContRegisterActivate response. */ +typedef struct { + cmpSpContRegisterActivateRsp_t rsp; + mcSoRootCont_t soRootCont; + mcSoSpCont_t soSpCont; +} cmpRspSpContRegisterActivate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_CMD Command + * @{ */ + +typedef struct { + mcSymmetricKey_t kSpAuth; +} cmpSpRegisterMsgEdata_t; + +typedef struct { + cmpSpRegisterMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterMsgEdata_t))]; +} cmpSpRegisterCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + cmpSpRegisterCmdEd_t ed; +} cmpSpRegisterCmdSdata_t; + +typedef struct { + cmpSpRegisterCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContRegisterCmd_t; + +/** SpContRegister command. */ +typedef struct { + cmpSpContRegisterCmd_t cmd; +} cmpCmdSpContRegister_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_RSP Response + * @{ */ + +typedef struct { + mcSoRootCont_t soRootCont; + mcSoSpCont_t soSpCont; +} cmpSpRegisterRspEdata_t; + +typedef struct { + cmpSpRegisterRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterRspEdata_t))]; +} cmpSpRegisterRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpRegisterRspEd_t ed; +} cmpSpRegisterRspSdata_t; + +typedef struct { + cmpSpRegisterRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContRegisterRsp_t; + +/** SpContRegister response. */ +typedef struct { + cmpSpContRegisterRsp_t rsp; + mcSoRootCont_t soRootCont; + mcSoSpCont_t soSpCont; +} cmpRspSpContRegister_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_CMD Command + * @{ */ + +typedef struct { + mcSymmetricKey_t kSpAuth; +} cmpSpActivateMsgEdata_t; + +typedef struct { + cmpSpActivateMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateMsgEdata_t))]; +} cmpSpActivateCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + cmpSpActivateCmdEd_t ed; +} cmpSpActivateCmdSdata_t; + +typedef struct { + cmpSpActivateCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContActivateCmd_t; + +/** SpContActivate command. */ +typedef struct { + cmpSpContActivateCmd_t cmd; +} cmpCmdSpContActivate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; +} cmpSpActivateRspEdata_t; + +typedef struct { + cmpSpActivateRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateRspEdata_t))]; +} cmpSpActivateRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpActivateRspEd_t ed; +} cmpSpActivateRspSdata_t; + +typedef struct { + cmpSpActivateRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContActivateRsp_t; + +/** SpContActivate response. */ +typedef struct { + cmpSpContActivateRsp_t rsp; + mcSoSpCont_t soSpCont; +} cmpRspSpContActivate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; +} cmpSpContUnregCmdSdata_t; + +typedef struct { + cmpSpContUnregCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContUnregisterCmd_t; + +/** SpContUnregister command. */ +typedef struct { + cmpSpContUnregisterCmd_t cmd; +} cmpCmdSpContUnregister_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_RSP Response + * @{ */ + +typedef struct { + mcSoRootCont_t soRootCont; +} cmpSpUnregRspEdata_t; + +typedef struct { + cmpSpUnregRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnregRspEdata_t))]; +} cmpSpUnregRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpUnregRspEd_t ed; +} cmpSpContUnregRspSdata_t; + +typedef struct { + cmpSpContUnregRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContUnregisterRsp_t; + +/** SpContUnregister response. */ +typedef struct { + cmpSpContUnregisterRsp_t rsp; + mcSoRootCont_t soRootCont; +} cmpRspSpContUnregister_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; +} cmpSpLockByRootCmdSdata_t; + +typedef struct { + cmpSpLockByRootCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContLockByRootCmd_t; + +/** SpContLockByRoot command. */ +typedef struct { + cmpSpContLockByRootCmd_t cmd; + mcSoSpCont_t soSpCont; +} cmpCmdSpContLockByRoot_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; +} cmpSpLockByRootRspEdata_t; + +typedef struct { + cmpSpLockByRootRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpLockByRootRspEdata_t))]; +} cmpSpLockByRootRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpLockByRootRspEd_t ed; +} cmpSpLockByRootRspSdata_t; + +typedef struct { + cmpSpLockByRootRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContLockByRootRsp_t; + +/** SpContLockByRoot response. */ +typedef struct { + cmpSpContLockByRootRsp_t rsp; + mcSoSpCont_t soSpCont; +} cmpRspSpContLockByRoot_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; +} cmpSpUnlockByRootCmdSdata_t; + +typedef struct { + cmpSpUnlockByRootCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContUnlockByRootCmd_t; + +/** SpContUnlockByRoot command. */ +typedef struct { + cmpSpContUnlockByRootCmd_t cmd; + mcSoSpCont_t soSpCont; +} cmpCmdSpContUnlockByRoot_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; +} cmpSpUnlockByRootRspEdata_t; + +typedef struct { + cmpSpUnlockByRootRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnlockByRootRspEdata_t))]; +} cmpSpUnlockByRootRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpUnlockByRootRspEd_t ed; +} cmpSpUnlockByRootRspSdata_t; + +typedef struct { + cmpSpUnlockByRootRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContUnlockByRootRsp_t; + +/** SpContUnlockByRoot response. */ +typedef struct { + cmpSpContUnlockByRootRsp_t rsp; + mcSoSpCont_t soSpCont; +} cmpRspSpContUnlockByRoot_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; +} cmpSpLockBySpCmdSdata_t; + +typedef struct { + cmpSpLockBySpCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContLockBySpCmd_t; + +/** SpContLockBySp command. */ +typedef struct { + cmpSpContLockBySpCmd_t cmd; +} cmpCmdSpContLockBySp_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_RSP Respose + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; +} cmpSpLockBySpRspEdata_t; + +typedef struct { + cmpSpLockBySpRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpLockBySpRspEdata_t))]; +} cmpSpLockBySpRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpLockBySpRspEd_t ed; +} cmpSpLockBySpRspSdata_t; + +typedef struct { + cmpSpLockBySpRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContLockBySpRsp_t; + +/** SpContLockBySp response. */ +typedef struct { + cmpSpContLockBySpRsp_t rsp; + mcSoSpCont_t soSpCont; +} cmpRspSpContLockBySp_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP + * @{ */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; +} cmpSpUnlockBySpCmdSdata_t; + +typedef struct { + cmpSpUnlockBySpCmdSdata_t sdata; + cmpMac_t mac; +} cmpSpContUnlockBySpCmd_t; + +/** SpContUnlockBySp command. */ +typedef struct { + cmpSpContUnlockBySpCmd_t cmd; +} cmpCmdSpContUnlockBySp_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; +} cmpSpUnlockBySpRspEdata_t; + +typedef struct { + cmpSpUnlockBySpRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnlockBySpRspEdata_t))]; +} cmpSpUnlockBySpRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpSpUnlockBySpRspEd_t ed; +} cmpSpUnlockBySpRspSdata_t; + +typedef struct { + cmpSpUnlockBySpRspSdata_t sdata; + cmpMac_t mac; +} cmpSpContUnlockBySpRsp_t; + +/** SpContUnlockBySp response. */ +typedef struct { + cmpSpContUnlockBySpRsp_t rsp; + mcSoSpCont_t soSpCont; +} cmpRspSpContUnlockBySp_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_CMD Command + * @{ */ + +typedef struct { + mcSymmetricKey_t kSpTltEnc; +} cmpTltRegMsgEdata_t; + +typedef struct { + cmpTltRegMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegMsgEdata_t))]; +} cmpTltRegCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; + cmpTltRegCmdEd_t ed; +} cmpTltRegCmdSdata_t; + +typedef struct { + cmpTltRegCmdSdata_t sdata; + cmpMac_t mac; +} cmpTltContRegisterCmd_t; + +/** TltContRegister command. */ +typedef struct { + cmpTltContRegisterCmd_t cmd; +} cmpCmdTltContRegister_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; + mcSoTltCont_t soTltCont; +} cmpTltRegRspEdata_t; + +typedef struct { + cmpTltRegRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegRspEdata_t))]; +} cmpTltRegRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpTltRegRspEd_t ed; +} cmpTltRegRspSdata_t; + +typedef struct { + cmpTltRegRspSdata_t sdata; + cmpMac_t mac; +} cmpTltContRegisterRsp_t; + +/** TltContRegister response. */ +typedef struct { + cmpTltContRegisterRsp_t rsp; + mcSoSpCont_t soSpCont; + mcSoTltCont_t soTltCont; +} cmpRspTltContRegister_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; +} cmpTltActCmdSdata_t; + +typedef struct { + cmpTltActCmdSdata_t sdata; + cmpMac_t mac; +} cmpTltContActivateCmd_t; + +/** TltContActivate command. */ +typedef struct { + cmpTltContActivateCmd_t cmd; + mcSoTltCont_t soTltCont; +} cmpCmdTltContActivate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_RSP Response + * @{ */ + +typedef struct { + mcSoTltCont_t soTltCont; +} cmpTltActRspEdata_t; + +typedef struct { + cmpTltActRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltActRspEdata_t))]; +} cmpTltActRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpTltActRspEd_t ed; +} cmpTltActRspSdata_t; + +typedef struct { + cmpTltActRspSdata_t sdata; + cmpMac_t mac; +} cmpTltContActivateRsp_t; + +/** TltContActivate response. */ +typedef struct { + cmpTltContActivateRsp_t rsp; + mcSoTltCont_t soTltCont; +} cmpRspTltContActivate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_CMD Command + * @{ */ + +typedef struct { + mcSymmetricKey_t kSpTltEnc; +} cmpTltRegActMsgEdata_t; + +typedef struct { + cmpTltRegActMsgEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActMsgEdata_t))]; +} cmpTltRegActCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; + cmpTltRegActCmdEd_t ed; +} cmpTltRegActCmdSdata_t; + +typedef struct { + cmpTltRegActCmdSdata_t sdata; + cmpMac_t mac; +} cmpTltContRegisterActivateCmd_t; + +/** TltContRegisterActivate command. */ +typedef struct { + cmpTltContRegisterActivateCmd_t cmd; +} cmpCmdTltContRegisterActivate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; + mcSoTltCont_t soTltCont; +} cmpTltRegActRspEdata_t; + +typedef struct { + cmpTltRegActRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActRspEdata_t))]; +} cmpTltRegActRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpTltRegActRspEd_t ed; +} cmpTltRegActRspSdata_t; + +typedef struct { + cmpTltRegActRspSdata_t sdata; + cmpMac_t mac; +} cmpTltContRegisterActivateRsp_t; + +/** TltContRegisterActivate response. */ +typedef struct { + cmpTltContRegisterActivateRsp_t rsp; + mcSoSpCont_t soSpCont; + mcSoTltCont_t soTltCont; +} cmpRspTltContRegisterActivate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; +} cmpTltUnregCmdSdata_t; + +typedef struct { + cmpTltUnregCmdSdata_t sdata; + cmpMac_t mac; +} cmpTltContUnregisterCmd_t; + +/** TltContUnregister command. */ +typedef struct { + cmpTltContUnregisterCmd_t cmd; +} cmpCmdTltContUnregister_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_RSP Response + * @{ */ + +typedef struct { + mcSoSpCont_t soSpCont; +} cmpTltUnregRspEdata_t; + +typedef struct { + cmpTltUnregRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltUnregRspEdata_t))]; +} cmpTltUnregRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpTltUnregRspEd_t ed; +} cmpTltUnregRspSdata_t; + +typedef struct { + cmpTltUnregRspSdata_t sdata; + cmpMac_t mac; +} cmpTltContUnregisterRsp_t; + +/** TltContUnregister response. */ +typedef struct { + cmpTltContUnregisterRsp_t rsp; + mcSoSpCont_t soSpCont; +} cmpRspTltContUnregister_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; +} cmpTltLockBySpCmdSdata_t; + +typedef struct { + cmpTltLockBySpCmdSdata_t sdata; + cmpMac_t mac; +} cmpTltContLockBySpCmd_t; + +/** TltContLockBySp command. */ +typedef struct { + cmpTltContLockBySpCmd_t cmd; + mcSoTltCont_t soTltCont; +} cmpCmdTltContLockBySp_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_RSP Response + * @{ */ + +typedef struct { + mcSoTltCont_t soTltCont; +} cmpTltLockBySpRspEdata_t; + +typedef struct { + cmpTltLockBySpRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltLockBySpRspEdata_t))]; +} cmpTltLockBySpRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpTltLockBySpRspEd_t ed; +} cmpTltLockBySpRspSdata_t; + +typedef struct { + cmpTltLockBySpRspSdata_t sdata; + cmpMac_t mac; +} cmpTltContLockBySpRsp_t; + +/** TltContLockBySp response. */ +typedef struct { + cmpTltContLockBySpRsp_t rsp; + mcSoTltCont_t soTltCont; +} cmpRspTltContLockBySp_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_CMD Command + * @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; +} cmpTltUnlockBySpCmdSdata_t; + +typedef struct { + cmpTltUnlockBySpCmdSdata_t sdata; + cmpMac_t mac; +} cmpTltContUnlockBySpCmd_t; + +/** TltContUnlockBySp command. */ +typedef struct { + cmpTltContUnlockBySpCmd_t cmd; + mcSoTltCont_t soTltCont; +} cmpCmdTltContUnlockBySp_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_RSP Response + * @{ */ + +typedef struct { + mcSoTltCont_t soTltCont; +} cmpTltUnlockBySpRspEdata_t; + +typedef struct { + cmpTltUnlockBySpRspEdata_t edata; + uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltUnlockBySpRspEdata_t))]; +} cmpTltUnlockBySpRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + cmpTltUnlockBySpRspEd_t ed; +} cmpTltUnlockBySpRspSdata_t; + +typedef struct { + cmpTltUnlockBySpRspSdata_t sdata; + cmpMac_t mac; +} cmpTltContUnlockBySpRsp_t; + +/** TltContUnlockBySp response. */ +typedef struct { + cmpTltContUnlockBySpRsp_t rsp; + mcSoTltCont_t soTltCont; +} cmpRspTltContUnlockBySp_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_GET_SUID +* @{ */ + +/** @defgroup MC_CMP_CMD_GET_SUID_CMD Command +* @{ */ + +/** GetSuid command. */ +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpCmdGetSuid_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_GET_SUID_RSP Response +* @{ */ + +/** GetSuid response. */ +typedef struct { +cmpResponseHeader_t rspHeader; + mcSuid_t suid; +} cmpRspGetSuid_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE +* @{ */ + +/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_CMD Command +* @{ */ + +typedef struct { + cmpCommandHeader_t cmdHeader; +} cmpAuthenticateTerminateCmdSdata_t; + +typedef struct { + cmpAuthenticateTerminateCmdSdata_t sdata; + cmpMac_t mac; +} cmpAuthenticateTerminateCmd_t; + +/** AuthenticateTerminate command. */ +typedef struct { + cmpAuthenticateTerminateCmd_t cmd; +} cmpCmdAuthenticateTerminate_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_RSP Response +* @{ */ + +typedef struct { + cmpResponseHeader_t rspHeader; +} cmpAuthenticateTerminateRspSdata_t; + +typedef struct { + cmpAuthenticateTerminateRspSdata_t sdata; + cmpMac_t mac; +} cmpTerminateAutenticateRsp_t; + +/** AuthenticateTerminate response. */ +typedef struct { + cmpTerminateAutenticateRsp_t rsp; +} cmpRspAuthenticateTerminate_t; + +/** @} */ + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE + * @{ */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_CMD Command + * @{ */ + +typedef struct { + mcPid_t pid; + mcCoDataCont_t persoData; +} cmpTltContPersonalizeCmdEdata_t; + +typedef struct { + cmpTltContPersonalizeCmdEdata_t edata; + uint8_t padding_[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeCmdEdata_t))]; +} cmpTltContPersonalizeCmdEd_t; + +typedef struct { + cmpCommandHeader_t cmdHeader; + mcSpid_t spid; + mcUuid_t uuid; + uint32_t edLen; + cmpTltContPersonalizeCmdEd_t ed; +} cmpTltContPersonalizeCmdSdata_t; + +typedef struct { + cmpTltContPersonalizeCmdSdata_t sdata; + cmpMac_t mac_; +} cmpTltContPersonalizeCmd_t; + +/** TltContPersonalize command. */ +typedef struct { + cmpTltContPersonalizeCmd_t cmd; + mcSoTltCont_t soTltCont_; +} cmpCmdTltContPersonalize_t; + +/** @} */ + +/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONLIZE_RSP Response + * @{ */ + +typedef struct { + mcSoDataCont_t soDataCont; +} cmpTltContPersonalizeRspEdata_t; + +typedef struct { + cmpTltContPersonalizeRspEdata_t edata; + uint8_t padding_[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeRspEdata_t))]; +} cmpTltContPersonalizeRspEd_t; + +typedef struct { + cmpResponseHeader_t rspHeader; + uint32_t edLen; + cmpTltContPersonalizeRspEd_t ed; +} cmpTltContPersonalizeRspSdata_t; + +typedef struct { + cmpTltContPersonalizeRspSdata_t sdata; + cmpMac_t mac_; +} cmpTltContPersonalizeRsp_t; + +/** TltContPersonalize response. */ +typedef struct { + cmpTltContPersonalizeRsp_t rsp; + mcSoDataCont_t soDataCont_; +} cmpRspTltContPersonalize_t; + + +/** @} */ + +/** @} */ + + +#endif // CMP_H_ + +/** @} */ + diff --git a/mobicore/common/MobiCore/inc/TlCm/tlCmApi.h b/mobicore/common/MobiCore/inc/TlCm/tlCmApi.h new file mode 100644 index 0000000..6428dd2 --- /dev/null +++ b/mobicore/common/MobiCore/inc/TlCm/tlCmApi.h @@ -0,0 +1,184 @@ +/** @addtogroup CMP + * @{ + * @file + * Interface to content management trustlet definitions. + * + * The TlCm (Content Management Trustlet) is responsible for implementing + * CMP commands and generating approriate CMP responses. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 TLCMAPI_H_ +#define TLCMAPI_H_ + +#include "cmp.h" +#include "tlCmError.h" + +/** TlCm command ids. + * List of all commands supported by TlCm. + * @note All command ids must be in range 0 to 0x7FFFFFFF. + */ +//lint -esym(756, cmpCommands_t) cmpCommands_t type by itself not used. +typedef enum cmpCommands_t { + MC_CMP_CMD_AUTHENTICATE = 0, + MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION = 1, + MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION = 2, + MC_CMP_CMD_BEGIN_SP_AUTHENTICATION = 3, + MC_CMP_CMD_GENERATE_AUTH_TOKEN = 4, + MC_CMP_CMD_GET_VERSION = 5, +// MC_CMP_CMD_ROOT_CONT_ACTIVATE = 6, + MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT = 7, +// MC_CMP_CMD_ROOT_CONT_REGISTER = 8, + MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE = 9, + MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT = 10, + MC_CMP_CMD_ROOT_CONT_UNREGISTER = 11, + MC_CMP_CMD_SP_CONT_ACTIVATE = 12, + MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT = 13, + MC_CMP_CMD_SP_CONT_LOCK_BY_SP = 14, + MC_CMP_CMD_SP_CONT_REGISTER = 15, + MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE = 16, + MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT = 17, + MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP = 18, + MC_CMP_CMD_SP_CONT_UNREGISTER = 19, + MC_CMP_CMD_TLT_CONT_ACTIVATE = 20, + MC_CMP_CMD_TLT_CONT_LOCK_BY_SP = 21, + MC_CMP_CMD_TLT_CONT_PERSONALIZE = 22, + MC_CMP_CMD_TLT_CONT_REGISTER = 23, + MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE = 24, + MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP = 25, + MC_CMP_CMD_TLT_CONT_UNREGISTER = 26, + MC_CMP_CMD_GET_SUID = 27, + MC_CMP_CMD_AUTHENTICATE_TERMINATE = 28, + MC_CMP_CMD_LAST_ = MC_CMP_CMD_AUTHENTICATE_TERMINATE, +} cmpCommands_t; + +/** + * CMP Content Manager message data. + */ +typedef union { + cmpCommandHeader_t commandHeader; + cmpResponseHeader_t responseHeader; + + cmpCmdGetVersion_t cmpCmdGetVersion; + cmpRspGetVersion_t cmpRspGetVersion; + + cmpCmdBeginSocAuthentication_t cmpCmdBeginSocAuthentication; + cmpRspBeginSocAuthentication_t cmpRspBeginSocAuthentication; + + cmpCmdBeginRootAuthentication_t cmpCmdBeginRootAuthentication; + cmpRspBeginRootAuthentication_t cmpRspBeginRootAuthentication; + + cmpCmdBeginSpAuthentication_t cmpCmdBeginSpAuthentication; + cmpRspBeginSpAuthentication_t cmpRspBeginSpAuthentication; + + cmpCmdAuthenticate_t cmpCmdAuthenticate; + cmpRspAuthenticate_t cmpRspAuthenticate; + + cmpCmdGenAuthToken_t cmpCmdGenAuthToken; + cmpRspGenAuthToken_t cmpRspGenAuthToken; + + cmpCmdRootContRegisterActivate_t cmpCmdRootContRegisterActivate; + cmpRspRootContRegisterActivate_t cmpRspRootContRegisterActivate; + + cmpCmdRootContUnregister_t cmpCmdRootContUnregister; + cmpRspRootContUnregister_t cmpRspRootContUnregister; + + cmpCmdRootContLockByRoot_t cmpCmdRootContLockByRoot; + cmpRspRootContLockByRoot_t cmpRspRootContLockByRoot; + + cmpCmdRootContUnlockByRoot_t cmpCmdRootContUnlockByRoot; + cmpRspRootContUnlockByRoot_t cmpRspRootContUnlockByRoot; + + cmpCmdSpContRegisterActivate_t cmpCmdSpContRegisterActivate; + cmpRspSpContRegisterActivate_t cmpRspSpContRegisterActivate; + + cmpCmdSpContUnregister_t cmpCmdSpContUnregister; + cmpRspSpContUnregister_t cmpRspSpContUnregister; + + cmpCmdSpContLockByRoot_t cmpCmdSpContLockByRoot; + cmpRspSpContLockByRoot_t cmpRspSpContLockByRoot; + + cmpCmdSpContUnlockByRoot_t cmpCmdSpContUnlockByRoot; + cmpRspSpContUnlockByRoot_t cmpRspSpContUnlockByRoot; + + cmpCmdSpContLockBySp_t cmpCmdSpContLockBySp; + cmpRspSpContLockBySp_t cmpRspSpContLockBySp; + + cmpCmdSpContUnlockBySp_t cmpCmdSpContUnlockBySp; + cmpRspSpContUnlockBySp_t cmpRspSpContUnlockBySp; + + cmpCmdTltContRegister_t cmpCmdTltContRegister; + cmpRspTltContRegister_t cmpRspTltContRegister; + + cmpCmdTltContActivate_t cmpCmdTltContActivate; + cmpRspTltContActivate_t cmpRspTltContActivate; + + cmpCmdTltContRegisterActivate_t cmpCmdTltContRegisterActivate; + cmpRspTltContRegisterActivate_t cmpRspTltContRegisterActivate; + + cmpCmdTltContLockBySp_t cmpCmdTltContLockBySp; + cmpRspTltContLockBySp_t cmpRspTltContLockBySp; + + cmpCmdTltContUnlockBySp_t cmpCmdTltContUnlockBySp; + cmpRspTltContUnlockBySp_t cmpRspTltContUnlockBySp; + + cmpCmdTltContUnregister_t cmpCmdTltContUnregister; + cmpRspTltContUnregister_t cmpRspTltContUnregister; + + cmpCmdGetSuid_t cmpCmdGetSuid; + cmpRspGetSuid_t cmpRspGetSuid; + + cmpCmdAuthenticateTerminate_t cmpCmdAuthenticateTerminate; + cmpRspAuthenticateTerminate_t cmpRspAuthenticateTerminate; + + cmpCmdTltContPersonalize_t cmpCmdTltContPersonalize; + cmpRspTltContPersonalize_t cmpRspTltContPersonalize; + + cmpCmdSpContRegister_t cmpCmdSpContRegister; + cmpRspSpContRegister_t cmpRspSpContRegister; + + cmpCmdSpContActivate_t cmpCmdSpContActivate; + cmpRspSpContActivate_t cmpRspSpContActivate; +} cmpMessage_t; + +/** + * Overall CMP structure. + */ +typedef struct { + /** CMP message. */ + cmpMessage_t msg; +} cmp_t; + +/** + * TlCm exit code: TlCm exited with error. + */ +#define EXIT_ERROR ((uint32_t)(-1)) + +#endif // TLCMAPI_H_ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/TlCm/tlCmError.h b/mobicore/common/MobiCore/inc/TlCm/tlCmError.h new file mode 100644 index 0000000..ed1fe24 --- /dev/null +++ b/mobicore/common/MobiCore/inc/TlCm/tlCmError.h @@ -0,0 +1,62 @@ +/** @addtogroup CMP + * @{ + * + * @file + * TlCm error return code definitions. + * Definition of all possible TlCm rror return codes. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 TLCMERROR_H_ +#define TLCMERROR_H_ + +#define SUCCESSFUL 0x00000000 + +#define RET_ERR_EXT_UNKNOWN_COMMAND 0xE0000000 +#define RET_ERR_EXT_SECURITY_STATUS_NOT_SATISFIED 0xE0000010 +#define RET_ERR_EXT_SECURE_MESSAGING_FAILED 0xE0000020 +#define RET_ERR_EXT_INCORRECT_PARAMETERS 0xE0000030 +#define RET_ERR_EXT_REFERENCED_DATA_INVALID 0xE0000040 +#define RET_ERR_EXT_REFERENCED_DATA_NOT_FOUND 0xE0000050 +#define RET_ERR_EXT_METHOD_BLOCKED 0xE0000060 +#define RET_ERR_EXT_CONDITIONS_OF_USE_NOT_SATISFIED 0xE0000070 +#define RET_ERR_EXT_DEVICE_ALREADY_BOUND 0xE0000080 +#define RET_ERR_EXT_ALREADY_REGISTERED 0xE0000090 +#define RET_ERR_EXT_ALREADY_ACTIVATED 0xE00000A0 +#define RET_ERR_EXT_NOT_REGISTERED 0xE00000B0 +#define RET_ERR_EXT_NOT_ACTIVATED 0xE00000C0 +#define RET_ERR_EXT_CONTAINER_FULL 0xE00000D0 +#define RET_ERR_EXT_INTERNAL_ERROR 0xE0001000 + +#define RET_ERR_EXT_UNSPECIFIED 0xEEEEEEEE + +#endif // TLCMERROR_H_ + +/** @} */ + + diff --git a/mobicore/common/MobiCore/inc/TlCm/tlCmUuid.h b/mobicore/common/MobiCore/inc/TlCm/tlCmUuid.h new file mode 100644 index 0000000..6e17afd --- /dev/null +++ b/mobicore/common/MobiCore/inc/TlCm/tlCmUuid.h @@ -0,0 +1,42 @@ +/** @addtogroup CMP + * @{ + * @file + * Content management trustlet UUID definitions. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 TLCMUUID_H +#define TLCMUUID_H + +/** UUID of content management trustlet. */ +#define TL_CM_UUID { { 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } + +#endif // TLCMUUID_H + +/** @} */ + diff --git a/mobicore/common/MobiCore/inc/TlCm/version.h b/mobicore/common/MobiCore/inc/TlCm/version.h new file mode 100644 index 0000000..0719dcb --- /dev/null +++ b/mobicore/common/MobiCore/inc/TlCm/version.h @@ -0,0 +1,36 @@ +/** @addtogroup CMP + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CMP_VERSION_H_ +#define CMP_VERSION_H_ + +#define CMP_VERSION_MAJOR 2 +#define CMP_VERSION_MINOR 0 + +#endif /** CMP_VERSION_H_ */ + + diff --git a/mobicore/common/MobiCore/inc/mcContainer.h b/mobicore/common/MobiCore/inc/mcContainer.h new file mode 100644 index 0000000..a1ad57a --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcContainer.h @@ -0,0 +1,275 @@ +/** @addtogroup MC_CONTAINER mcContainer - Containers for MobiCore Content Management. + * @ingroup MC_DATA_TYPES + * @{ + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MC_CONTAINER_H_ +#define MC_CONTAINER_H_ + +#include <stdint.h> + +#include "mcRootid.h" +#include "mcSpid.h" +#include "mcUuid.h" +#include "mcSo.h" +#include "mcSuid.h" + +#define CONTAINER_VERSION_MAJOR 2 +#define CONTAINER_VERSION_MINOR 0 + +#define MC_CONT_SYMMETRIC_KEY_SIZE 32 +#define MC_CONT_PUBLIC_KEY_SIZE 320 +#define MC_CONT_CHILDREN_COUNT 16 +#define MC_DATA_CONT_MAX_DATA_SIZE 2048 +#define MC_TLT_CODE_HASH_SIZE 32 + +#define MC_BYTES_TO_WORDS(bytes) ( (bytes) / sizeof(uint32_t) ) +#define MC_ENUM_32BIT_SPACER ((int32_t)-1) + +typedef uint32_t mcContVersion_t; + +/** Personalization Data ID. */ +typedef struct { + uint32_t data; +} mcPid_t; + +typedef struct { + uint32_t keydata[MC_BYTES_TO_WORDS(MC_CONT_SYMMETRIC_KEY_SIZE)]; +} mcSymmetricKey_t; + +typedef struct { + uint32_t keydata[MC_BYTES_TO_WORDS(MC_CONT_PUBLIC_KEY_SIZE)]; +} mcPublicKey_t; + +typedef mcSpid_t spChild_t[MC_CONT_CHILDREN_COUNT]; + +typedef mcUuid_t mcUuidChild_t[MC_CONT_CHILDREN_COUNT]; + +/** Content management container states. + */ +typedef enum { + /** Container state unregistered. */ + MC_CONT_STATE_UNREGISTERED = 0, + /** Container is registered. */ + MC_CONT_STATE_REGISTERED = 1, + /** Container is activated. */ + MC_CONT_STATE_ACTIVATED = 2, + /** Container is locked by root. */ + MC_CONT_STATE_ROOT_LOCKED = 3, + /** Container is locked by service provider. */ + MC_CONT_STATE_SP_LOCKED = 4, + /** Container is locked by root and service provider. */ + MC_CONT_STATE_ROOT_SP_LOCKED = 5, + /** Dummy: ensure that enum is 32 bits wide. */ + MC_CONT_ATTRIB_SPACER = MC_ENUM_32BIT_SPACER +} mcContainerState_t; + +/** Content management container attributes. + */ +typedef struct { + mcContainerState_t state; +} mcContainerAttribs_t; + +/** Container types. */ +typedef enum { + /** SOC container. */ + CONT_TYPE_SOC = 0, + /** Root container. */ + CONT_TYPE_ROOT, + /** Service provider container. */ + CONT_TYPE_SP, + /** Trustlet container. */ + CONT_TYPE_TLCON, + /** Service provider data. */ + CONT_TYPE_SPDATA, + /** Trustlet data. */ + CONT_TYPE_TLDATA +} contType_t; + + +/** @defgroup MC_CONTAINER_CRYPTO_OBJECTS Container secrets. + * Data that is stored encrypted within the container. + * @{ */ + +/** SoC secret */ +typedef struct { + mcSymmetricKey_t kSocAuth; +} mcCoSocCont_t; + +/** */ +typedef struct { + mcSymmetricKey_t kRootAuth; +} mcCoRootCont_t; + +/** */ +typedef struct { + mcSymmetricKey_t kSpAuth; +} mcCoSpCont_t; + +/** */ +typedef struct { + mcSymmetricKey_t kTl; +} mcCoTltCont_t; + +/** */ +typedef struct { + uint8_t data[MC_DATA_CONT_MAX_DATA_SIZE]; +} mcCoDataCont_t; + +/** */ +typedef union { + mcSpid_t spid; + mcUuid_t uuid; +} mcCid_t; + +/** @} */ + +/** @defgroup MC_CONTAINER_CONTAINER_OBJECTS Container definitions. + * Container type definitions. + * @{ */ + +/** SoC Container */ +typedef struct { + contType_t type; + uint32_t version; + mcContainerAttribs_t attribs; + mcSuid_t suid; + // Secrets. + mcCoSocCont_t co; +} mcSocCont_t; + +/** */ +typedef struct { + contType_t type; + uint32_t version; + mcContainerAttribs_t attribs; + mcSuid_t suid; + mcRootid_t rootid; + spChild_t children; + // Secrets. + mcCoRootCont_t co; +} mcRootCont_t; + +/** */ +typedef struct { + contType_t type; + uint32_t version; + mcContainerAttribs_t attribs; + mcSpid_t spid; + mcUuidChild_t children; + // Secrets. + mcCoSpCont_t co; +} mcSpCont_t; + +/** */ +typedef struct { + contType_t type; + uint32_t version; + mcContainerAttribs_t attribs; + mcSpid_t parent; + mcUuid_t uuid; + // Secrets. + mcCoTltCont_t co; +} mcTltCont_t; + +/** */ +typedef struct { + contType_t type; + uint32_t version; + mcUuid_t uuid; + mcPid_t pid; + // Secrets. + mcCoDataCont_t co; +} mcDataCont_t; + +/** @} */ + +/** Calculates the total size of the secure object hash and padding for a given + * container. + * @param contTotalSize Total size of the container (sum of plain and encrypted + * parts). + * @param contCoSize Size/length of the encrypted container part ("crypto + * object"). + * @return Total size of hash and padding for given container. + */ +#define SO_CONT_HASH_AND_PAD_SIZE(contTotalSize, contCoSize) ( \ + MC_SO_SIZE((contTotalSize) - (contCoSize), (contCoSize)) \ + - sizeof(mcSoHeader_t) \ + - (contTotalSize) ) + +/** @defgroup MC_CONTAINER_SECURE_OBJECTS Containers in secure objects. + * Secure objects wrapping different containers. + * @{ */ + +/** Authentication token */ +typedef struct { + mcSoHeader_t soHeader; + mcSocCont_t coSoc; + uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcSocCont_t), sizeof(mcCoSocCont_t))]; +} mcSoAuthTokenCont_t; + +/** Root container */ +typedef struct { + mcSoHeader_t soHeader; + mcRootCont_t cont; + uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcRootCont_t), sizeof(mcCoRootCont_t))]; +} mcSoRootCont_t; + +/** */ +typedef struct { + mcSoHeader_t soHeader; + mcSpCont_t cont; + uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcSpCont_t), sizeof(mcCoSpCont_t))]; +} mcSoSpCont_t; + +/** */ +typedef struct { + mcSoHeader_t soHeader; + mcTltCont_t cont; + uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcTltCont_t), sizeof(mcCoTltCont_t))]; +} mcSoTltCont_t; + +/** */ +typedef struct { + mcSoHeader_t soHeader; + mcDataCont_t cont; + uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcDataCont_t), sizeof(mcCoDataCont_t))]; +} mcSoDataCont_t; + +/** */ +typedef struct { + mcSoRootCont_t soRoot; + mcSoSpCont_t soSp; + mcSoTltCont_t soTlt; +} mcSoContainerPath_t; + +/** @} */ + +#endif // MC_CONTAINER_H_ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/mcDriverId.h b/mobicore/common/MobiCore/inc/mcDriverId.h new file mode 100644 index 0000000..e4e6a39 --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcDriverId.h @@ -0,0 +1,64 @@ +/** + * @file + * Driver ID definition. + * + * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 RTMDRVID_H_ +#define RTMDRVID_H_ + +#define MC_DRV_VENDOR_ID_SHIFT (16) +#define MC_DRV_VENDOR_ID_MASK (0xFFFF << MC_DRV_VENDOR_ID_SHIFT) +#define MC_DRV_NUMBER_MASK (0x0000FFFF) + +/** MobiCore vendor IDs. */ +typedef enum { + MC_DRV_VENDOR_ID_GD = 0 << MC_DRV_VENDOR_ID_SHIFT, +} mcDrvVendorId_t; + +/** MobiCore GD driver numbers. */ +typedef enum { + MC_DRV_NUMBER_INVALID = 0, + MC_DRV_NUMBER_CRYPTO = 1, + MC_DRV_NUMBER_KEYPAD = 2, + /** Last GD driver number reserved for pre-installed drivers. + * GD driver numbers up to this constant may not be used for loadable drivers. */ + MC_DRV_NUMBER_LAST_PRE_INSTALLED = 100, +} mcDrvNumber_t; + +/** MobiCore driver IDs for Trustlets. */ +typedef enum { + MC_DRV_ID_INVALID = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_INVALID, + MC_DRV_ID_CRYPTO = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_CRYPTO, + MC_DRV_ID_KEYPAD = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_KEYPAD, + /** Last GD driver ID reserved for pre-installed drivers. + * GD driver IDs up to this constant may not be used for loadable drivers. */ + MC_DRV_ID_LAST_PRE_INSTALLED = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_LAST_PRE_INSTALLED, +} mcDriverId_t; + +#endif /* RTMDRVID_H_ */ diff --git a/mobicore/common/MobiCore/inc/mcLoadFormat.h b/mobicore/common/MobiCore/inc/mcLoadFormat.h new file mode 100644 index 0000000..eca9962 --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcLoadFormat.h @@ -0,0 +1,194 @@ +/** + * @defgroup MCLF MobiCore Load Format + * + * @defgroup MCLF_VER MCLF Versions + * @ingroup MCLF + * + * @addtogroup MCLF + * @{ + * + * MobiCore Load Format declarations. + * + * Holds the definitions for the layout of MobiCore Trustlet Blob. + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCLOADFORMAT_H_ +#define MCLOADFORMAT_H_ + +#include "mcUuid.h" +#include "mcDriverId.h" + +#define MCLF_VERSION_MAJOR 2 +#define MCLF_VERSION_MINOR 1 + +#define MC_SERVICE_HEADER_MAGIC_BE ((uint32_t)('M'|('C'<<8)|('L'<<16)|('F'<<24))) /**< "MCLF" in big endian integer representation */ +#define MC_SERVICE_HEADER_MAGIC_LE ((uint32_t)(('M'<<24)|('C'<<16)|('L'<<8)|'F')) /**< "MCLF" in little endian integer representation */ +#define MC_SERVICE_HEADER_MAGIC_STR "MCLF" /**< "MCLF" as string */ + +/** @name MCLF flags */ +/*@{*/ +#define MC_SERVICE_HEADER_FLAGS_PERMANENT (1U << 0) /**< Loaded service cannot be unloaded from MobiCore. */ +#define MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE (1U << 1) /**< Service has no WSM control interface. */ +#define MC_SERVICE_HEADER_FLAGS_DEBUGGABLE (1U << 2) /**< Service can be debugged. */ +/*@}*/ + +#if !defined(ADDR_T_DEFINED) +#define ADDR_T_DEFINED +typedef void* addr_t; /**< an address, can be physical or virtual */ +#endif // !defined(ADDR_T_DEFINED) + +/** Service type. + * The service type defines the type of executable. + */ +typedef enum { + SERVICE_TYPE_ILLEGAL = 0, /**< Service type is invalid. */ + SERVICE_TYPE_DRIVER = 1, /**< Service is a driver. */ + SERVICE_TYPE_SP_TRUSTLET = 2, /**< Service is a Trustlet. */ + SERVICE_TYPE_SYSTEM_TRUSTLET = 3 /**< Service is a system Trustlet. */ +} serviceType_t; + +/** + * Memory types. + */ +typedef enum { + MCLF_MEM_TYPE_INTERNAL_PREFERRED = 0, /**< If available use internal memory; otherwise external memory. */ + MCLF_MEM_TYPE_INTERNAL = 1, /**< Internal memory must be used for executing the service. */ + MCLF_MEM_TYPE_EXTERNAL = 2, /**< External memory must be used for executing the service. */ +} memType_t; + +/** + * Descriptor for a memory segment. + */ +typedef struct { + addr_t start; /**< Virtual start address. */ + uint32_t len; /**< Length of the segment in bytes. */ +} segmentDescriptor_t, *segmentDescriptor_ptr; + +/** + * MCLF intro for data structure identification. + * Must be the first element of a valid MCLF file. + */ +typedef struct { + uint32_t magic; /**< Header magic value ASCII "MCLF". */ + uint32_t version; /**< Version of the MCLF header structure. */ +} mclfIntro_t, *mclfIntro_ptr; + +/** @} */ + + +// Version 1 ///////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @defgroup MCLF_VER_V1 MCLF Version 1 + * @ingroup MCLF_VER + * + * @addtogroup MCLF_VER_V1 + * @{ + */ + +/** + * Version 1 MCLF header. + */ +typedef struct { + mclfIntro_t intro; /**< MCLF header start with the mandatory intro. */ + uint32_t flags; /**< Service flags. */ + memType_t memType; /**< Type of memory the service must be executed from. */ + serviceType_t serviceType; /**< Type of service. */ + + uint32_t numInstances; /**< Number of instances which can be run simultaneously. */ + mcUuid_t uuid; /**< Loadable service unique identifier (UUID). */ + mcDriverId_t driverId; /**< If the serviceType is SERVICE_TYPE_DRIVER the Driver ID is used. */ + uint32_t numThreads; /**< + * <pre> + * <br>Number of threads (N) in a service depending on service type.<br> + * + * SERVICE_TYPE_SP_TRUSTLET: N = 1 + * SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1 + * SERVICE_TYPE_DRIVER: N >= 1 + * </pre> + */ + segmentDescriptor_t text; /**< Virtual text segment. */ + segmentDescriptor_t data; /**< Virtual data segment. */ + uint32_t bssLen; /**< Length of the BSS segment in bytes. MUST be at least 8 byte. */ + addr_t entry; /**< Virtual start address of service code. */ +} mclfHeaderV1_t, *mclfHeaderV1_ptr; +/** @} */ + +// Version 2 ///////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @defgroup MCLF_VER_V2 MCLF Version 2 + * @ingroup MCLF_VER + * + * @addtogroup MCLF_VER_V2 + * @{ + */ + +/** + * Version 2 MCLF header. + */ +typedef struct { + mclfIntro_t intro; /**< MCLF header start with the mandatory intro. */ + uint32_t flags; /**< Service flags. */ + memType_t memType; /**< Type of memory the service must be executed from. */ + serviceType_t serviceType; /**< Type of service. */ + + uint32_t numInstances; /**< Number of instances which can be run simultaneously. */ + mcUuid_t uuid; /**< Loadable service unique identifier (UUID). */ + mcDriverId_t driverId; /**< If the serviceType is SERVICE_TYPE_DRIVER the Driver ID is used. */ + uint32_t numThreads; /**< + * <pre> + * <br>Number of threads (N) in a service depending on service type.<br> + * + * SERVICE_TYPE_SP_TRUSTLET: N = 1 + * SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1 + * SERVICE_TYPE_DRIVER: N >= 1 + * </pre> + */ + segmentDescriptor_t text; /**< Virtual text segment. */ + segmentDescriptor_t data; /**< Virtual data segment. */ + uint32_t bssLen; /**< Length of the BSS segment in bytes. MUST be at least 8 byte. */ + addr_t entry; /**< Virtual start address of service code. */ + uint32_t serviceVersion; /**< Version of the interface the driver exports. */ +} mclfHeaderV2_t, *mclfHeaderV2_ptr; +/** @} */ + + +// Version 1 and 2 /////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @addtogroup MCLF + * @{ + */ + +/** MCLF header */ +typedef union { + mclfIntro_t intro; /**< Intro for data structure identification. */ + mclfHeaderV1_t mclfHeaderV1; /**< Version 1 header */ + mclfHeaderV2_t mclfHeaderV2; /**< Version 2 header */ +} mclfHeader_t, *mclfHeader_ptr; + +#endif /* MCLOADFORMAT_H_ */ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/mcRootid.h b/mobicore/common/MobiCore/inc/mcRootid.h new file mode 100644 index 0000000..9b88e1d --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcRootid.h @@ -0,0 +1,54 @@ +/** + * @addtogroup MC_ROOTID mcRootid - Root container id. + * + * Global definition of root ID. + * + * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * @ingroup MC_DATA_TYPES + * @{ + */ + +#ifndef MC_ROOTID_H_ +#define MC_ROOTID_H_ + +/** Root Identifier type. */ +typedef uint32_t mcRootid_t; + +/** Reserved root id value 1. */ +static const mcRootid_t MC_ROOTID_RESERVED1 = 0; + +/** Reserved root id value 2. */ +static const mcRootid_t MC_ROOTID_RESERVED2 = 0xFFFFFFFF; + +/** Root id for system applications. */ +static const mcRootid_t MC_ROOTID_SYSTEM = 0xFFFFFFFE; + +#endif // MC_ROOTID_H_ + +/** @} */ + diff --git a/mobicore/common/MobiCore/inc/mcSo.h b/mobicore/common/MobiCore/inc/mcSo.h new file mode 100644 index 0000000..cf1f4ae --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcSo.h @@ -0,0 +1,164 @@ +/** + * @defgroup MC_DATA_TYPES MobiCore generic data types + * + * @addtogroup MC_SO mcSo - Secure objects definitions. + * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * @ingroup MC_DATA_TYPES + * @{ + * + */ + +#ifndef MC_SO_H_ +#define MC_SO_H_ + +#include "mcUuid.h" +#include "mcSpid.h" + +#define SO_VERSION_MAJOR 2 +#define SO_VERSION_MINOR 0 + +#define MC_ENUM_32BIT_SPACER ((int32_t)-1) + +/** Secure object type. */ +typedef enum { + /** Regular secure object. */ + MC_SO_TYPE_REGULAR = 0x00000001, + /** Dummy to ensure that enum is 32 bit wide. */ + MC_SO_TYPE_DUMMY = MC_ENUM_32BIT_SPACER, +} mcSoType_t; + + +/** Secure object context. + * A context defines which key to use to encrypt/decrypt a secure object. + */ +typedef enum { + /** Trustlet context. */ + MC_SO_CONTEXT_TLT = 0x00000001, + /** Service provider context. */ + MC_SO_CONTEXT_SP = 0x00000002, + /** Device context. */ + MC_SO_CONTEXT_DEVICE = 0x00000003, + /** Dummy to ensure that enum is 32 bit wide. */ + MC_SO_CONTEXT_DUMMY = MC_ENUM_32BIT_SPACER, +} mcSoContext_t; + +/** Secure object lifetime. + * A lifetime defines how long a secure object is valid. + */ +typedef enum { + /** SO does not expire. */ + MC_SO_LIFETIME_PERMANENT = 0x00000000, + /** SO expires on reboot (coldboot). */ + MC_SO_LIFETIME_POWERCYCLE = 0x00000001, + /** SO expires when Trustlet is closed. */ + MC_SO_LIFETIME_SESSION = 0x00000002, + /** Dummy to ensure that enum is 32 bit wide. */ + MC_SO_LIFETIME_DUMMY = MC_ENUM_32BIT_SPACER, +} mcSoLifeTime_t; + +/** Service provider Trustlet id. + * The combination of service provider id and Trustlet UUID forms a unique + * Trustlet identifier. + */ +typedef struct { + /** Service provider id. */ + mcSpid_t spid; + /** Trustlet UUID. */ + mcUuid_t uuid; +} tlApiSpTrustletId_t; + +/** Secure object header. + * A secure object header introduces a secure object. + * Layout of a secure object: + * <pre> + * <code> + * + * +--------+------------------+------------------+--------+---------+ + * | Header | plain-data | encrypted-data | hash | padding | + * +--------+------------------+------------------+--------+---------+ + * + * /--------/---- plainLen ----/-- encryptedLen --/-- 32 --/- 1..16 -/ + * + * /----------------- toBeHashedLen --------------/ + * + * /---------- toBeEncryptedLen ---------/ + * + * /--------------------------- totalSoSize -------------------------/ + * + * </code> + * </pre> + */ +typedef struct { + /** Type of secure object. */ + uint32_t type; + /** Secure object version. */ + uint32_t version; + /** Secure object context. */ + mcSoContext_t context; + /** Secure object lifetime. */ + mcSoLifeTime_t lifetime; + /** Producer Trustlet id. */ + tlApiSpTrustletId_t producer; + /** Length of unencrypted user data (after the header). */ + uint32_t plainLen; + /** Length of encrypted user data (after unencrypted data, excl. checksum + * and excl. padding bytes). */ + uint32_t encryptedLen; +} mcSoHeader_t; + +/** Maximum size of the payload (plain length + encrypted length) of a secure object. */ +#define MC_SO_PAYLOAD_MAX_SIZE 1000000 + +/** Block size of encryption algorithm used for secure objects. */ +#define MC_SO_ENCRYPT_BLOCK_SIZE 16 + +/** Maximum number of ISO padding bytes. */ +#define MC_SO_MAX_PADDING_SIZE (MC_SO_ENCRYPT_BLOCK_SIZE) + +/** Size of hash used for secure objects. */ +#define MC_SO_HASH_SIZE 32 + +/** Calculates gross size of cryptogram within secure object including ISO padding bytes. */ +#define MC_SO_ENCRYPT_PADDED_SIZE(netsize) ( (netsize) + \ + MC_SO_MAX_PADDING_SIZE - (netsize) % MC_SO_MAX_PADDING_SIZE ) + +/** Calculates the total size of a secure object. + * @param plainLen Length of plain text part within secure object. + * @param encryptedLen Length of encrypted part within secure object (excl. + * hash, padding). + * @return Total (gross) size of the secure object or 0 if given parameters are + * illegal or would lead to a secure object of invalid size. + */ +#define MC_SO_SIZE(plainLen, encryptedLen) ( \ + ((plainLen) + (encryptedLen) < (encryptedLen) || (plainLen) + (encryptedLen) > MC_SO_PAYLOAD_MAX_SIZE) ? 0 : \ + sizeof(mcSoHeader_t) + (plainLen) + MC_SO_ENCRYPT_PADDED_SIZE((encryptedLen) + MC_SO_HASH_SIZE) \ +) + +#endif // MC_SO_H_ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/mcSpid.h b/mobicore/common/MobiCore/inc/mcSpid.h new file mode 100644 index 0000000..2e8f80c --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcSpid.h @@ -0,0 +1,53 @@ +/** + * @addtogroup MC_SPID mcSpid - service provider ID. + * + * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * @ingroup MC_DATA_TYPES + * @{ + */ + +#ifndef MC_SPID_H_ +#define MC_SPID_H_ + +/** Service provider Identifier type. */ +typedef uint32_t mcSpid_t; + +/** SPID value used as free marker in root containers. */ +static const mcSpid_t MC_SPID_FREE = 0xFFFFFFFF; + +/** Reserved SPID value. */ +static const mcSpid_t MC_SPID_RESERVED = 0; + +/** SPID for system applications. */ +static const mcSpid_t MC_SPID_SYSTEM = 0xFFFFFFFE; + +#endif // MC_SPID_H_ + +/** @} */ + + + diff --git a/mobicore/common/MobiCore/inc/mcSuid.h b/mobicore/common/MobiCore/inc/mcSuid.h new file mode 100644 index 0000000..55afa98 --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcSuid.h @@ -0,0 +1,53 @@ +/** + * @addtogroup MC_SUID mcSuid - SoC unique ID. + * + * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * @ingroup MC_DATA_TYPES + * @{ + */ + +#ifndef MC_SUID_H_ +#define MC_SUID_H_ + +/** Length of SUID. */ +#define MC_SUID_LEN 16 + +/** Platform specific device identifier (serial number of the chip). */ +typedef struct { + uint8_t data[MC_SUID_LEN - sizeof(uint32_t)]; +} suidData_t; + +/** Soc unique identifier type. */ +typedef struct { + uint32_t sipId; /**< Silicon Provider ID to be set during build. */ + suidData_t suidData; +} mcSuid_t; + +#endif // MC_SUID_H_ + +/** @} */ diff --git a/mobicore/common/MobiCore/inc/mcUuid.h b/mobicore/common/MobiCore/inc/mcUuid.h new file mode 100644 index 0000000..a1d2a0b --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcUuid.h @@ -0,0 +1,74 @@ +/** + * @addtogroup MC_UUID mcUuid - Universally Unique Identifier. + * + * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * @ingroup MC_DATA_TYPES + * @{ + */ + +#ifndef MC_UUID_H_ +#define MC_UUID_H_ + +#define UUID_TYPE + +/** Universally Unique Identifier (UUID) according to ISO/IEC 11578. */ +typedef struct { + uint8_t value[16]; /**< Value of the UUID. */ +} mcUuid_t, *mcUuid_ptr; + +/** UUID value used as free marker in service provider containers. */ +#define MC_UUID_FREE_DEFINE \ + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +static const mcUuid_t MC_UUID_FREE = { + MC_UUID_FREE_DEFINE +}; + +/** Reserved UUID. */ +#define MC_UUID_RESERVED_DEFINE \ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + +static const mcUuid_t MC_UUID_RESERVED = { + MC_UUID_RESERVED_DEFINE +}; + +/** UUID for system applications. */ +#define MC_UUID_SYSTEM_DEFINE \ + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE } + +static const mcUuid_t MC_UUID_SYSTEM = { + MC_UUID_SYSTEM_DEFINE +}; + +#endif // MC_UUID_H_ + +/** @} */ + diff --git a/mobicore/common/MobiCore/inc/mcVersionHelper.h b/mobicore/common/MobiCore/inc/mcVersionHelper.h new file mode 100644 index 0000000..87e33b5 --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcVersionHelper.h @@ -0,0 +1,194 @@ +/** @addtogroup MC_RTM + * @{ + * MobiCore Version Helper Macros + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdio.h> + +//lint -emacro(*,MC_CHECK_VERSION) Disable all warnings for this macro. +//lint -emacro(*,MC_MAKE_VERSION) Disable all warnings for this macro. +//lint -emacro(*,MC_GET_MAJOR_VERSION) Disable all warnings for this macro. +//lint -emacro(*,MC_GET_MINOR_VERSION) Disable all warnings for this macro. +//lint -emacro(*,MC_GET_MINOR_VERSION) Disable all warnings for this macro. +//lint -emacro(*,ASSERT_VERSION_IMPLEMENTATION) Disable all warnings for this macro. +//lint -esym(*,Actual_*) Disable all warnings for these functions. + +/** Create a version number given major and minor numbers. */ +#define MC_MAKE_VERSION(major,minor) \ + ( (((major) & 0xffff) << 16) |\ + ((minor) & 0xffff)) + +/** Get major version number from complete version. */ +#define MC_GET_MAJOR_VERSION(version) ((version) >> 16) + +/** Get minor version number from complete version. */ +#define MC_GET_MINOR_VERSION(version) ((version) & 0xffff) + +// Asserts expression at compile-time (to be used outside a function body). +#define ASSERT_VERSION_IMPLEMENTATION(comp, versionpart, requiredV, actualV, expression) \ + extern int Actual_##comp##_##versionpart##_VERSION_##actualV##_does_not_match_required_version_##requiredV[(expression) ? 0:-1] + +#define ASSERT_VERSION_EVALUATOR(comp, versionpart, requiredV, actualV, expression) \ + ASSERT_VERSION_IMPLEMENTATION(comp, versionpart, requiredV, actualV, expression) + +#define ASSERT_VERSION(required, comparator, comp, versionpart) \ + ASSERT_VERSION_EVALUATOR(comp, versionpart, required, comp ##_VERSION_## versionpart, required comparator comp ##_VERSION_## versionpart) + +/** Checks at compile-time that an interface version provided by component + * 'comp' is identical to the required version of a component using this interface. + * Note! This check is useful for components that IMPLEMENT a particular + * interface to be alerted of changes to the interface which are likely to + * require adaptations in the implementation. */ +#define MC_CHECK_VERSION_EQUALS(comp, major, minor) \ + ASSERT_VERSION(major, ==, comp, MAJOR); \ + ASSERT_VERSION(minor, ==, comp, MINOR); + +/** Checks at compile-time that an interface version provided by component 'comp' meets the + * required version of a component using this interface. */ +#define MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \ + ASSERT_VERSION(majorRequired, ==, comp, MAJOR); \ + ASSERT_VERSION(minorRequired, <=, comp, MINOR); + +/** Version check helper macro for an interface consumer against an interface + * provider. + * @param comp Name of Interface to check. + * @param majorRequired Required major version of interface provider. + * @param minorRequired Required minor version of interface provider. + * Performs a compile-time interface version check that comp_VERSION_MAJOR + * equals majorRequired and that comp_VERSION_MINOR is at least minorRequired. + * On success, compilation goes through. + * On error, compilation breaks, telling the component that did not match in the + * error message. + * + * Additionally, a function is created: + * + * checkVersionOk##component(uint32_t version, char** errmsg) + * + * Compares version against majorRequired and minorRequired. + * Additionally, it creates a message string that can be printed out using printf("%s", errmsg). + * It returns either only the actual version, or on mismatch, actual and required version. + * + * @param version[in] component version as returned by layer-specific getVersion. + * @param errmsg[out] a message string that contains a log. + * + */ +#if !defined(NDEBUG) +#define MC_CHECK_VERSION(comp, majorRequired, minorRequired) \ + MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \ + static uint32_t checkVersionOk##comp(uint32_t version, char** errmsg) { \ + static char msgBuf[100]; \ + uint32_t major = MC_GET_MAJOR_VERSION(version); \ + uint32_t minor = MC_GET_MINOR_VERSION(version); \ + uint32_t ret = 0; \ + *errmsg = msgBuf; \ + if ((major == majorRequired) && (minor >= minorRequired)) { \ + snprintf(msgBuf, sizeof(msgBuf), \ + #comp " version is %u.%u", major, minor); \ + ret = 1; \ + } else { \ + snprintf(msgBuf, sizeof(msgBuf), \ + #comp " version error. Got: %u.%u, want >= %u.%u", major, minor, majorRequired, minorRequired); \ + } \ + msgBuf[sizeof(msgBuf) - 1] = '\0'; \ + return ret; \ + } +#else +#define MC_CHECK_VERSION(comp, majorRequired, minorRequired) \ + MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \ + static uint32_t checkVersionOk##comp(uint32_t version, char** errmsg) { \ + uint32_t major = MC_GET_MAJOR_VERSION(version); \ + uint32_t minor = MC_GET_MINOR_VERSION(version); \ + *errmsg = NULL; \ + if ((major == majorRequired) && (minor >= minorRequired)) { \ + return 1; \ + }; \ + return 0; \ + } +#endif + +/** Version check helper macro for version checks of a data object version + * against an data object consumer. + * + * @param comp Name of Interface to check. + * @param majorRequired Major data object version supported by component. + * @param minorRequired Minor data object version supported by component. + * Performs a compile-time interface version check that comp_VERSION_MAJOR + * equals majorRequired and that comp_VERSION_MINOR is at least minorRequired. + * On success, compilation goes through. + * On error, compilation breaks, telling the component that did not match in the + * error message. + * + * Additionally, the following function is created: + * + * checkVersionOkDataObject##component(uint32_t version, char** errmsg) + * + * This function checks that the data object version is compatible with the + * interface version; that is, the major version of the data object must match + * exactly and the minor version of the data object MUST BE LESS OR EQUAL to the + * required interface version. + * Additionally, it creates a message string that can be printed out using printf("%s", errmsg). + * It returns either only the actual version, or on mismatch, actual and + * provided version. + * + * @param version[in] Data object version of data object. + * @param errmsg[out] a message string that contains a log. + * + */ +#if !defined(NDEBUG) +#define MC_CHECK_DATA_OBJECT_VERSION(comp, majorRequired, minorRequired) \ + MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \ + static uint32_t checkVersionOkDataObject##comp(uint32_t version, char** errmsg) { \ + static char msgBuf[100]; \ + uint32_t major = MC_GET_MAJOR_VERSION(version); \ + uint32_t minor = MC_GET_MINOR_VERSION(version); \ + uint32_t ret = 0; \ + *errmsg = msgBuf; \ + if ((major == majorRequired) && (minor <= minorRequired)) { \ + snprintf(msgBuf, sizeof(msgBuf), \ + #comp " version is %u.%u", major, minor); \ + ret = 1; \ + } else { \ + snprintf(msgBuf, sizeof(msgBuf), \ + #comp " version error. Got: %u.%u, want <= %u.%u", major, minor, majorRequired, minorRequired); \ + } \ + msgBuf[sizeof(msgBuf) - 1] = '\0'; \ + return ret; \ + } +#else +#define MC_CHECK_DATA_OBJECT_VERSION(comp, majorRequired, minorRequired) \ + MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \ + static uint32_t checkVersionOkDataObject##comp(uint32_t version, char** errmsg) { \ + uint32_t major = MC_GET_MAJOR_VERSION(version); \ + uint32_t minor = MC_GET_MINOR_VERSION(version); \ + *errmsg = NULL; \ + if ((major == majorRequired) && (minor <= minorRequired)) { \ + return 1; \ + }; \ + return 0; \ + } +#endif diff --git a/mobicore/common/MobiCore/inc/mcVersionInfo.h b/mobicore/common/MobiCore/inc/mcVersionInfo.h new file mode 100644 index 0000000..1464e73 --- /dev/null +++ b/mobicore/common/MobiCore/inc/mcVersionInfo.h @@ -0,0 +1,52 @@ +/** @addtogroup MC_RTM + * @{ + * MobiCore Version Information + * + * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCVERSIONINFO_H_ +#define MCVERSIONINFO_H_ + +/** Length of MobiCore product ID string. */ +#define MC_PRODUCT_ID_LEN 64 + +/** Global MobiCore Version Information. + */ +typedef struct { + char productId[MC_PRODUCT_ID_LEN]; /** < Product ID of Mobicore; zero-terminated */ + uint32_t versionMci; /** < Version of Mobicore Control Interface */ + uint32_t versionSo; /** < Version of Secure Objects */ + uint32_t versionMclf; /** < Version of MobiCore Load Format */ + uint32_t versionContainer; /** < Version of MobiCore Container Format */ + uint32_t versionMcConfig; /** < Version of MobiCore Configuration Block Format */ + uint32_t versionTlApi; /** < Version of MobiCore Trustlet API Implementation */ + uint32_t versionDrApi; /** < Version of MobiCore Driver API Implementation */ + uint32_t versionCmp; /** < Version of Content Management Protocol */ +} mcVersionInfo_t; + +#endif /** MCVERSIONINFO_H_ */ diff --git a/mobicore/daemon/Android.mk b/mobicore/daemon/Android.mk new file mode 100644 index 0000000..37a3fe3 --- /dev/null +++ b/mobicore/daemon/Android.mk @@ -0,0 +1,8 @@ +# ============================================================================= +# +# Makefile pointing to all makefiles within the project. +# +# ============================================================================= +APP_PROJECT_PATH := $(call my-dir) +# Including all Android.mk files from subdirectories +include $(call all-subdir-makefiles) diff --git a/mobicore/daemon/Application.mk b/mobicore/daemon/Application.mk new file mode 100644 index 0000000..c88edd4 --- /dev/null +++ b/mobicore/daemon/Application.mk @@ -0,0 +1,17 @@ +# ============================================================================= +# +# Main build file defining the project modules and their global variables. +# +# ============================================================================= + +# Don't remove this - mandatory +APP_PROJECT_PATH := $(call my-dir) + +# The only STL implementation currently working with exceptions +APP_STL := stlport_static + +# Don't optimize for better debugging +APP_OPTIM := debug + +# Show all warnings +APP_CFLAGS := -Wall diff --git a/mobicore/daemon/ClientLib/Android.mk b/mobicore/daemon/ClientLib/Android.mk new file mode 100644 index 0000000..c2bf7e9 --- /dev/null +++ b/mobicore/daemon/ClientLib/Android.mk @@ -0,0 +1,47 @@ +# ============================================================================= +# +# Module: libMcClient.so +# +# C(version) Client Lib for Linux TLCs +# +# ============================================================================= + +LOCAL_PATH := $(call my-dir) +MY_CLIENTLIB_PATH := $(LOCAL_PATH) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libMcClient +LOCAL_MODULE_TAGS := eng +LOCAL_PRELINK_MODULE := false + +# External include files +LOCAL_C_INCLUDES += bionic \ + external/stlport/stlport + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(LOCAL_PATH)/public \ + $(APP_PROJECT_PATH) \ + $(APP_PROJECT_PATH)/Daemon/public \ + $(APP_PROJECT_PATH)/Kernel \ + $(APP_PROJECT_PATH)/Kernel/Platforms/Generic \ + $(APP_PROJECT_PATH)/Common + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(COMP_PATH_MobiCore)/inc \ + $(COMP_PATH_MobiCoreDriverMod)/Public + +# Add new source files here +LOCAL_SRC_FILES +=\ + Device.cpp\ + ClientLib.cpp\ + Session.cpp + +LOCAL_STATIC_LIBRARIES = libstlport_static libMcKernel libMcCommon + +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_SHARED_LIBRARY) diff --git a/mobicore/daemon/ClientLib/ClientLib.cpp b/mobicore/daemon/ClientLib/ClientLib.cpp new file mode 100644 index 0000000..9b6c5df --- /dev/null +++ b/mobicore/daemon/ClientLib/ClientLib.cpp @@ -0,0 +1,1278 @@ +/** @addtogroup MCD_IMPL_LIB + * @{ + * @file + * + * MobiCore Driver API. + * + * Functions for accessing MobiCore functionality from the normal world. + * Handles sessions and notifications via MCI buffer. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdint.h> +#include <stdbool.h> +#include <list> +#include <cassert> + +#include "public/MobiCoreDriverApi.h" + +#include "mc_drv_module_api.h" +#include "Connection.h" +#include "CMutex.h" +#include "Device.h" +#include "mcVersionHelper.h" + +#include "Daemon/public/MobiCoreDriverCmd.h" +#include "Daemon/public/mcVersion.h" + +#define LOG_TAG "McClient" +#include "log.h" + +MC_CHECK_VERSION(DAEMON, 0, 2); + +/** Notification data structure. */ +typedef struct { + uint32_t sessionId; /**< Session ID. */ + int32_t payload; /**< Additional notification information. */ +} notification_t; + +using namespace std; + +list<Device*> devices; + +// Forward declarations. +static uint32_t getDaemonVersion(Connection* devCon); + +//------------------------------------------------------------------------------ +static Device *resolveDeviceId( + uint32_t deviceId +) { + Device *ret = NULL; + + // Get Session for sessionId + for (list<Device*>::iterator iterator = devices.begin(); + iterator != devices.end(); + ++iterator) + { + Device *device = (*iterator); + + if (device->deviceId == deviceId) + { + ret = device; + break; + } + } + return ret; +} + + +//------------------------------------------------------------------------------ +static void addDevice( + Device *device +) { + devices.push_back(device); +} + + +//------------------------------------------------------------------------------ +static bool removeDevice( + uint32_t deviceId +) { + bool ret = false; + + for (list<Device*>::iterator iterator = devices.begin(); + iterator != devices.end(); + ++iterator) + { + Device *device = (*iterator); + + if (device->deviceId == deviceId) + { + devices.erase(iterator); + delete device; + ret = true; + break; + } + } + return ret; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcOpenDevice( + uint32_t deviceId +) { + mcResult_t mcResult = MC_DRV_OK; + static CMutex mutex; + Connection *devCon = NULL; + + mutex.lock(); // Enter critical section + + do + { + Device *device = resolveDeviceId(deviceId); + if (NULL != device) + { + LOG_E("mcOpenDevice(): Device %d already opened", deviceId); + mcResult = MC_DRV_ERR_INVALID_OPERATION; + break; + } + + // Open new connection to device + devCon = new Connection(); + if (!devCon->connect(SOCK_PATH)) + { + LOG_E("mcOpenDevice(): Could not connect to %s", SOCK_PATH); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + // Runtime check of Daemon version. + char* errmsg; + if (!checkVersionOkDAEMON(getDaemonVersion(devCon), &errmsg)) { + LOG_E("%s", errmsg); + mcResult = MC_DRV_ERR_DAEMON_VERSION; + break; + } + LOG_I("%s", errmsg); + + // Forward device open to the daemon and read result + mcDrvCmdOpenDevice_t mcDrvCmdOpenDevice = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_OPEN_DEVICE + }, + /* .payload = */ { + /* .deviceId = */ deviceId + } + }; + + int len = devCon->writeData( + &mcDrvCmdOpenDevice, + sizeof(mcDrvCmdOpenDevice)); + if (len < 0) + { + LOG_E("mcOpenDevice(): CMD_OPEN_DEVICE writeCmd failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + mcDrvResponseHeader_t rspHeader; + len = devCon->readData( + &rspHeader, + sizeof(rspHeader)); + if (len != sizeof(rspHeader)) + { + LOG_E("mcOpenDevice(): CMD_OPEN_DEVICE readRsp failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcOpenDevice(): CMD_OPEN_DEVICE failed, respId=%d", rspHeader.responseId); + switch(rspHeader.responseId) + { + case MC_DRV_RSP_PAYLOAD_LENGTH_ERROR: + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + case MC_DRV_INVALID_DEVICE_NAME: + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + case MC_DRV_RSP_DEVICE_ALREADY_OPENED: + default: + mcResult = MC_DRV_ERR_INVALID_OPERATION; + break; + } + break; + } + + // there is no payload to read + + device = new Device(deviceId, devCon); + if (!device->open(MC_DRV_MOD_DEVNODE_FULLPATH)) + { + delete device; + // devCon is freed in the Device destructor + devCon = NULL; + LOG_E("mcOpenDevice(): could not open device file: %s", MC_DRV_MOD_DEVNODE_FULLPATH); + mcResult = MC_DRV_ERR_INVALID_DEVICE_FILE; + break; + } + + addDevice(device); + + } while (false); + + if (mcResult != MC_DRV_OK && devCon != NULL) + { + delete devCon; + } + + mutex.unlock(); // Exit critical section + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcCloseDevice( + uint32_t deviceId +) { + mcResult_t mcResult = MC_DRV_OK; + static CMutex mutex; + + mutex.lock(); // Enter critical section + do + { + Device *device = resolveDeviceId(deviceId); + if (NULL == device) + { + LOG_E("mcCloseDevice(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + Connection *devCon = device->connection; + + // Return if not all sessions have been closed + if (device->hasSessions()) + { + LOG_E("mcCloseDevice(): cannot close with sessions still pending"); + mcResult = MC_DRV_ERR_SESSION_PENDING; + break; + } + + mcDrvCmdCloseDevice_t mcDrvCmdCloseDevice = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_CLOSE_DEVICE + } + }; + int len = devCon->writeData( + &mcDrvCmdCloseDevice, + sizeof(mcDrvCmdCloseDevice)); + // ignore error, but log details + if (len < 0) + { + LOG_E("mcCloseDevice(): CMD_CLOSE_DEVICE writeCmd failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + } + + mcDrvResponseHeader_t rspHeader; + len = devCon->readData( + &rspHeader, + sizeof(rspHeader)); + if (len != sizeof(rspHeader)) + { + LOG_E("mcCloseDevice(): CMD_CLOSE_DEVICE readResp failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcCloseDevice(): CMD_CLOSE_DEVICE failed, respId=%d", rspHeader.responseId); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + removeDevice(deviceId); + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcOpenSession( + mcSessionHandle_t *session, + const mcUuid_t *uuid, + uint8_t *tci, + uint32_t len +) { + mcResult_t mcResult = MC_DRV_OK; + static CMutex mutex; + + mutex.lock(); // Enter critical section + + do + { + if (NULL == session) + { + LOG_E("mcOpenSession(): Session is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (NULL == uuid) + { + LOG_E("mcOpenSession(): UUID is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (NULL == tci) + { + LOG_E("mcOpenSession(): TCI is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (len > MC_MAX_TCI_LEN) + { + LOG_E("mcOpenSession(): TCI length is longer than %d", MC_MAX_TCI_LEN); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + // Get the device associated with the given session + Device *device = resolveDeviceId(session->deviceId); + if (NULL == device) + { + LOG_E("mcOpenSession(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + Connection *devCon = device->connection; + + // Get the physical address of the given TCI + CWsm_ptr pWsm = device->findContiguousWsm(tci); + if (NULL == pWsm) + { + LOG_E("mcOpenSession(): Could not resolve physical address of TCI"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + if (pWsm->len < len) + { + LOG_E("mcOpenSession(): length is more than allocated TCI"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + // Prepare open session command + mcDrvCmdOpenSession_t cmdOpenSession = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_OPEN_SESSION + }, + /* .payload = */ { + /* .deviceId = */ session->deviceId, + /* .uuid = */ *uuid, + /* .tci = */ (uint32_t)pWsm->physAddr, + /* .len = */ len + } + }; + + // Transmit command data + + int len = devCon->writeData( + &cmdOpenSession, + sizeof(cmdOpenSession)); + if (sizeof(cmdOpenSession) != len) + { + LOG_E("mcOpenSession(): CMD_OPEN_SESSION writeData failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + // Read command response + + // read header first + mcDrvResponseHeader_t rspHeader; + len = devCon->readData( + &rspHeader, + sizeof(rspHeader)); + if (sizeof(rspHeader) != len) + { + LOG_E("mcOpenSession(): CMD_OPEN_SESSION readResp failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcOpenSession(): CMD_OPEN_SESSION failed, respId=%d", rspHeader.responseId); + switch(rspHeader.responseId) + { + case MC_DRV_RSP_WRONG_PUBLIC_KEY: + mcResult = MC_DRV_ERR_WRONG_PUBLIC_KEY; + break; + case MC_DRV_RSP_CONTAINER_TYPE_MISMATCH: + mcResult = MC_DRV_ERR_CONTAINER_TYPE_MISMATCH; + break; + case MC_DRV_RSP_CONTAINER_LOCKED: + mcResult = MC_DRV_ERR_CONTAINER_LOCKED; + break; + case MC_DRV_RSP_SP_NO_CHILD: + mcResult = MC_DRV_ERR_SP_NO_CHILD; + break; + case MC_DRV_RSP_TL_NO_CHILD: + mcResult = MC_DRV_ERR_TL_NO_CHILD; + break; + case MC_DRV_RSP_UNWRAP_ROOT_FAILED: + mcResult = MC_DRV_ERR_UNWRAP_ROOT_FAILED; + break; + case MC_DRV_RSP_UNWRAP_SP_FAILED: + mcResult = MC_DRV_ERR_UNWRAP_SP_FAILED; + break; + case MC_DRV_RSP_UNWRAP_TRUSTLET_FAILED: + mcResult = MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED; + break; + case MC_DRV_RSP_TRUSTLET_NOT_FOUND: + mcResult = MC_DRV_ERR_INVALID_DEVICE_FILE; + break; + case MC_DRV_RSP_PAYLOAD_LENGTH_ERROR: + case MC_DRV_RSP_DEVICE_NOT_OPENED: + case MC_DRV_RSP_FAILED: + default: + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + break; + } + + // read payload + mcDrvRspOpenSessionPayload_t rspOpenSessionPayload; + len = devCon->readData( + &rspOpenSessionPayload, + sizeof(rspOpenSessionPayload)); + if (sizeof(rspOpenSessionPayload) != len) + { + LOG_E("mcOpenSession(): CMD_OPEN_SESSION readPayload failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + // Register session with handle + session->sessionId = rspOpenSessionPayload.sessionId; + + // Set up second channel for notifications + Connection *sessionConnection = new Connection(); + if (!sessionConnection->connect(SOCK_PATH)) + { + LOG_E("mcOpenSession(): Could not connect to %s", SOCK_PATH); + delete sessionConnection; + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + //TODO CONTINOUE HERE !!!! FIX RW RETURN HANDLING!!!! + + // Write command to use channel for notifications + mcDrvCmdNqConnect_t cmdNqConnect = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_NQ_CONNECT + }, + /* .payload = */ { + /* .deviceId = */ session->deviceId, + /* .sessionId = */ session->sessionId, + /* .deviceSessionId = */ rspOpenSessionPayload.deviceSessionId, + /* .sessionMagic = */ rspOpenSessionPayload.sessionMagic + } + }; + sessionConnection->writeData( + &cmdNqConnect, + sizeof(cmdNqConnect)); + + + // Read command response, header first + len = sessionConnection->readData( + &rspHeader, + sizeof(rspHeader)); + if (sizeof(rspHeader) != len) + { + LOG_E("mcOpenSession(): CMD_NQ_CONNECT readRsp failed, ret=%d", len); + delete sessionConnection; + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcOpenSession(): CMD_NQ_CONNECT failed, respId=%d", rspHeader.responseId); + delete sessionConnection; + mcResult = MC_DRV_ERR_NQ_FAILED; + break; + } + + // there is no payload. + + // Session has been established, new session object must be created + device->createNewSession( + session->sessionId, + sessionConnection); + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcCloseSession( + mcSessionHandle_t *session +) { + mcResult_t mcResult = MC_DRV_OK; + static CMutex mutex; + + mutex.lock(); // Enter critical section + + do + { + if (NULL == session) + { + LOG_E("mcCloseSession(): Session is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + Device *device = resolveDeviceId(session->deviceId); + if (NULL == device) + { + LOG_E("mcCloseSession(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + Connection *devCon = device->connection; + + Session *nqSession = device->resolveSessionId(session->sessionId); + if (NULL == nqSession) + { + LOG_E("mcCloseSession(): Session not found"); + mcResult = MC_DRV_ERR_UNKNOWN_SESSION; + break; + } + + // Write close session command + mcDrvCmdCloseSession_t cmdCloseSession = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_CLOSE_SESSION + }, + /* .payload = */ { + /* .sessionId = */ session->sessionId, + } + }; + devCon->writeData( + &cmdCloseSession, + sizeof(cmdCloseSession)); + + // Read command response + mcDrvResponseHeader_t rspHeader; + int len = devCon->readData( + &rspHeader, + sizeof(rspHeader)); + if (sizeof(rspHeader) != len) + { + LOG_E("mcCloseSession(): CMD_CLOSE_SESSION readRsp failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcCloseSession(): CMD_CLOSE_SESSION failed, respId=%d", rspHeader.responseId); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + + bool r = device->removeSession(session->sessionId); + assert(r == true); + mcResult = MC_DRV_OK; + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcNotify( + mcSessionHandle_t *session +) { + mcResult_t mcResult = MC_DRV_OK; + + LOG_I("===%s()===", __func__); + + do + { + if (NULL == session) + { + LOG_E("mcNotify(): Session is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + Device *device = resolveDeviceId(session->deviceId); + if (NULL == device) + { + LOG_E("mcNotify(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + Connection *devCon = device->connection; + + Session *nqsession = device->resolveSessionId(session->sessionId); + if (NULL == nqsession) + { + LOG_E("mcNotify(): Session not found"); + mcResult = MC_DRV_ERR_UNKNOWN_SESSION; + break; + } + + mcDrvCmdNotify_t cmdNotify = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_NOTIFY + }, + /* .payload = */ { + /* .sessionId = */ session->sessionId, + } + }; + + devCon->writeData( + &cmdNotify, + sizeof(cmdNotify)); + + // Daemon will not return a response + + } while(false); + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcWaitNotification( + mcSessionHandle_t *session, + int32_t timeout +) { + mcResult_t mcResult = MC_DRV_OK; + + LOG_I("===%s()===", __func__); + + do + { + if (NULL == session) + { + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + Device *device = resolveDeviceId(session->deviceId); + if (NULL == device) + { + LOG_E("mcWaitNotification(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + + Session *nqSession = device->resolveSessionId(session->sessionId); + if (NULL == nqSession) + { + LOG_E("mcWaitNotification(): Session not found"); + mcResult = MC_DRV_ERR_UNKNOWN_SESSION; + break; + } + + Connection * nqconnection = nqSession->notificationConnection; + uint32_t count = 0; + + // Read notification queue till it's empty + for(;;) + { + notification_t notification; + ssize_t numRead = nqconnection->readData( + ¬ification, + sizeof(notification_t), + timeout); + //Exit on timeout in first run + //Later runs have timeout set to 0. -2 means, there is no more data. + if (0 == count && -2 == numRead) + { + LOG_E("mcWaitNotification(): read timeout"); + mcResult = MC_DRV_ERR_TIMEOUT; + break; + } + // After first notification the queue will be drained, Thus we set + // no timeout for the following reads + timeout = 0; + + if (numRead != sizeof(notification_t)) + { + if (0 == count) + { + //failure in first read, notify it + mcResult = MC_DRV_ERR_NOTIFICATION; + LOG_E("mcWaitNotification(): read notification failed, %i bytes received", (int)numRead); + break; + } + else + { + // Read of the n-th notification failed/timeout. We don't tell the + // caller, as we got valid notifications before. + mcResult = MC_DRV_OK; + break; + } + } + + count++; + LOG_I("mcWaitNotification(): readNq count=%d, SessionID=%d, Payload=%d", + count, notification.sessionId, notification.payload); + + if (0 != notification.payload) + { + // Session end point died -> store exit code + nqSession->setErrorInfo(notification.payload); + + mcResult = MC_DRV_INFO_NOTIFICATION; + break; + } + } // for(;;) + + } while (false); + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcMallocWsm( + uint32_t deviceId, + uint32_t align, + uint32_t len, + uint8_t **wsm, + uint32_t wsmFlags +) { + mcResult_t mcResult = MC_DRV_ERR_UNKNOWN; + static CMutex mutex; + + LOG_I("===%s()===", __func__); + + mutex.lock(); // Enter critical section + + do + { + Device *device = resolveDeviceId(deviceId); + if (NULL == device) + { + LOG_E("mcMallocWsm(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + if(NULL == wsm) + { + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + CWsm_ptr pWsm = device->allocateContiguousWsm(len); + if (NULL == pWsm) + { + LOG_E("mcMallocWsm(): Allocation of WSM failed"); + mcResult = MC_DRV_ERR_NO_FREE_MEMORY; + break; + } + + *wsm = (uint8_t*)pWsm->virtAddr; + mcResult = MC_DRV_OK; + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcFreeWsm( + uint32_t deviceId, + uint8_t *wsm +) { + mcResult_t mcResult = MC_DRV_ERR_UNKNOWN; + Device *device; + + static CMutex mutex; + + LOG_I("===%s()===", __func__); + + mutex.lock(); // Enter critical section + + do { + + // Get the device associated wit the given session + device = resolveDeviceId(deviceId); + if (NULL == device) + { + LOG_E("mcFreeWsm(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + + // find WSM object + CWsm_ptr pWsm = device->findContiguousWsm(wsm); + if (NULL == pWsm) + { + LOG_E("mcFreeWsm(): unknown address"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + // Free the given virtual address + if (!device->freeContiguousWsm(pWsm)) + { + LOG_E("mcFreeWsm(): Free of virtual address failed"); + mcResult = MC_DRV_ERR_FREE_MEMORY_FAILED; + break; + } + mcResult = MC_DRV_OK; + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcMap( + mcSessionHandle_t *sessionHandle, + void *buf, + uint32_t bufLen, + mcBulkMap_t *mapInfo +) { + mcResult_t mcResult = MC_DRV_ERR_UNKNOWN; + static CMutex mutex; + + mutex.lock(); // Enter critical section + + do + { + if (NULL == sessionHandle) + { + LOG_E("mcMap(): sessionHandle is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (NULL == mapInfo) + { + LOG_E("mcMap(): mapInfo is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (NULL == buf) + { + LOG_E("mcMap(): buf is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + // Determine device the session belongs to + Device *device = resolveDeviceId(sessionHandle->deviceId); + if (NULL == device) { + LOG_E("mcMap(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + Connection *devCon = device->connection; + + // Get session + Session *session = device->resolveSessionId(sessionHandle->sessionId); + if (NULL == session) + { + LOG_E("mcMap(): Session not found"); + mcResult = MC_DRV_ERR_UNKNOWN_SESSION; + break; + } + + // Workaround Linux memory handling + if (NULL != buf) + { + for (uint32_t i = 0; i < bufLen; i += 4096) { + volatile uint8_t x = ((uint8_t *) buf)[i]; x = x; + } + } + + // Register mapped bulk buffer to Kernel Module and keep mapped bulk buffer in mind + BulkBufferDescriptor *bulkBuf = session->addBulkBuf(buf, bufLen); + if (NULL == bulkBuf) + { + LOG_E("mcMap(): Error mapping bulk buffer"); + mcResult = MC_DRV_ERR_BULK_MAPPING; + break; + } + + + // Prepare map command + mcDrvCmdMapBulkMem_t mcDrvCmdMapBulkMem = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_MAP_BULK_BUF + }, + /* .payload = */ { + /* .sessionId = */ session->sessionId, + /* .pAddrL2 = */ (uint32_t)bulkBuf->physAddrWsmL2, + /* .offsetPayload = */ (uint32_t)(bulkBuf->virtAddr) & 0xFFF, + /* .lenBulkMem = */ bulkBuf->len + } + }; + + // Transmit map command to MobiCore device + devCon->writeData( + &mcDrvCmdMapBulkMem, + sizeof(mcDrvCmdMapBulkMem)); + + // Read command response + mcDrvResponseHeader_t rspHeader; + int len = devCon->readData( + &rspHeader, + sizeof(rspHeader)); + if (sizeof(rspHeader) != len) + { + LOG_E("mcMap(): CMD_MAP_BULK_BUF readRsp failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcMap(): CMD_MAP_BULK_BUF failed, respId=%d", rspHeader.responseId); + // REV We ignore Daemon Error code because client cannot handle it anyhow. + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + + // Unregister mapped bulk buffer from Kernel Module and remove mapped + // bulk buffer from session maintenance + if (!session->removeBulkBuf(buf)) + { + // Removing of bulk buffer not possible + LOG_E("mcMap(): Unregistering of bulk memory from Kernel Module failed"); + } + break; + } + + mcDrvRspMapBulkMemPayload_t rspMapBulkMemPayload; + devCon->readData( + &rspMapBulkMemPayload, + sizeof(rspMapBulkMemPayload)); + + // Set mapping info for Trustlet + mapInfo->sVirtualAddr = (void *) (rspMapBulkMemPayload.secureVirtualAdr); + mapInfo->sVirtualLen = bufLen; + mcResult = MC_DRV_OK; + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcUnmap( + mcSessionHandle_t *sessionHandle, + void *buf, + mcBulkMap_t *mapInfo +) { + mcResult_t mcResult = MC_DRV_ERR_UNKNOWN; + static CMutex mutex; + + LOG_I("===%s()===", __func__); + + mutex.lock(); // Enter critical section + + do + { + if (NULL == sessionHandle) + { + LOG_E("mcUnmap(): sessionHandle is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (NULL == mapInfo) + { + LOG_E("mcUnmap(): mapInfo is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + if (NULL == buf) + { + LOG_E("mcUnmap(): buf is null"); + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + // Determine device the session belongs to + Device *device = resolveDeviceId(sessionHandle->deviceId); + if (NULL == device) + { + LOG_E("mcUnmap(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + Connection *devCon = device->connection; + + // Get session + Session *session = device->resolveSessionId(sessionHandle->sessionId); + if (NULL == session) + { + LOG_E("mcUnmap(): Session not found"); + mcResult = MC_DRV_ERR_UNKNOWN_SESSION; + break; + } + + // Prepare unmap command + mcDrvCmdUnmapBulkMem_t cmdUnmapBulkMem = { + // C++ does not support C99 designated initializers + /* .header = */ { + /* .commandId = */ MC_DRV_CMD_UNMAP_BULK_BUF + }, + /* .payload = */ { + /* .sessionId = */ session->sessionId, + /* .secureVirtualAdr = */ (uint32_t)(mapInfo->sVirtualAddr), + /* .lenBulkMem = mapInfo->sVirtualLen*/ + } + }; + + devCon->writeData( + &cmdUnmapBulkMem, + sizeof(cmdUnmapBulkMem)); + + // Read command response + mcDrvResponseHeader_t rspHeader; + int len = devCon->readData( + &rspHeader, + sizeof(rspHeader)); + if (sizeof(rspHeader) != len) + { + LOG_E("mcUnmap(): CMD_UNMAP_BULK_BUF readRsp failed, ret=%d", len); + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) + { + LOG_E("mcUnmap(): CMD_UNMAP_BULK_BUF failed, respId=%d", rspHeader.responseId); + // REV We ignore Daemon Error code because client cannot handle it anyhow. + mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE; + break; + } + + mcDrvRspUnmapBulkMemPayload_t rspUnmapBulkMemPayload; + devCon->readData( + &rspUnmapBulkMemPayload, + sizeof(rspUnmapBulkMemPayload)); + + // REV axh: what about check the payload? + + // Unregister mapped bulk buffer from Kernel Module and remove mapped + // bulk buffer from session maintenance + if (!session->removeBulkBuf(buf)) + { + // Removing of bulk buffer not possible + LOG_E("mcUnmap(): Unregistering of bulk memory from Kernel Module failed"); + mcResult = MC_DRV_ERR_BULK_UNMAPPING; + break; + } + + mcResult = MC_DRV_OK; + + } while (false); + + mutex.unlock(); // Exit critical section + + return mcResult; +} + + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcGetSessionErrorCode( + mcSessionHandle_t *session, + int32_t *lastErr +) { + mcResult_t mcResult = MC_DRV_OK; + + LOG_I("===%s()===", __func__); + + do + { + if (NULL == session || NULL == lastErr) + { + mcResult = MC_DRV_ERR_INVALID_PARAMETER; + break; + } + + // Get device + Device *device = resolveDeviceId(session->deviceId); + if (NULL == device) + { + LOG_E("mcGetSessionErrorCode(): Device not found"); + mcResult = MC_DRV_ERR_UNKNOWN_DEVICE; + break; + } + + // Get session + Session *nqsession = device->resolveSessionId(session->sessionId); + if (NULL == nqsession) + { + LOG_E("mcGetSessionErrorCode(): Session not found"); + mcResult = MC_DRV_ERR_UNKNOWN_SESSION; + break; + } + + // get session error code from session + *lastErr = nqsession->getLastErr(); + + } while (false); + + return mcResult; +} + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcDriverCtrl( + mcDriverCtrl_t param, + uint8_t *data, + uint32_t len +) { + LOG_W("mcDriverCtrl(): not implemented"); + return MC_DRV_ERR_NOT_IMPLEMENTED; +} + +//------------------------------------------------------------------------------ +__MC_CLIENT_LIB_API mcResult_t mcGetMobiCoreVersion( + uint32_t deviceId, + mcVersionInfo_t* versionInfo +) { + mcResult_t mcResult = MC_DRV_OK; + + Device* device = resolveDeviceId(deviceId); + if (NULL == device) { + LOG_E("mcGetMobiCoreVersion(): Device not found"); + return MC_DRV_ERR_UNKNOWN_DEVICE; + } + + if (NULL == versionInfo) { + return MC_DRV_ERR_INVALID_PARAMETER; + } + + Connection* devCon = device->connection; + + mcDrvCmdGetMobiCoreVersion_t mcDrvCmdGetMobiCoreVersion = { + { + MC_DRV_CMD_GET_MOBICORE_VERSION, + } + }; + int len = devCon->writeData( + &mcDrvCmdGetMobiCoreVersion, + sizeof(mcDrvCmdGetMobiCoreVersion)); + + if (len < 0) { + LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION writeCmd failed, ret=%d", len); + return MC_DRV_ERR_DAEMON_UNREACHABLE; + } + + // Read GET MOBICORE VERSION response. + + // Read header first. + mcDrvResponseHeader_t rspHeader; + len = devCon->readData(&rspHeader, sizeof(rspHeader)); + if (sizeof(rspHeader) != len) { + LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION failed to respond, ret=%d", len); + return MC_DRV_ERR_DAEMON_UNREACHABLE; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) { + LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION bad response, respId=%d", rspHeader.responseId); + return MC_DRV_ERR_DAEMON_UNREACHABLE; + } + + // Read payload. + mcDrvRspGetMobiCoreVersionPayload_t rspGetMobiCoreVersionPayload; + len = devCon->readData(&rspGetMobiCoreVersionPayload, sizeof(rspGetMobiCoreVersionPayload)); + if (sizeof(rspGetMobiCoreVersionPayload) != len) { + LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION readPayload failed, ret=%d", len); + return MC_DRV_ERR_DAEMON_UNREACHABLE; + } + + *versionInfo = rspGetMobiCoreVersionPayload.versionInfo; + + return mcResult; +} + + +//------------------------------------------------------------------------------ +static uint32_t getDaemonVersion( + Connection* devCon +) { + assert(devCon != NULL); + + // Send GET VERSION command to daemon. + mcDrvCmdGetVersion_t cmdGetVersion = { + { + MC_DRV_CMD_GET_VERSION, + }, + }; + int len = devCon->writeData(&cmdGetVersion, sizeof(cmdGetVersion)); + if (sizeof(cmdGetVersion) != len) { + LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION failed, ret=%d", len); + return 0; + } + + // Read GET VERSION response. + + // Read header first. + mcDrvResponseHeader_t rspHeader; + len = devCon->readData(&rspHeader, sizeof(rspHeader)); + if (sizeof(rspHeader) != len) { + LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION failed to respond, ret=%d", len); + return 0; + } + + if (MC_DRV_RSP_OK != rspHeader.responseId) { + LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION bad response, respId=%d", rspHeader.responseId); + return 0; + } + + // Read payload. + mcDrvRspGetVersionPayload_t rspGetVersionPayload; + len = devCon->readData(&rspGetVersionPayload, sizeof(rspGetVersionPayload)); + if (sizeof(rspGetVersionPayload) != len) { + LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION readPayload failed, ret=%d", len); + return 0; + } + + return rspGetVersionPayload.version; +} + +/** @} */ diff --git a/mobicore/daemon/ClientLib/Device.cpp b/mobicore/daemon/ClientLib/Device.cpp new file mode 100644 index 0000000..bde0a08 --- /dev/null +++ b/mobicore/daemon/ClientLib/Device.cpp @@ -0,0 +1,259 @@ +/** @addtogroup MCD_IMPL_LIB + * @{ + * @file + * + * Client library device management. + * + * Device and Trustlet Session management Funtions. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdint.h> +#include <vector> + +#include "mc_drv_module_api.h" + +#include "Device.h" + +#define LOG_TAG "McClientLib_Device" +#include "log.h" + + +//------------------------------------------------------------------------------ +Device::Device( + uint32_t deviceId, + Connection *connection +) { + this->deviceId = deviceId; + this->connection = connection; + + pMcKMod = new CMcKMod(); +} + + +//------------------------------------------------------------------------------ +Device::~Device( + void +) { + /* Delete all session objects. Usually this should not be needed as closeDevice() + * requires that all sessions have been closed before. + */ + sessionIterator_t sessionIterator = sessionList.begin(); + while(sessionIterator != sessionList.end()) + { + delete (*sessionIterator); + sessionIterator = sessionList.erase(sessionIterator); + } + + // Free all allocated WSM descriptors + wsmIterator_t wsmIterator = wsmL2List.begin(); + while(wsmIterator != wsmL2List.end()) + { + CWsm_ptr pWsm = *wsmIterator; + + // ignore return code + pMcKMod->free(pWsm->handle); + + delete (*wsmIterator); + wsmIterator = wsmL2List.erase(wsmIterator); + } + delete connection; + delete pMcKMod; +} + + +//------------------------------------------------------------------------------ +bool Device::open( + const char * deviceName +) { + return pMcKMod->open(deviceName); +} + + +//------------------------------------------------------------------------------ +void Device::close( + void +) { + pMcKMod->close(); +} + + +//------------------------------------------------------------------------------ +bool Device::hasSessions( + void +) { + return sessionList.size() > 0; +} + + +//------------------------------------------------------------------------------ +void Device::createNewSession( + uint32_t sessionId, + Connection *connection +) { + Session *session = new Session(sessionId, pMcKMod, connection); + sessionList.push_back(session); +} + + +//------------------------------------------------------------------------------ +bool Device::removeSession( + uint32_t sessionId +) { + bool ret = false; + + sessionIterator_t interator = sessionList.begin(); + while(interator != sessionList.end()) + { + if ((*interator)->sessionId == sessionId) + { + delete (*interator); + interator = sessionList.erase(interator); + ret = true; + break; + } + else + { + interator++; + } + } + return ret; +} + + +//------------------------------------------------------------------------------ +Session *Device::resolveSessionId( + uint32_t sessionId +) { + Session *ret = NULL; + + // Get Session for sessionId + for ( sessionIterator_t interator = sessionList.begin(); + interator != sessionList.end(); + ++interator) + { + if ((*interator)->sessionId == sessionId) { + ret = (*interator); + break; + } + } + return ret; +} + + +//------------------------------------------------------------------------------ +CWsm_ptr Device::allocateContiguousWsm( + uint32_t len +) { + CWsm_ptr pWsm = NULL; + do + { + if (0 == len) + { + break; + } + + // Allocate shared memory + addr_t virtAddr; + uint32_t handle; + addr_t physAddr; + bool mciReuse = false; + int ret = pMcKMod->mmap( + len, + &handle, + &virtAddr, + &physAddr, + &mciReuse); + if (0 != ret) + { + break; + } + + // Register (vaddr,paddr) with device + pWsm = new CWsm(virtAddr,len,handle,physAddr); + + wsmL2List.push_back(pWsm); + + } while(0); + + // Return pointer to the allocated memory + return pWsm; +} + + +//------------------------------------------------------------------------------ +bool Device::freeContiguousWsm( + CWsm_ptr pWsm +) { + bool ret = false; + wsmIterator_t iterator; + + for (iterator=wsmL2List.begin(); iterator!=wsmL2List.end(); ++iterator) + { + if (pWsm == *iterator) + { + ret = true; + break; + } + } + + if(ret) { + LOG_I("freeWsm virtAddr=0x%p, handle=%d", + pWsm->virtAddr,pWsm->handle); + + // ignore return code + pMcKMod->free(pWsm->handle); + + iterator = wsmL2List.erase(iterator); + delete pWsm; + } + return ret; +} + + +//------------------------------------------------------------------------------ +CWsm_ptr Device::findContiguousWsm( + addr_t virtAddr +) { + CWsm_ptr pWsm = NULL; + + for( wsmIterator_t iterator=wsmL2List.begin(); + iterator!=wsmL2List.end(); + ++iterator) + { + CWsm_ptr pTmpWsm = *iterator; + if (virtAddr == pTmpWsm->virtAddr) + { + pWsm = pTmpWsm; + break; + } + } + + return pWsm; +} + +/** @} */ diff --git a/mobicore/daemon/ClientLib/Device.h b/mobicore/daemon/ClientLib/Device.h new file mode 100644 index 0000000..56d8fff --- /dev/null +++ b/mobicore/daemon/ClientLib/Device.h @@ -0,0 +1,151 @@ +/** @addtogroup MCD_IMPL_LIB + * @{ + * @file + * + * Client library device management. + * + * Device and Trustlet Session management Functions. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 DEVICE_H_ +#define DEVICE_H_ + +#include <stdint.h> +#include <vector> + +#include "Session.h" +#include "CWsm.h" + + +class Device { + +private: + sessionList_t sessionList; /**< MobiCore Trustlet session associated with the device */ + wsmList_t wsmL2List; /**< WSM L2 Table */ + + +public: + uint32_t deviceId; /**< Device identifier */ + Connection *connection; /**< The device connection */ + CMcKMod_ptr pMcKMod; + + Device( + uint32_t deviceId, + Connection *connection + ); + + virtual ~Device( + void + ); + + /** + * Open the device. + * @param deviceName Name of the kernel modules device file. + * @return true if the device has been opened successfully + */ + bool open( + const char * deviceName + ); + + /** + * Closes the device. + */ + void close( + void + ); + + /** + * Check if the device has open sessions. + * @return true if the device has one or more open sessions. + */ + bool hasSessions( + void + ); + + /** + * Add a session to the device. + * @param sessionId session ID + * @param connection session connection + */ + void createNewSession( + uint32_t sessionId, + Connection *connection + ); + + /** + * Remove the specified session from the device. + * The session object will be destroyed and all resources associated with it will be freed. + * + * @param sessionId Session of the session to remove. + * @return true if a session has been found and removed. + */ + bool removeSession( + uint32_t sessionId + ); + + /** + * Get as session object for a given session ID. + * @param sessionId Identified of a previously opened session. + * @return Session object if available or NULL if no session has been found. + */ + Session *resolveSessionId( + uint32_t sessionId + ); + + /** + * Allocate a block of contiguous WSM. + * @param len The virtual address to be registered. + * @return The virtual address of the allocated memory or NULL if no memory is available. + */ + CWsm_ptr allocateContiguousWsm( + uint32_t len + ); + + /** + * Unregister a vaddr from a device. + * @param vaddr The virtual address to be registered. + * @param paddr The physical address to be registered. + */ + bool freeContiguousWsm( + CWsm_ptr pWsm + ); + + /** + * Get a WSM object for a given virtual address. + * @param vaddr The virtual address which has been allocate with mcMallocWsm() in advance. + * @return the WSM object or NULL if no address has been found. + */ + CWsm_ptr findContiguousWsm( + addr_t virtAddr + ); + +}; + +#endif /* DEVICE_H_ */ + +/** @} */ diff --git a/mobicore/daemon/ClientLib/Session.cpp b/mobicore/daemon/ClientLib/Session.cpp new file mode 100644 index 0000000..85e1398 --- /dev/null +++ b/mobicore/daemon/ClientLib/Session.cpp @@ -0,0 +1,207 @@ +/** @addtogroup MCD_IMPL_LIB + * @{ + * @file + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdint.h> +#include <vector> + +#include "mc_drv_module_api.h" + +#include "Session.h" + +#define LOG_TAG "McClient" +#include "log.h" + + +//------------------------------------------------------------------------------ +Session::Session( + uint32_t sessionId, + CMcKMod *mcKMod, + Connection *connection +) { + this->sessionId = sessionId; + this->mcKMod = mcKMod; + this->notificationConnection = connection; + + sessionInfo.lastErr = SESSION_ERR_NO; + sessionInfo.state = SESSION_STATE_INITIAL; +} + + +//------------------------------------------------------------------------------ +Session::~Session( + void +) { + BulkBufferDescriptor *pBlkBufDescr; + + // Unmap still mapped buffers + for ( bulkBufferDescrIterator_t iterator = bulkBufferDescriptors.begin(); + iterator != bulkBufferDescriptors.end(); + ++iterator) + { + pBlkBufDescr = *iterator; + + LOG_I("removeBulkBuf - Physical Address of L2 Table = 0x%X, handle= %d", + (unsigned int)pBlkBufDescr->physAddrWsmL2, + pBlkBufDescr->handle); + + // ignore any error, as we cannot do anything in this case. + int ret = mcKMod->unregisterWsmL2(pBlkBufDescr->handle); + if (0 != ret) + { + LOG_E("removeBulkBuf(): mcKModUnregisterWsmL2 failed: %d",ret); + } + + //iterator = bulkBufferDescriptors.erase(iterator); + delete(pBlkBufDescr); + } + + // Finally delete notification connection + delete notificationConnection; +} + + +//------------------------------------------------------------------------------ +void Session::setErrorInfo( + int32_t err +) { + sessionInfo.lastErr = err; +} + + +//------------------------------------------------------------------------------ +int32_t Session::getLastErr( + void +) { + return sessionInfo.lastErr; +} + + +//------------------------------------------------------------------------------ +BulkBufferDescriptor* Session::addBulkBuf( + addr_t buf, + uint32_t len +) { + BulkBufferDescriptor* blkBufDescr = NULL; + + // Search bulk buffer descriptors for existing vAddr + // At the moment a virtual address can only be added one time + for ( bulkBufferDescrIterator_t iterator = bulkBufferDescriptors.begin(); + iterator != bulkBufferDescriptors.end(); + ++iterator + ) { + if ((*iterator)->virtAddr == buf) + { + return NULL; + } + } + + do + { + // Prepare the interface structure for memory registration in Kernel Module + addr_t pPhysWsmL2; + uint32_t handle; + + int ret = mcKMod->registerWsmL2( + buf, + len, + 0, + &handle, + &pPhysWsmL2); + + if (0 != ret) { + LOG_E("mcKModRegisterWsmL2 failed, ret=%d",ret); + break; + } + + LOG_I("addBulkBuf - Physical Address of L2 Table = 0x%X, handle=%d", + (unsigned int)pPhysWsmL2, + handle); + + // Create new descriptor + blkBufDescr = new BulkBufferDescriptor( + buf, + len, + handle, + pPhysWsmL2); + + // Add to vector of descriptors + bulkBufferDescriptors.push_back(blkBufDescr); + } while(0); + + return blkBufDescr; +} + + +//------------------------------------------------------------------------------ +bool Session::removeBulkBuf( + addr_t virtAddr +) { + bool ret = true; + BulkBufferDescriptor *pBlkBufDescr = NULL; + + LOG_I("removeBulkBuf(): Virtual Address = 0x%X", (unsigned int) virtAddr); + + // Search and remove bulk buffer descriptor + for ( bulkBufferDescrIterator_t iterator = bulkBufferDescriptors.begin(); + iterator != bulkBufferDescriptors.end(); + ++iterator + ) { + + if ((*iterator)->virtAddr == virtAddr) + { + pBlkBufDescr = *iterator; + iterator = bulkBufferDescriptors.erase(iterator); + break; + } + } + + if (NULL == pBlkBufDescr) + { + LOG_E("removeBulkBuf - Virtual Address not found"); + ret = false; + } + else + { + LOG_I("removeBulkBuf(): WsmL2 phys=0x%X, handle=%d", + (unsigned int)pBlkBufDescr->physAddrWsmL2, pBlkBufDescr->handle); + + // ignore any error, as we cannot do anything + int ret = mcKMod->unregisterWsmL2(pBlkBufDescr->handle); + if (0 != ret) + { + LOG_E("removeBulkBuf(): mcKModUnregisterWsmL2 failed: %d",ret); + } + + delete (pBlkBufDescr); + } + + return ret; +} + +/** @} */ diff --git a/mobicore/daemon/ClientLib/Session.h b/mobicore/daemon/ClientLib/Session.h new file mode 100644 index 0000000..8d609a8 --- /dev/null +++ b/mobicore/daemon/ClientLib/Session.h @@ -0,0 +1,167 @@ +/** @addtogroup MCD_IMPL_LIB + * @{ + * @file + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 SESSION_H_ +#define SESSION_H_ + +#include <stdint.h> +#include <list> + +#include "mc_drv_module_api.h" +#include "Connection.h" +#include "CMcKMod.h" + + +class BulkBufferDescriptor{ + +public: + addr_t virtAddr; /**< The virtual address of the Bulk buffer*/ + uint32_t len; /**< Length of the Bulk buffer*/ + uint32_t handle; + addr_t physAddrWsmL2; /**< The physical address of the L2 table of the Bulk buffer*/ + + BulkBufferDescriptor( + addr_t virtAddr, + uint32_t len, + uint32_t handle, + addr_t physAddrWsmL2 + ) : + virtAddr(virtAddr), + len(len), + handle(handle), + physAddrWsmL2(physAddrWsmL2) + {}; + +}; + +typedef std::list<BulkBufferDescriptor*> bulkBufferDescrList_t; +typedef bulkBufferDescrList_t::iterator bulkBufferDescrIterator_t; + + +/** Session states. + * At the moment not used !!. + */ +typedef enum +{ + SESSION_STATE_INITIAL, + SESSION_STATE_OPEN, + SESSION_STATE_TRUSTLET_DEAD +} sessionState_t; + +#define SESSION_ERR_NO 0 /**< No session error */ + +/** Session information structure. + * The information structure is used to hold the state of the session, which will limit further actions for the session. + * Also the last error code will be stored till it's read. + */ +typedef struct { + sessionState_t state; /**< Session state */ + int32_t lastErr; /**< Last error of session */ +} sessionInformation_t; + + +class Session { + +private: + + CMcKMod *mcKMod; + bulkBufferDescrList_t bulkBufferDescriptors; /**< Descriptors of additional bulk buffer of a session */ + sessionInformation_t sessionInfo; /**< Informations about session */ + +public: + + uint32_t sessionId; + Connection *notificationConnection; + + Session( + uint32_t sessionId, + CMcKMod *mcKMod, + Connection *connection + ); + + virtual ~Session( + void + ); + + /** + * Add address information of additional bulk buffer memory to session and + * register virtual memory in kernel module. + * + * @attention The virtual address can only be added one time. If the virtual address already exist, NULL is returned. + * + * @param buf The virtual address of bulk buffer. + * @param len Length of bulk buffer. + * + * @return On success the actual Bulk buffer descriptor with all address information is retured, NULL if an error occurs. + */ + BulkBufferDescriptor * addBulkBuf( + addr_t buf, + uint32_t len + ); + + /** + * Remove address information of additional bulk buffer memory from session and + * unregister virtual memory in kernel module + * + * @param buf The virtual address of the bulk buffer. + * + * @return true on success. + */ + bool removeBulkBuf( + addr_t buf + ); + + /** + * Set additional error information of the last error that occured. + * + * @param errorCode The actual error. + */ + void setErrorInfo( + int32_t err + ); + + /** + * Get additional error information of the last error that occured. + * + * @attention After request the information is set to SESSION_ERR_NO. + * + * @return Last stored error code or SESSION_ERR_NO. + */ + int32_t getLastErr( + void + ); + +}; + +typedef std::list<Session*> sessionList_t; +typedef sessionList_t::iterator sessionIterator_t; + +#endif /* SESSION_H_ */ + +/** @} */ diff --git a/mobicore/daemon/ClientLib/public/MobiCoreDriverApi.h b/mobicore/daemon/ClientLib/public/MobiCoreDriverApi.h new file mode 100644 index 0000000..85997e6 --- /dev/null +++ b/mobicore/daemon/ClientLib/public/MobiCoreDriverApi.h @@ -0,0 +1,428 @@ +/** + * @defgroup MCD_API MobiCore Driver API + * @addtogroup MCD_API + * @{ + * + * @if DOXYGEN_MCDRV_API + * @mainpage MobiCore Driver API. + * @endif + * + * MobiCore Driver API. + * + * The MobiCore (MC) Driver API provides access functions to the MobiCore runtime environment and the contained Trustlets. + * + * @image html DoxyOverviewDrvApi500x.png + * @image latex DoxyOverviewDrvApi500x.png "MobiCore Overview" width=12cm + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCDRIVER_H_ +#define MCDRIVER_H_ + +#if (!defined(__MC_CLIENT_LIB_API)) && __cplusplus + #define __MC_CLIENT_LIB_API extern "C" +#else + #define __MC_CLIENT_LIB_API +#endif // __cplusplus + + +#include <stdint.h> +#include <stdbool.h> + +#include "mcUuid.h" +#include "mcVersionInfo.h" + +/** + * Return values of MobiCore driver functions. + */ +typedef enum +{ + MC_DRV_OK = 0, /**< Function call succeeded. */ + MC_DRV_NO_NOTIFICATION = 1, /**< No notification available. */ + MC_DRV_ERR_NOTIFICATION = 2, /**< Error during notification on communication level. */ + MC_DRV_ERR_NOT_IMPLEMENTED = 3, /**< Function not implemented. */ + MC_DRV_ERR_OUT_OF_RESOURCES = 4, /**< No more resources available. */ + MC_DRV_ERR_INIT = 5, /**< Driver initialization failed. */ + MC_DRV_ERR_UNKNOWN = 6, /**< Unknown error. */ + MC_DRV_ERR_UNKNOWN_DEVICE = 7, /**< The specified device is unknown. */ + MC_DRV_ERR_UNKNOWN_SESSION = 8, /**< The specified session is unknown. */ + MC_DRV_ERR_INVALID_OPERATION = 9, /**< The specified operation is not allowed. */ + MC_DRV_ERR_INVALID_RESPONSE = 10, /**< The response header from the MC is invalid. */ + MC_DRV_ERR_TIMEOUT = 11, /**< Function call timed out. */ + MC_DRV_ERR_NO_FREE_MEMORY = 12, /**< Can not allocate additional memory. */ + MC_DRV_ERR_FREE_MEMORY_FAILED = 13, /**< Free memory failed. */ + MC_DRV_ERR_SESSION_PENDING = 14, /**< Still some open sessions pending. */ + MC_DRV_ERR_DAEMON_UNREACHABLE = 15, /**< MC daemon not reachable */ + MC_DRV_ERR_INVALID_DEVICE_FILE = 16, /**< The device file of the kernel module could not be opened. */ + MC_DRV_ERR_INVALID_PARAMETER = 17, /**< Invalid parameter. */ + MC_DRV_ERR_KERNEL_MODULE = 18, /**< Unspecified error from Kernel Module*/ + MC_DRV_ERR_BULK_MAPPING = 19, /**< Error during mapping of additional bulk memory to session. */ + MC_DRV_ERR_BULK_UNMAPPING = 20, /**< Error during unmapping of additional bulk memory to session. */ + MC_DRV_INFO_NOTIFICATION = 21, /**< Notification received, exit code available. */ + MC_DRV_ERR_NQ_FAILED = 22, /**< Set up of NWd connection failed. */ + MC_DRV_ERR_DAEMON_VERSION = 23, /**< Wrong daemon version. */ + MC_DRV_ERR_CONTAINER_VERSION = 24, /**< Wrong container version. */ + MC_DRV_ERR_WRONG_PUBLIC_KEY = 25, /**< System Trustlet public key is wrong. */ + MC_DRV_ERR_CONTAINER_TYPE_MISMATCH = 26, /**< Wrong containter type(s). */ + MC_DRV_ERR_CONTAINER_LOCKED = 27, /**< Container is locked (or not activated). */ + MC_DRV_ERR_SP_NO_CHILD = 28, /**< SPID is not registered with root container. */ + MC_DRV_ERR_TL_NO_CHILD = 29, /**< UUID is not registered with sp container. */ + MC_DRV_ERR_UNWRAP_ROOT_FAILED = 30, /**< Unwrapping of root container failed. */ + MC_DRV_ERR_UNWRAP_SP_FAILED = 31, /**< Unwrapping of service provider container failed. */ + MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED = 32, /**< Unwrapping of Trustlet container failed. */ +} mcResult_t; + + +/** + * Driver control command. + */ +typedef enum { + MC_CTRL_DUMMY = 1 /**< Dummy. */ +} mcDriverCtrl_t; + + +/** Structure of Session Handle, includes the Session ID and the Device ID the Session belongs to. + * The session handle will be used for session-based MobiCore communication. + * It will be passed to calls which address a communication end point in the MobiCore environment. + */ +typedef struct { + uint32_t sessionId; /**< MobiCore session ID */ + uint32_t deviceId; /**< Device ID the session belongs to */ +} mcSessionHandle_t; + +/** Information structure about additional mapped Bulk buffer between the Trustlet Connector (Nwd) and + * the Trustlet (Swd). This structure is initialized from a Trustlet Connector by calling mcMap(). + * In order to use the memory within a Trustlet the Trustlet Connector has to inform the Trustlet with + * the content of this structure via the TCI. + */ +typedef struct { + void *sVirtualAddr; /**< The virtual address of the Bulk buffer regarding the address space of the Trustlet, already includes a possible offset! */ + uint32_t sVirtualLen; /**< Length of the mapped Bulk buffer */ +} mcBulkMap_t; + + +#define MC_DEVICE_ID_DEFAULT 0 /**< The default device ID */ +#define MC_INFINITE_TIMEOUT ((int32_t)(-1)) /**< Wait infinite for a response of the MC. */ +#define MC_NO_TIMEOUT 0 /**< Do not wait for a response of the MC. */ +#define MC_MAX_TCI_LEN 0x100000 /**< TCI/DCI must not exceed 1MiB */ + +/* Mark only the following functions for export */ +#pragma GCC visibility push(default) + +/** Open a new connection to a MobiCore device. + * + * mcOpenDevice() initializes all device specific resources required to communicate + * with an MobiCore instance located on the specified device in the system. If the device + * does not exist the function will return MC_DRV_ERR_UNKNOWN_DEVICE. + * + * @param [in] deviceId Identifier for the MobiCore device to be used. MC_DEVICE_ID_DEFAULT refers to the default device. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_ERR_INVALID_OPERATION if device already opened. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when deviceId is unknown. + * @return MC_DRV_ERR_INVALID_DEVICE_FILE if kernel module under /dev/mobicore cannot be opened + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcOpenDevice( + uint32_t deviceId +); + +/** Close the connection to a MobiCore device. + * When closing a device, active sessions have to be closed beforehand. + * Resources associated with the device will be released. + * The device may be opened again after it has been closed. + * + * @param [in] deviceId Identifier for the MobiCore device. MC_DEVICE_ID_DEFAULT refers to the default device. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid. + * @return MC_DRV_ERR_SESSION_PENDING when a session is still open. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcCloseDevice( + uint32_t deviceId +); + +/** Open a new session to a Trustlet. The trustlet with the given UUID has to be available in the flash filesystem. + * + * Write MCP open message to buffer and notify MobiCore about the availability of a new command. + * Waits till the MobiCore responses with the new session ID (stored in the MCP buffer). + * + * @param [in,out] session On success, the session data will be returned. Note that session.deviceId has to be the device id of an opened device. + * @param [in] uuid UUID of the Trustlet to be opened. + * @param [in] tci TCI buffer for communicating with the trustlet. + * @param [in] tciLen Length of the TCI buffer. Maximum allowed value is MC_MAX_TCI_LEN. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if session parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon socket occur. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when daemon returns an error. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcOpenSession( + mcSessionHandle_t *session, + const mcUuid_t *uuid, + uint8_t *tci, + uint32_t tciLen +); + +/** Close a Trustlet session. + * + * Closes the specified MobiCore session. The call will block until the session has been closed. + * + * @pre Device deviceId has to be opened in advance. + * + * @param [in] session Session to be closed. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if session parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur. + * @return MC_DRV_ERR_INVALID_DEVICE_FILE when daemon cannot open trustlet file. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcCloseSession( + mcSessionHandle_t *session +); + +/** Notify a session. + * Notifies the session end point about available message data. + * If the session parameter is correct, notify will always succeed. + * Corresponding errors can only be received by mcWaitNotification(). + * @pre A session has to be opened in advance. + * + * @param session The session to be notified. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if session parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid. + */ +__MC_CLIENT_LIB_API mcResult_t mcNotify( + mcSessionHandle_t *session +); + +/** Wait for a notification. + * + * Wait for a notification issued by the MobiCore for a specific session. + * The timeout parameter specifies the number of milliseconds the call will wait for a notification. + * If the caller passes 0 as timeout value the call will immediately return. If timeout value is below 0 the call will block + * until a notification for the session has been received. + * + * @attention if timeout is below 0, call will block: + * Caller has to trust the other side to send a notification to wake him up again. + * + * @param [in] session The session the notification should correspond to. + * @param [in] timeout Time in milliseconds to wait (MC_NO_TIMEOUT : direct return, > 0 : milliseconds, MC_INFINITE_TIMEOUT : wait infinitely) + * + * @return MC_DRV_OK if notification is available. + * @return MC_DRV_ERR_TIMEOUT if no notification arrived in time. + * @return MC_DRV_INFO_NOTIFICATION if a problem with the session was encountered. Get more details with mcGetSessionErrorCode(). + * @return MC_DRV_ERR_NOTIFICATION if a problem with the socket occurred. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid. + */ +__MC_CLIENT_LIB_API mcResult_t mcWaitNotification( + mcSessionHandle_t *session, + int32_t timeout +); + +/** + * Allocate a block of world shared memory (WSM). + * The MC driver allocates a contiguous block of memory which can be used as WSM. + * This implicates that the allocated memory is aligned according to the alignment parameter. + * Always returns a buffer of size WSM_SIZE aligned to 4K. + * + * @param [in] deviceId The ID of an opened device to retrieve the WSM from. + * @param [in] align The alignment (number of pages) of the memory block (e.g. 0x00000001 for 4kb). + * @param [in] len Length of the block in bytes. + * @param [out] wsm Virtual address of the world shared memory block. + * @param [in] wsmFlags Platform specific flags describing the memory to be allocated. + * + * @attention: align and wsmFlags are currently ignored + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid. + * @return MC_DRV_ERR_NO_FREE_MEMORY if no more contiguous memory is available in this size or for this process. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcMallocWsm( + uint32_t deviceId, + uint32_t align, + uint32_t len, + uint8_t **wsm, + uint32_t wsmFlags +); + +/** + * Free a block of world shared memory (WSM). + * The MC driver will free a block of world shared memory (WSM) previously allocated with + * mcMallocWsm(). The caller has to assure that the address handed over to the driver + * is a valid WSM address. + * + * @param [in] deviceId The ID to which the given address belongs. + * @param [in] wsm Address of WSM block to be freed. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid. + * @return MC_DRV_ERR_FREE_MEMORY_FAILED on failures. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcFreeWsm( + uint32_t deviceId, + uint8_t *wsm +); + +/** + * Map additional bulk buffer between a Trustlet Connector (TLC) and the Trustlet (TL) for a session. + * Memory allocated in user space of the TLC can be mapped as additional communication channel + * (besides TCI) to the Trustlet. Limitation of the Trustlet memory structure apply: only 6 chunks can be mapped + * with a maximum chunk size of 1 MiB each. + * + * @attention It is up to the application layer (TLC) to inform the Trustlet about the additional mapped bulk memory. + * + * @param [in] session Session handle with information of the deviceId and the sessionId. The + * given buffer is mapped to the session specified in the sessionHandle. + * @param [in] buf Virtual address of a memory portion (relative to TLC) to be shared with the Trustlet, already includes a possible offset! + * @param [in] len length of buffer block in bytes. + * @param [out] mapInfo Information structure about the mapped Bulk buffer between the TLC (Nwd) and + * the TL (Swd). + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur. + * @return MC_DRV_ERR_BULK_MAPPING when buf is already uses as bulk buffer or when registering the buffer failed. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcMap( + mcSessionHandle_t *session, + void *buf, + uint32_t len, + mcBulkMap_t *mapInfo +); + +/** + * Remove additional mapped bulk buffer between Trustlet Connector (TLC) and the Trustlet (TL) for a session. + * + * @attention The bulk buffer will immediately be unmapped from the session context. + * @attention The application layer (TLC) must inform the TL about unmapping of the additional bulk memory before calling mcUnmap! + * + * @param [in] session Session handle with information of the deviceId and the sessionId. The + * given buffer is unmapped from the session specified in the sessionHandle. + * @param [in] buf Virtual address of a memory portion (relative to TLC) shared with the TL, already includes a possible offset! + * @param [in] mapInfo Information structure about the mapped Bulk buffer between the TLC (Nwd) and + * the TL (Swd). + * @attention The clientlib currently ignores the len field in mapInfo. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur. + * @return MC_DRV_ERR_BULK_UNMAPPING when buf was not registered earlier or when unregistering failed. + * + * Uses a Mutex. + */ +__MC_CLIENT_LIB_API mcResult_t mcUnmap( + mcSessionHandle_t *session, + void *buf, + mcBulkMap_t *mapInfo +); + + +/** + * @attention: Not implemented. + * Execute driver specific command. + * mcDriverCtrl() can be used to execute driver specific commands. + * Besides the control command MC_CTRL_GET_VERSION commands are implementation specific. + * Please refer to the corresponding specification of the driver manufacturer. + * + * @param [in] param Command ID of the command to be executed. + * @param [in, out] data Command data and response depending on command. + * @param [in] len Length of the data block. + * + * @return MC_DRV_ERR_NOT_IMPLEMENTED. + */ +__MC_CLIENT_LIB_API mcResult_t mcDriverCtrl( + mcDriverCtrl_t param, + uint8_t *data, + uint32_t len +); + +/** + * Get additional error information of the last error that occured on a session. + * After the request the stored error code will be deleted. + * + * @param [in] session Session handle with information of the deviceId and the sessionId. + * @param [out] lastErr >0 Trustlet has terminated itself with this value, <0 Trustlet is dead because of an error within the MobiCore (e.g. Kernel exception). + * See also MCI definition. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid. + */ +__MC_CLIENT_LIB_API mcResult_t mcGetSessionErrorCode( + mcSessionHandle_t *session, + int32_t *lastErr +); + +/** + * Get MobiCore version information of a device. + * + * @param [in] deviceId of an open device. + * @param [out] versionInfo MobiCore version info. + * + * @return MC_DRV_OK if operation has been successfully completed. + * @return MC_DRV_ERR_UNKNOWN_DEVICE when device is not open. + * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid. + * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur. + */ +__MC_CLIENT_LIB_API mcResult_t mcGetMobiCoreVersion( + uint32_t deviceId, + mcVersionInfo_t* versionInfo +); +#pragma GCC visibility pop +#endif /** MCDRIVER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Common/Android.mk b/mobicore/daemon/Common/Android.mk new file mode 100644 index 0000000..1b6520c --- /dev/null +++ b/mobicore/daemon/Common/Android.mk @@ -0,0 +1,33 @@ +# ============================================================================= +# +# Module: libCommon.a - classes shared by various modules +# +# ============================================================================= + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libMcCommon +LOCAL_MODULE_TAGS := eng + +# Add new source files here +LOCAL_SRC_FILES +=\ + CMutex.cpp\ + Connection.cpp\ + NetlinkConnection.cpp\ + CSemaphore.cpp\ + CThread.cpp + +# Header files required by components including this module +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) +LOCAL_EXPORT_CPPFLAGS += -fno-rtti -fno-exceptions + +LOCAL_C_INCLUDES += bionic \ + external/stlport/stlport + +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions + +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_STATIC_LIBRARY) diff --git a/mobicore/daemon/Common/CMutex.cpp b/mobicore/daemon/Common/CMutex.cpp new file mode 100644 index 0000000..0ae95c8 --- /dev/null +++ b/mobicore/daemon/Common/CMutex.cpp @@ -0,0 +1,77 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Mutex implementation (pthread wrapper). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "CMutex.h" + + +//------------------------------------------------------------------------------ +CMutex::CMutex( + void +) { + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_cond, NULL); +} + + +//------------------------------------------------------------------------------ +CMutex::~CMutex( + void +) { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); +} + + +//------------------------------------------------------------------------------ +int32_t CMutex::lock( + void +) { + return pthread_mutex_lock(&m_mutex); +} + + +//------------------------------------------------------------------------------ +int32_t CMutex::trylock( + void +) { + return pthread_mutex_trylock(&m_mutex); +} + + +//------------------------------------------------------------------------------ +int32_t CMutex::unlock( + void +) { + return pthread_mutex_unlock(&m_mutex); +} + +/** @} */ diff --git a/mobicore/daemon/Common/CMutex.h b/mobicore/daemon/Common/CMutex.h new file mode 100644 index 0000000..c6c1bc4 --- /dev/null +++ b/mobicore/daemon/Common/CMutex.h @@ -0,0 +1,63 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Mutex implementation (pthread wrapper). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CMUTEX_H_ +#define CMUTEX_H_ + +#include <inttypes.h> +#include "pthread.h" + + +class CMutex { + +public: + + CMutex(void); + + ~CMutex(void); + + int32_t lock(void); + + int32_t trylock(void); + + int32_t unlock(void); + +private: + + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + +}; + +#endif /* CMUTEX_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Common/CSemaphore.cpp b/mobicore/daemon/Common/CSemaphore.cpp new file mode 100644 index 0000000..2e7deea --- /dev/null +++ b/mobicore/daemon/Common/CSemaphore.cpp @@ -0,0 +1,113 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Semaphore implementation (pthread wrapper). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <time.h> +#include <limits.h> +#include "CSemaphore.h" +#include <stdio.h> + +//------------------------------------------------------------------------------ +CSemaphore::CSemaphore(int size) : m_waiters_count(0), m_count(size) +{ + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_cond, NULL); +} + + +//------------------------------------------------------------------------------ +CSemaphore::~CSemaphore() +{ + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); +} + + +//------------------------------------------------------------------------------ +void CSemaphore::wait() +{ + pthread_mutex_lock(&m_mutex); + m_waiters_count ++; + while( m_count == 0 ) + pthread_cond_wait(&m_cond, &m_mutex); + m_waiters_count --; + m_count --; + pthread_mutex_unlock(&m_mutex); +} + +//------------------------------------------------------------------------------ +bool CSemaphore::wait(int sec) +{ + int rc = 0; + struct timespec tm; + if(sec < 0) + sec = LONG_MAX; + clock_gettime(CLOCK_REALTIME, &tm); + tm.tv_sec += sec; + + pthread_mutex_lock(&m_mutex); + m_waiters_count ++; + if( m_count == 0 ) { + rc = pthread_cond_timedwait(&m_cond, &m_mutex, &tm); + } + m_waiters_count --; + // Decrement only if waiting actually succeeded, otherwise we + // just timed out + if (!rc) + m_count --; + pthread_mutex_unlock(&m_mutex); + return (rc == 0); +} + + +//------------------------------------------------------------------------------ +bool CSemaphore::wouldWait() +{ + bool ret = false; + pthread_mutex_lock(&m_mutex); + if( m_count == 0 ) + ret = true; + pthread_mutex_unlock(&m_mutex); + return ret; +} + + +//------------------------------------------------------------------------------ +void CSemaphore::signal() +{ + pthread_mutex_lock(&m_mutex); + if( m_waiters_count > 0 ) + pthread_cond_signal(&m_cond); + m_count ++; + pthread_mutex_unlock(&m_mutex); +} + +/** @} */ diff --git a/mobicore/daemon/Common/CSemaphore.h b/mobicore/daemon/Common/CSemaphore.h new file mode 100644 index 0000000..0739430 --- /dev/null +++ b/mobicore/daemon/Common/CSemaphore.h @@ -0,0 +1,70 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Semaphore implementation (pthread wrapper). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CSEMAPHORE_H_ +#define CSEMAPHORE_H_ + +#include "pthread.h" + +/** + * Could inherit from CMutex, or use CMutex internally. + * Semaphore is a mutex with a counter. Constructor and destructor + * code is the same. + */ + +class CSemaphore { + +public: + + CSemaphore(int size = 0); + + ~CSemaphore(void); + + void wait(void); + bool wait(int sec); + + bool wouldWait(void); + + void signal(void); + +private: + + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + int m_waiters_count; + int m_count; + +}; + +#endif /*CSEMAPHORE_H_*/ + +/** @} */ diff --git a/mobicore/daemon/Common/CThread.cpp b/mobicore/daemon/Common/CThread.cpp new file mode 100644 index 0000000..1508c13 --- /dev/null +++ b/mobicore/daemon/Common/CThread.cpp @@ -0,0 +1,143 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Thread implementation (pthread abstraction). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "CThread.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + + +//------------------------------------------------------------------------------ +CThread::CThread(void) : + m_terminate(false), m_isExiting(false) +{ + m_sem = new CSemaphore(); +} + + +//------------------------------------------------------------------------------ +CThread::~CThread( + void +) { + delete m_sem; +} + + +//------------------------------------------------------------------------------ +void CThread::terminate( + void +) { + m_terminate = true; +} + + +//------------------------------------------------------------------------------ +bool CThread::isExiting( + void +) { + return m_isExiting; +} + + +//------------------------------------------------------------------------------ +void CThread::setExiting( + void +) { + m_isExiting = true; +} + + +//------------------------------------------------------------------------------ +void CThread::exit( + int32_t exitcode +) { + setExiting(); + pthread_exit((void *)exitcode); +} + + +//------------------------------------------------------------------------------ +bool CThread::shouldTerminate( + void +) { + return m_terminate; +} + + +//------------------------------------------------------------------------------ +void CThread::start( + void +) { + int ret; + ret = pthread_create(&m_thread, NULL, CThreadStartup, this); + if (0 != ret) + LOG_E("pthread_create failed with error code %d", ret); +} + + +//------------------------------------------------------------------------------ +void CThread::join( + void +) { + int ret; + ret = pthread_join(m_thread, NULL); + if (0 != ret) + LOG_E("pthread_join failed with error code %d", ret); +} + + +//------------------------------------------------------------------------------ +void CThread::sleep( + void +) { + m_sem->wait(); +} + + +//------------------------------------------------------------------------------ +void CThread::wakeup( + void +) { + m_sem->signal(); +} + + +//------------------------------------------------------------------------------ +void *CThreadStartup( + void *_tgtObject +) { + CThread *tgtObject = (CThread *) _tgtObject; + tgtObject->run(); + return NULL; +} + +/** @} */ diff --git a/mobicore/daemon/Common/CThread.h b/mobicore/daemon/Common/CThread.h new file mode 100644 index 0000000..be053bf --- /dev/null +++ b/mobicore/daemon/Common/CThread.h @@ -0,0 +1,86 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Thread implementation (pthread abstraction). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CTHREAD_H_ +#define CTHREAD_H_ + +#include <inttypes.h> +#include "CSemaphore.h" +#include "pthread.h" + +using namespace std; + + +class CThread { + +public: + + CThread(void); + + virtual ~CThread(void); + + virtual void run(void)=0; + + void start(void); + + void join(void); + + void sleep(void); + + void wakeup(void); + + void terminate(void); + + bool isExiting(void); + + void setExiting(void); + +protected: + + bool shouldTerminate(void); + + void exit(int32_t exitcode); + +private: + + CSemaphore *m_sem; + pthread_t m_thread; + bool m_terminate; + bool m_isExiting; + +}; + +extern "C" void *CThreadStartup(void *); + +#endif /*CTHREAD_H_*/ + +/** @} */ diff --git a/mobicore/daemon/Common/CWsm.h b/mobicore/daemon/Common/CWsm.h new file mode 100644 index 0000000..d95dc73 --- /dev/null +++ b/mobicore/daemon/Common/CWsm.h @@ -0,0 +1,70 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * World shared memory definitions. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CWSM_H_ +#define CWSM_H_ + +#include <stdint.h> +#include <list> +#include "McTypes.h" + + +class CWsm { + +public: + + addr_t virtAddr; + uint32_t len; + uint32_t handle; + addr_t physAddr; + + CWsm( + addr_t virtAddr, + uint32_t len, + uint32_t handle, + addr_t physAddr = NULL // this may be unknown, so is can be omitted. + ) : + virtAddr(virtAddr), + len(len), + handle(handle), + physAddr(physAddr) + { }; + +}; + +typedef CWsm *CWsm_ptr; +typedef std::list<CWsm_ptr> wsmList_t; +typedef wsmList_t::iterator wsmIterator_t; + +#endif /* CWSM_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Common/Connection.cpp b/mobicore/daemon/Common/Connection.cpp new file mode 100644 index 0000000..d9b012b --- /dev/null +++ b/mobicore/daemon/Common/Connection.cpp @@ -0,0 +1,200 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection data. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <unistd.h> +#include <assert.h> +#include <cstring> +#include <errno.h> + +#include "Connection.h" + +#define LOG_TAG "McClient" +#include "log.h" + + +//------------------------------------------------------------------------------ +Connection::Connection( + void +) { + connectionData = NULL; + // Set invalid socketDescriptor + socketDescriptor = -1; +} + + +//------------------------------------------------------------------------------ +Connection::Connection( + int socketDescriptor, + sockaddr_un *remote +) { + assert(NULL != remote); + assert(-1 != socketDescriptor); + + this->socketDescriptor = socketDescriptor; + this->remote = *remote; + connectionData = NULL; +} + + +//------------------------------------------------------------------------------ +Connection::~Connection( + void +) { + LOG_I("%s: Connection closed!", __func__); + if (socketDescriptor != -1) + close(socketDescriptor); +} + + +//------------------------------------------------------------------------------ +bool Connection::connect( + const char *dest +) { + bool ret = false; + int32_t len; + + assert(NULL != dest); + + LOG_I("connect(): Connecting to %s", dest); + do { + remote.sun_family = AF_UNIX; + strncpy(remote.sun_path, dest, sizeof(remote.sun_path) - 1); + if ((socketDescriptor = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + LOG_E("Can't open stream socket - errno: %d", errno); + break; + } + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + // The Daemon socket is in the Abstract Domain(LINUX ONLY!) + remote.sun_path[0] = 0; + if (::connect(socketDescriptor, (struct sockaddr *) &remote, len) < 0) { + LOG_E("connect() failed - errno: %d", errno); + break; + } + ret = true; + } while (false); + + return ret; +} + + +//------------------------------------------------------------------------------ +size_t Connection::readData( + void *buffer, + uint32_t len +) { + return readData(buffer, len, -1); +} + + +//------------------------------------------------------------------------------ +size_t Connection::readData( + void *buffer, + uint32_t len, + int32_t timeout +) { + size_t ret; + struct timeval tv; + struct timeval *ptv = NULL; + fd_set readfds; + + assert(NULL != buffer); + assert(-1 != socketDescriptor); + + do{ + + if(timeout >= 0){ + // Calculate timeout value + tv.tv_sec = timeout/1000; + tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000; + ptv = &tv; + } + + FD_ZERO(&readfds); + FD_SET(socketDescriptor, &readfds); + ret = select(socketDescriptor + 1, &readfds, NULL, NULL, ptv); + + // check for read error + if (-1 == (int)ret) { + LOG_E("readData(): select() failed, ret=%d, errno=%d", ret,errno); + break; + } + + // Handle case of no descriptor ready + if (0 == ret) { + LOG_W("readData(): select() timed out"); + ret = -2; + break; + } + + // one or more descriptors are ready + + // finally check if fd has been selected -> must socketDescriptor + if (!FD_ISSET(socketDescriptor, &readfds)) + { + LOG_E("readData(): failure, errno=%d", errno); + break; + } + + ret = recv(socketDescriptor, buffer, len, MSG_WAITALL); + if(0 == ret) + { + LOG_I("readData(): peer orderly closed connection."); + break; + } + + }while(false); + + return ret; +} + + +//------------------------------------------------------------------------------ +size_t Connection::writeData( + void *buffer, + uint32_t len +) { + size_t ret; + + assert(NULL != buffer); + assert(-1 != socketDescriptor); + + ret = send(socketDescriptor, buffer, len, 0); + if (ret != len) + { + LOG_E( "writeData(): could no send all data, ret=%d, errno: %d", ret,errno); + ret = -1; + } + + return ret; +} + +/** @} */ diff --git a/mobicore/daemon/Common/Connection.h b/mobicore/daemon/Common/Connection.h new file mode 100644 index 0000000..81e8dd8 --- /dev/null +++ b/mobicore/daemon/Common/Connection.h @@ -0,0 +1,125 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection data. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CONNECTION_H_ +#define CONNECTION_H_ + +#include <list> +#include <exception> + +#include <inttypes.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + + +class Connection { + +public: + struct sockaddr_un remote; /**< Remote address */ + int32_t socketDescriptor; /**< Local socket descriptor */ + void *connectionData; /**< reference to data related with the connection */ + bool detached; /**< Connection state */ + + Connection( + void + ); + + Connection( + int socketDescriptor, + sockaddr_un *remote + ); + + virtual ~Connection( + void + ); + + /** + * Connect to destination. + * + * @param Destination pointer. + * @return true on success. + */ + virtual bool connect( + const char *dest + ); + + /** + * Read bytes from the connection. + * + * @param buffer Pointer to destination buffer. + * @param len Number of bytes to read. + * @param timeout Timeout in milliseconds + * @return Number of bytes read. + * @return -1 if select() failed (returned -1) + * @return -2 if no data available, i.e. timeout + */ + virtual size_t readData( + void *buffer, + uint32_t len, + int32_t timeout + ); + + /** + * Read bytes from the connection. + * + * @param buffer Pointer to destination buffer. + * @param len Number of bytes to read. + * @return Number of bytes read. + */ + virtual size_t readData( + void * buffer, + uint32_t len + ); + + /** + * Write bytes to the connection. + * + * @param buffer Pointer to source buffer. + * @param len Number of bytes to read. + * @return Number of bytes written. + */ + virtual size_t writeData( + void *buffer, + uint32_t len + ); + +}; + +typedef std::list<Connection*> connectionList_t; +typedef connectionList_t::iterator connectionIterator_t; + + +#endif /* CONNECTION_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Common/McTypes.h b/mobicore/daemon/Common/McTypes.h new file mode 100644 index 0000000..a4f8f4f --- /dev/null +++ b/mobicore/daemon/Common/McTypes.h @@ -0,0 +1,40 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * MobiCore types redefinition. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCTYPES_H_ +#define MCTYPES_H_ + +typedef void *addr_t; + +#endif /* MCTYPES_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Common/NetlinkConnection.cpp b/mobicore/daemon/Common/NetlinkConnection.cpp new file mode 100644 index 0000000..81b394b --- /dev/null +++ b/mobicore/daemon/Common/NetlinkConnection.cpp @@ -0,0 +1,289 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection data. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <cstring> +#include <errno.h> +#include <stdio.h> +#include <sys/socket.h> +#include <linux/netlink.h> + +#include "NetlinkConnection.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + + +uint64_t hashConnection( + pid_t pid, + uint32_t seq +) +{ + return (((uint64_t)seq) << 32) | (uint64_t)pid; +} + + +//------------------------------------------------------------------------------ +NetlinkConnection::NetlinkConnection( + void +) :Connection(), + dataLeft(0), + manager(NULL) +{ + detached = false; + dataMsg = NULL; + dataStart = NULL; + dataLen = 0; + + + selfPid = getpid(); + peerPid = 0; + sequenceMagic = 0; + hash = hashConnection(peerPid, sequenceMagic); +} + + +//------------------------------------------------------------------------------ +NetlinkConnection::NetlinkConnection( + NetlinkConnectionManager *manager, + int socketDescriptor, + uint32_t pid, + uint32_t seq +): Connection(), + dataLeft(0), + manager(manager) +{ + detached = false; + dataMsg = NULL; + dataStart = NULL; + dataLen = 0; + + this->socketDescriptor = socketDescriptor; + selfPid = getpid(); + peerPid = pid; + sequenceMagic = seq; + hash = hashConnection(pid, seq); +} + + +//------------------------------------------------------------------------------ +NetlinkConnection::~NetlinkConnection( + void +) { + LOG_I("%s: destroy connection for PID 0x%X", __func__, peerPid); + socketDescriptor = -1; + free(dataMsg); + + if (manager) { + manager->removeConnection(hash); + } +} + + +//------------------------------------------------------------------------------ +bool NetlinkConnection::connect( + const char *dest +) { + struct sockaddr_nl addr; + bool ret = false; + + assert(NULL != dest); + + LOG_I("%s: Connecting to SEQ 0x%X", __func__, MC_DAEMON_PID); + do { + if ((socketDescriptor = socket(PF_NETLINK, SOCK_DGRAM, MC_DAEMON_NETLINK)) < 0) { + LOG_E("%s: Can't open netlink socket - errno: %d(%s)", + __func__, errno, strerror(errno)); + break; + } + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + addr.nl_pid = selfPid; /* self pid */ + addr.nl_groups = 0; /* not in mcast groups */ + + if (bind(socketDescriptor, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + LOG_E("%s: bind() failed - errno: %d(%s)", __func__, errno, strerror(errno)); + close(socketDescriptor); + + // Set invalid socketDescriptor + socketDescriptor = -1; + break; + } + ret = true; + + + } while (false); + + return ret; +} + + +//------------------------------------------------------------------------------ +void NetlinkConnection::handleMessage( + struct nlmsghdr *nlh +) { + dataMutex.lock(); + /* Takeover the buffer */ + dataMsg = nlh; + dataLen = NLMSG_PAYLOAD(dataMsg, 0); + dataStart = static_cast<uint8_t *>(NLMSG_DATA(dataMsg)); + dataMutex.unlock(); + dataLeft.signal(); +} + +//------------------------------------------------------------------------------ +size_t NetlinkConnection::readData( + void *buffer, + uint32_t len +) { + return readData(buffer, len, -1); +} + + +//------------------------------------------------------------------------------ +size_t NetlinkConnection::readData( + void *buffer, + uint32_t len, + int32_t timeout +) { + size_t ret = -1; + assert(NULL != buffer); + + if(!dataLeft.wait(timeout)){ + return -2; + } + dataMutex.lock(); + // No data left?? Could we get this far? + if (dataLen <= 0) + { + dataMutex.unlock(); + return -2; + } + + //LOG_I("%s: reading connection data %u, connection data left %u", + // __func__, len, dataLen); + + assert(dataStart != NULL); + + // trying to read more than the left data + if (len > dataLen) + { + ret = dataLen; + memcpy(buffer, dataStart, dataLen); + dataLen = 0; + } + else + { + ret = len; + memcpy(buffer, dataStart, len); + dataLen -= len; + dataStart += len; + } + + if (dataLen == 0) + { + dataStart = NULL; + free(dataMsg); + dataMsg = NULL; + } + else{ + // Still some data left + dataLeft.signal(); + } + dataMutex.unlock(); + + //LOG_I("%s: read %u", __func__, ret); + return ret; +} + +//------------------------------------------------------------------------------ +size_t NetlinkConnection::writeData( + void *buffer, + uint32_t len +) { + size_t ret; + struct sockaddr_nl dest_addr; + struct nlmsghdr *nlh = NULL; + struct iovec iov; + struct msghdr msg; + + assert(NULL != buffer); + assert(-1 != socketDescriptor); + + //LOG_I("%s: send data %u to PID %u", __func__, len, sequenceMagic); + + memset(&dest_addr, 0, sizeof(dest_addr)); + dest_addr.nl_family = AF_NETLINK; + dest_addr.nl_pid = peerPid; + dest_addr.nl_groups = 0; /* unicast */ + + nlh=(struct nlmsghdr *)malloc( + NLMSG_SPACE(len)); + /* Fill the netlink message header */ + nlh->nlmsg_len = NLMSG_SPACE(len); + nlh->nlmsg_pid = selfPid; + nlh->nlmsg_flags = NLM_F_REQUEST; + nlh->nlmsg_seq = sequenceMagic; + + /* Fill in the netlink message payload */ + memcpy(NLMSG_DATA(nlh), buffer, len); + + iov.iov_base = (void *)nlh; + iov.iov_len = nlh->nlmsg_len; + msg.msg_name = (void *)&dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + + ret = sendmsg(socketDescriptor, &msg, 0); + if (ret != NLMSG_SPACE(len)) + { + LOG_E( "%s: could no send all data, ret=%d, errno: %d(%s)", + __func__, ret, errno, strerror(errno)); + ret = -1; + } + else{ + /* The whole message sent also includes the header, so make sure to + * return only the number of payload data sent, not everything */ + ret = len; + } + + free(nlh); + + return ret; +} + +/** @} */ diff --git a/mobicore/daemon/Common/NetlinkConnection.h b/mobicore/daemon/Common/NetlinkConnection.h new file mode 100644 index 0000000..7121919 --- /dev/null +++ b/mobicore/daemon/Common/NetlinkConnection.h @@ -0,0 +1,218 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection data. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 NETLINKCONNECTION_H_ +#define NETLINKCONNECTION_H_ + +#include <unistd.h> +#include <map> +#include <exception> +#include <inttypes.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include "Connection.h" +#include "CMutex.h" +#include "CSemaphore.h" + +/** PID(address) of MC daemon. */ +#define MC_DAEMON_PID 0xFFFFFFFF +/** Maximum Netlink payload size + * TODO: figure out the best value for this */ +#define MAX_PAYLOAD 1024 + +#define MC_DAEMON_NETLINK 17 + + +class NetlinkConnection; + +/** + * Hash function for unique ID of a connection. + * + * @param pid Connection PID + * @param seq Connection sequenceMagic + * + * @return Unique identifier of the connection + */ +uint64_t hashConnection(pid_t pid, uint32_t seq); + +/** Netlink connection manager interface. + * This inteface has to be implemented by the handling server + * to ensure connection will be removed from accounting when destroied. */ +class NetlinkConnectionManager { +public: + virtual ~NetlinkConnectionManager(){}; + /** + * Retreive connection based on a unique hash. + * Search the peer connections hashmap for a hash and return + * the associated Connection object + * + * @param hash The hash to search + * @return The NetlinkConnection object if found or NULL if not found + */ + virtual NetlinkConnection* findConnection( + uint64_t hash + ) = 0; + + /** + * Insert a connection in connection lisst + * Insert a new connection in the peer connections list. If there + * is already such a connection + * it will be overriden! + * + * @param hash The hash to use + * @param connection The connection object to insert + */ + virtual void insertConnection( + uint64_t hash, + NetlinkConnection *connection + ) = 0; + + /** + * Remove a connection from the peer connections + * Remove the connection associated with seq from the peer list. + * This doesn't actually free the connection object! + * If the hash is invalid nothing happens. + * + * @param hash The hash hash use + */ + virtual void removeConnection( + uint64_t hash + ) = 0; +}; + +class NetlinkConnection: public Connection { +public: + pid_t selfPid; /**< Which PID to use to identify when writing data */ + pid_t peerPid; /**< Destination PID for sending data */ + uint32_t sequenceMagic; /**< Random? magic to match requests/answers */ + uint64_t hash; /**< Unique connection ID, see hashConnection */ + + NetlinkConnection( + void + ); + + /** + * Connection main constructor + * + * @param manager Connection manager pointer. + * @param socketDescriptor Socket descriptor to use for writing + * @param pid Connection PID + * @param seq Connection sequence magic number + */ + NetlinkConnection( + NetlinkConnectionManager *manager, + int socketDescriptor, + uint32_t pid, + uint32_t seq + ); + + virtual ~NetlinkConnection( + void + ); + + /** + * Connect to destination. + * + * @param Destination pointer. + * @return true on success. + */ + virtual bool connect( + const char *dest + ); + + /** + * Read bytes from the connection(compatiblity method). + * + * @param buffer Pointer to destination buffer. + * @param len Number of bytes to read. + * @param timeout Timeout in milliseconds(ignored) + * @return Number of bytes read. + * @return -1 if select() failed (returned -1) + * @return -2 if no data available, i.e. timeout + */ + virtual size_t readData( + void *buffer, + uint32_t len, + int32_t timeout + ); + + /** + * Read bytes from the connection. + * + * @param buffer Pointer to destination buffer. + * @param len Number of bytes to read. + * @return Number of bytes read. + */ + virtual size_t readData( + void * buffer, + uint32_t len + ); + + /** + * Write bytes to the connection. + * + * @param buffer Pointer to source buffer. + * @param len Number of bytes to read. + * @return Number of bytes written. + */ + virtual size_t writeData( + void *buffer, + uint32_t len + ); + + /** + * Set the internal data connection. + * This method is called by the + * + * @param nlh Netlink structure pointing to data. + */ + void handleMessage( + struct nlmsghdr *nlh + ); + +private: + CMutex dataMutex; + CSemaphore dataLeft; + struct nlmsghdr *dataMsg; /**< Last message received */ + uint32_t dataLen; /**< How much connection data is left */ + uint8_t *dataStart; /**< Start pointer of remaining data */ + NetlinkConnectionManager *manager; /**< Netlink connection manager(eg. NetlinkServer) */ +}; + +typedef std::map<uint64_t, NetlinkConnection*> connectionMap_t; + +#endif /* NETLINKCONNECTION_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Android.mk b/mobicore/daemon/Daemon/Android.mk new file mode 100644 index 0000000..149305a --- /dev/null +++ b/mobicore/daemon/Daemon/Android.mk @@ -0,0 +1,43 @@ +# ============================================================================= +# +# Module: mcDriverDaemon +# +# ============================================================================= +LOCAL_PATH := $(call my-dir) +MY_MCDRIVER_PATH := $(LOCAL_PATH) + +include $(CLEAR_VARS) + +LOCAL_MODULE := mcDriverDaemon +LOCAL_MODULE_TAGS := eng + +# Add new subdirectories containing code here +include $(LOCAL_PATH)/Device/Android.mk +include $(LOCAL_PATH)/Server/Android.mk + +LOCAL_C_INCLUDES += bionic \ + external/stlport/stlport + +# Add new folders with header files here +LOCAL_C_INCLUDES += \ + $(COMP_PATH_MobiCore)/inc \ + $(COMP_PATH_MobiCoreDriverMod)/Public \ + $(APP_PROJECT_PATH)/ClientLib/public \ + $(APP_PROJECT_PATH)/Kernel \ + $(APP_PROJECT_PATH)/Kernel/Platforms/Generic \ + $(APP_PROJECT_PATH)/Common \ + $(APP_PROJECT_PATH)/Registry/Public \ + $(MY_MCDRIVER_PATH)/public + +# Add new source files here +LOCAL_SRC_FILES += \ + MobiCoreDriverDaemon.cpp + +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions +# Modules this one depnds on (depending ones first) +LOCAL_STATIC_LIBRARIES = libstlport_static libMcKernel libMcCommon libMcRegistry + +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_EXECUTABLE) + diff --git a/mobicore/daemon/Daemon/Device/Android.mk b/mobicore/daemon/Daemon/Device/Android.mk new file mode 100644 index 0000000..5ae55d8 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/Android.mk @@ -0,0 +1,26 @@ +# ============================================================================= +# +# MC driver device files +# +# ============================================================================= + +# This is not a separate module. +# Only for inclusion by other modules. + +MY_MCDRV_DEVICE_PATH := $(call my-dir) +MY_MCDRV_DEVICE_PATH_REL := Device + +include $(MY_MCDRV_DEVICE_PATH)/Platforms/Android.mk + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(MY_MCDRV_DEVICE_PATH)\ + $(MY_MCDRV_DEVICE_PATH)/public + +# Add new source files here +LOCAL_SRC_FILES +=\ + $(MY_MCDRV_DEVICE_PATH_REL)/DeviceIrqHandler.cpp\ + $(MY_MCDRV_DEVICE_PATH_REL)/DeviceScheduler.cpp\ + $(MY_MCDRV_DEVICE_PATH_REL)/MobiCoreDevice.cpp\ + $(MY_MCDRV_DEVICE_PATH_REL)/NotificationQueue.cpp\ + $(MY_MCDRV_DEVICE_PATH_REL)/TrustletSession.cpp\ diff --git a/mobicore/daemon/Daemon/Device/DeviceIrqHandler.cpp b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.cpp new file mode 100644 index 0000000..e941c88 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.cpp @@ -0,0 +1,44 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "DeviceIrqHandler.h" + + +//------------------------------------------------------------------------------ +void DeviceIrqHandler::run( + void +) { + handleIrq(); + this->exit(-1); +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/DeviceIrqHandler.h b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.h new file mode 100644 index 0000000..957db40 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.h @@ -0,0 +1,51 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * IRQ handler thread. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 DEVICEIRQHANDLER_H_ +#define DEVICEIRQHANDLER_H_ + +#include "CThread.h" + + +class DeviceIrqHandler: public CThread { + +public: + + virtual void handleIrq() =0; + + void run(); +}; + +#endif /* DEVICEIRQHANDLER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/DeviceScheduler.cpp b/mobicore/daemon/Daemon/Device/DeviceScheduler.cpp new file mode 100644 index 0000000..30024fb --- /dev/null +++ b/mobicore/daemon/Daemon/Device/DeviceScheduler.cpp @@ -0,0 +1,44 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "DeviceScheduler.h" + + +//------------------------------------------------------------------------------ +void DeviceScheduler::run( + void +) { + schedule(); + exit(-1); +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/DeviceScheduler.h b/mobicore/daemon/Daemon/Device/DeviceScheduler.h new file mode 100644 index 0000000..5698f68 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/DeviceScheduler.h @@ -0,0 +1,52 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * Scheduler thread + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 DEVICESCHEDULER_H_ +#define DEVICESCHEDULER_H_ + +#include "CThread.h" + + +class DeviceScheduler: public CThread { + +public: + + virtual void schedule() =0; + + void run(); + +}; + +#endif /* DEVICESCHEDULER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/MobiCoreDevice.cpp b/mobicore/daemon/Daemon/Device/MobiCoreDevice.cpp new file mode 100644 index 0000000..a5cfa71 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/MobiCoreDevice.cpp @@ -0,0 +1,626 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <cstdlib> +#include <pthread.h> +#include "McTypes.h" + +#include "DeviceScheduler.h" +#include "DeviceIrqHandler.h" +#include "ExcDevice.h" +#include "Connection.h" +#include "TrustletSession.h" + +#include "MobiCoreDevice.h" +#include "Mci/mci.h" +#include "mcLoadFormat.h" + + +#define LOG_TAG "McDaemon" +#include "log.h" +#include "public/MobiCoreDevice.h" + + +//------------------------------------------------------------------------------ +MobiCoreDevice::MobiCoreDevice() { + mcFault = false; +} + +//------------------------------------------------------------------------------ +MobiCoreDevice::~MobiCoreDevice() { + delete mcVersionInfo; + mcVersionInfo = NULL; +} + +//------------------------------------------------------------------------------ +TrustletSession* MobiCoreDevice::getTrustletSession( + uint32_t sessionId +) { + TrustletSession* ts = NULL; + + for (trustletSessionIterator_t session = trustletSessions.begin(); + session != trustletSessions.end(); + ++session) { + TrustletSession* tsTmp = *session; + if (tsTmp->sessionId == sessionId) + { + ts = tsTmp; + break; + } + } + return ts; +} + + +//------------------------------------------------------------------------------ +Connection * MobiCoreDevice::getSessionConnection( + uint32_t sessionId, + notification_t *notification +) { + Connection *con = NULL; + TrustletSession* ts = NULL; + + ts = getTrustletSession(sessionId); + if (NULL == ts) { + return NULL; + } + + con = ts->notificationConnection; + if(NULL == con) { + ts->queueNotification(notification); + return NULL; + } + + return con; +} + + +//------------------------------------------------------------------------------ +bool MobiCoreDevice::open( + Connection *connection +) { + // Link this device to the connection + connection->connectionData = this; + return true; +} + + +//------------------------------------------------------------------------------ +/** + * Close device. + * + * Removes all sessions to a connection. Though, clientLib rejects the closeDevice() + * command if still sessions connected to the device, this is needed to clean up all + * sessions if client dies. + */ +void MobiCoreDevice::close( + Connection *connection +) { + trustletSessionList_t::reverse_iterator interator; + static CMutex mutex; + // 1. Iterate through device session to find connection + // 2. Decide what to do with open Trustlet sessions + // 3. Remove & delete deviceSession from vector + + // Enter critical section + mutex.lock(); + for (interator = trustletSessions.rbegin(); + interator != trustletSessions.rend(); + interator++) { + TrustletSession* ts = *interator; + + if (ts->deviceConnection == connection) { + closeSession(connection, ts->sessionId); + } + } + // Leave critical section + mutex.unlock(); + + connection->connectionData = NULL; +} + + +//------------------------------------------------------------------------------ +void MobiCoreDevice::start( + void +) { + // Call the device specific initialization + // initDevice(); + + LOG_I("Starting DeviceIrqHandler..."); + // Start the irq handling thread + DeviceIrqHandler::start(); + + if (schedulerAvailable()) { + LOG_I("Starting DeviceScheduler..."); + // Start the scheduling handling thread + DeviceScheduler::start(); + } else { + LOG_I("No DeviceScheduler available."); + } +} + + +//------------------------------------------------------------------------------ +void MobiCoreDevice::signalMcpNotification( + void +) { + mcpSessionNotification.signal(); +} + + +//------------------------------------------------------------------------------ +bool MobiCoreDevice::waitMcpNotification( + void +) { + int counter = 5; + while (1) { + // In case of fault just return, nothing to do here + if (mcFault) { + return false; + } + // Wait 10 seconds for notification + if (mcpSessionNotification.wait(10) == false) { + // No MCP answer received and mobicore halted, dump mobicore status + // then throw exception + LOG_I("No MCP answer received in 2 seconds."); + if (getMobicoreStatus() == MC_STATUS_HALT) { + dumpMobicoreStatus(); + mcFault = true; + return false; + } else { + counter--; + if (counter < 1) { + mcFault = true; + return false; + } + } + } else { + break; + } + } + + // Check healthiness state of the device + if (DeviceIrqHandler::isExiting()) { + LOG_I("waitMcpNotification(): IrqHandler thread died! Joining"); + DeviceIrqHandler::join(); + LOG_I("waitMcpNotification(): Joined"); + LOG_E("IrqHandler thread died!"); + return false; + } + + if (DeviceScheduler::isExiting()) { + LOG_I("waitMcpNotification(): Scheduler thread died! Joining"); + DeviceScheduler::join(); + LOG_I("waitMcpNotification(): Joined"); + LOG_E("Scheduler thread died!"); + return false; + } + return true; +} + + +//------------------------------------------------------------------------------ +void MobiCoreDevice::openSession( + Connection *deviceConnection, + loadDataOpenSession_ptr pLoadDataOpenSession, + mcDrvCmdOpenSessionPayload_ptr pCmdOpenSessionPayload, + mcDrvRspOpenSessionPayload_ptr pRspOpenSessionPayload +) { + + do { + // Write MCP open message to buffer + mcpMessage->cmdOpen.cmdHeader.cmdId = MC_MCP_CMD_OPEN_SESSION; + mcpMessage->cmdOpen.uuid = pCmdOpenSessionPayload->uuid; + mcpMessage->cmdOpen.wsmTypeTci = WSM_CONTIGUOUS; + mcpMessage->cmdOpen.adrTciBuffer = (uint32_t)(pCmdOpenSessionPayload->tci); + mcpMessage->cmdOpen.ofsTciBuffer = 0; + mcpMessage->cmdOpen.lenTciBuffer = pCmdOpenSessionPayload->len; + + LOG_I("%s(): tciPhys=%p, len=%d,", __FUNCTION__, + (addr_t)(pCmdOpenSessionPayload->tci), + pCmdOpenSessionPayload->len); + + // check if load data is provided + if(NULL == pLoadDataOpenSession) + { + // Preinstalled trustlet shall be loaded + mcpMessage->cmdOpen.wsmTypeLoadData = WSM_INVALID; + } + else + { + mcpMessage->cmdOpen.wsmTypeLoadData = WSM_L2; + mcpMessage->cmdOpen.adrLoadData = (uint32_t)pLoadDataOpenSession->baseAddr; + mcpMessage->cmdOpen.ofsLoadData = pLoadDataOpenSession->offs; + mcpMessage->cmdOpen.lenLoadData = pLoadDataOpenSession->len; + memcpy(&mcpMessage->cmdOpen.tlHeader, pLoadDataOpenSession->tlHeader, sizeof(*pLoadDataOpenSession->tlHeader)); + } + + // Clear the notifications queue. We asume the race condition we have + // seen in openSession never happens elsewhere + notifications = std::queue<notification_t>(); + // Notify MC about a new command inside the MCP buffer + notify(SID_MCP); + + // Wait till response from MC is available + if(!waitMcpNotification()) { + break; + } + + // Check if the command response ID is correct + if ((MC_MCP_CMD_OPEN_SESSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) + { + LOG_E("%s(): CMD_OPEN_SESSION got invalid MCP command response(0x%X)", + __FUNCTION__, mcpMessage->rspHeader.rspId); + break; + } + + uint32_t mcRet = mcpMessage->rspOpen.rspHeader.result; + pRspOpenSessionPayload->mcResult = mcRet; + + if(MC_MCP_RET_OK != mcRet) + { + LOG_E("%s: CMD_OPEN_SESSION error %d", __FUNCTION__, mcRet); + break; + } + + LOG_I("%s: We have %d queued notifications after open session", + __FUNCTION__, notifications.size()); + // Read MC answer from MCP buffer + TrustletSession *trustletSession = new TrustletSession( + deviceConnection, + mcpMessage->rspOpen.sessionId); + + pRspOpenSessionPayload->deviceId = pCmdOpenSessionPayload->deviceId; + pRspOpenSessionPayload->sessionId = trustletSession->sessionId; + pRspOpenSessionPayload->deviceSessionId = (uint32_t)trustletSession; + pRspOpenSessionPayload->sessionMagic = trustletSession->sessionMagic; + + trustletSessions.push_back(trustletSession); + // We have some queued notifications and we need to send them to them + // trustlet session + while (!notifications.empty()) { + trustletSession->queueNotification(¬ifications.front()); + notifications.pop(); + } + + } while(0); +} + + +//------------------------------------------------------------------------------ +TrustletSession *MobiCoreDevice::registerTrustletConnection( + Connection *connection, + mcDrvCmdNqConnectPayload_ptr pCmdNqConnectPayload +) { + LOG_I("%s(): searching sessionMagic %d and sessionId %d", __FUNCTION__, + pCmdNqConnectPayload->sessionMagic, + pCmdNqConnectPayload->sessionId); + + for (trustletSessionIterator_t iterator = trustletSessions.begin(); + iterator != trustletSessions.end(); + ++iterator) { + TrustletSession *ts = *iterator; + + if (ts != (TrustletSession*) (pCmdNqConnectPayload->deviceSessionId)) { + continue; + } + + if ( (ts->sessionMagic != pCmdNqConnectPayload->sessionMagic) + || (ts->sessionId != pCmdNqConnectPayload->sessionId)) { + continue; + } + + LOG_I("%s(): found connection", __FUNCTION__); + + ts->notificationConnection = connection; + return ts; + } + + LOG_I("registerTrustletConnection(): search failed"); + return NULL; +} + + +//------------------------------------------------------------------------------ +/** + * Need connection as well as according session ID, so that a client can not + * close sessions not belonging to him. + */ +bool MobiCoreDevice::closeSession( + Connection *deviceConnection, + uint32_t sessionId +) { + bool ret = true; + + do { + TrustletSession *ts = NULL; + trustletSessionIterator_t iterator; + + // Search object to session id + for (iterator = trustletSessions.begin(); + iterator != trustletSessions.end(); + ++iterator) + { + TrustletSession *tsTmp = *iterator; + if ( (tsTmp->sessionId == sessionId) + && (tsTmp->deviceConnection == deviceConnection)) + { + ts = tsTmp; + break; + } + } + if (NULL == ts) + { + LOG_I("closeSession(): no session found with id=%d",sessionId); + ret = false; + break; + } + + LOG_I("closeSession(): Write MCP close message to buffer and notify, wait"); + + // Write MCP close message to buffer + mcpMessage->cmdClose.cmdHeader.cmdId = MC_MCP_CMD_CLOSE_SESSION; + mcpMessage->cmdClose.sessionId = sessionId; + + // Notify MC about the availability of a new command inside the MCP buffer + notify(SID_MCP); + + // Wait till response from MSH is available + if(!waitMcpNotification()) { + ret = false; + break; + } + + // Check if the command response ID is correct + if ((MC_MCP_CMD_CLOSE_SESSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) { + LOG_E("closeSession(): CMD_CLOSE_SESSION got invalid MCP response"); + ret = false; + break; + } + + // Read MC answer from MCP buffer + uint32_t mcRet = mcpMessage->rspOpen.rspHeader.result; + + if( MC_MCP_RET_OK != mcRet) { + LOG_E("closeSession(): CMD_CLOSE_SESSION error %d",mcRet); + ret = false; + break; + } + + // remove objects + trustletSessions.erase(iterator); + delete ts; + + } while(0); + + return ret; +} + + +//------------------------------------------------------------------------------ +void MobiCoreDevice::mapBulk( + Connection *deviceConnection, + mcDrvCmdMapBulkMemPayload_ptr pCmdMapBulkMemPayload, + mcDrvRspMapBulkMemPayload_ptr pRspMapBulkMemPayload +) { + do + { + + // Write MCP map message to buffer + mcpMessage->cmdMap.cmdHeader.cmdId = MC_MCP_CMD_MAP; + mcpMessage->cmdMap.sessionId = pCmdMapBulkMemPayload->sessionId; + mcpMessage->cmdMap.wsmType = WSM_L2; + mcpMessage->cmdMap.adrBuffer = (uint32_t)(pCmdMapBulkMemPayload->pAddrL2); + mcpMessage->cmdMap.ofsBuffer = pCmdMapBulkMemPayload->offsetPayload; + mcpMessage->cmdMap.lenBuffer = pCmdMapBulkMemPayload->lenBulkMem; + + // Notify MC about the availability of a new command inside the MCP buffer + notify(SID_MCP); + + // Wait till response from MC is available + if(!waitMcpNotification()) { + break; + } + + // Check if the command response ID is correct + if ((MC_MCP_CMD_MAP | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) { + LOG_E("mapBulk(): CMD_MAP got invalid MCP response"); + break; + } + + uint32_t mcRet = mcpMessage->rspMap.rspHeader.result; + pRspMapBulkMemPayload->mcResult = mcRet; + pRspMapBulkMemPayload->sessionId = pCmdMapBulkMemPayload->sessionId; + + if(MC_MCP_RET_OK != mcRet) { + LOG_E("mapBulk(): CMD_MAP error %d",mcRet); + break; + } + + pRspMapBulkMemPayload->secureVirtualAdr = mcpMessage->rspMap.secureVirtualAdr; + + } while(0); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDevice::unmapBulk( + Connection *deviceConnection, + mcDrvCmdUnmapBulkMemPayload_ptr pCmdUnmapBulkMemPayload, + mcDrvRspUnmapBulkMemPayload_ptr pRspUnmapBulkMemPayload +) { + do { + // Write MCP unmap command to buffer + mcpMessage->cmdUnmap.cmdHeader.cmdId = MC_MCP_CMD_UNMAP; + mcpMessage->cmdUnmap.sessionId = pCmdUnmapBulkMemPayload->sessionId; + mcpMessage->cmdUnmap.wsmType = WSM_L2; + mcpMessage->cmdUnmap.secureVirtualAdr = pCmdUnmapBulkMemPayload->secureVirtualAdr; + mcpMessage->cmdUnmap.lenVirtualBuffer = pCmdUnmapBulkMemPayload->lenBulkMem; + + // Notify MC about the availability of a new command inside the MCP buffer + notify(SID_MCP); + + // Wait till response from MC is available + if(!waitMcpNotification()) { + break; + } + + // Check if the command response ID is correct + if ((MC_MCP_CMD_UNMAP | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) + { + LOG_E("unmapBulk(): CMD_OPEN_SESSION got invalid MCP response"); + break; + } + + uint32_t mcRet = mcpMessage->rspUnmap.rspHeader.result; + pRspUnmapBulkMemPayload->mcResult = mcRet; + pRspUnmapBulkMemPayload->sessionId = pCmdUnmapBulkMemPayload->sessionId; + + if(MC_MCP_RET_OK != mcRet) + { + LOG_E("unmapBulk(): MC_MCP_CMD_UNMAP error %d",mcRet); + break; + } + + } while(0); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDevice::donateRam( + const uint32_t donationSize +) { + // Donate additional RAM to the MobiCore + CWsm_ptr ram = allocateContiguousPersistentWsm(donationSize); + if (NULL == ram) { + LOG_E("Allocation of additional RAM failed"); + return; + } + ramType_t ramType = RAM_GENERIC; + addr_t adrBuffer = ram->physAddr; + const uint32_t numPages = donationSize / (4 * 1024); + + + LOG_I("donateRam(): adrBuffer=%p, numPages=%d, ramType=%d", + adrBuffer, + numPages, + ramType); + + do { + // Write MCP open message to buffer + mcpMessage->cmdDonateRam.cmdHeader.cmdId = MC_MCP_CMD_DONATE_RAM; + mcpMessage->cmdDonateRam.adrBuffer = (uint32_t) adrBuffer; + mcpMessage->cmdDonateRam.numPages = numPages; + mcpMessage->cmdDonateRam.ramType = ramType; + + // Notify MC about a new command inside the MCP buffer + notify(SID_MCP); + + // Wait till response from MC is available + if(!waitMcpNotification()) { + break; + } + + // Check if the command response ID is correct + if ((MC_MCP_CMD_DONATE_RAM | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) + { + LOG_E("donateRam(): CMD_DONATE_RAM got invalid MCP response - rspId is: %d", + mcpMessage->rspHeader.rspId); + break; + } + + uint32_t mcRet = mcpMessage->rspDonateRam.rspHeader.result; + if(MC_MCP_RET_OK != mcRet) + { + LOG_E("donateRam(): CMD_DONATE_RAM error %d", mcRet); + break; + } + + LOG_I("donateRam() succeeded."); + + } while(0); +} + +//------------------------------------------------------------------------------ +void MobiCoreDevice::getMobiCoreVersion( + mcDrvRspGetMobiCoreVersionPayload_ptr pRspGetMobiCoreVersionPayload +) { + // If MobiCore version info already fetched. + if (mcVersionInfo != NULL) { + pRspGetMobiCoreVersionPayload->mcResult = MC_MCP_RET_OK; + pRspGetMobiCoreVersionPayload->versionInfo = *mcVersionInfo; + // Otherwise, fetch it via MCP. + } else { + pRspGetMobiCoreVersionPayload->mcResult = MC_MCP_RET_ERR_UNKNOWN; + + // Write MCP unmap command to buffer + mcpMessage->cmdGetMobiCoreVersion.cmdHeader.cmdId = MC_MCP_CMD_GET_MOBICORE_VERSION; + + // Notify MC about the availability of a new command inside the MCP buffer + notify(SID_MCP); + + // Wait till response from MC is available + if(!waitMcpNotification()) { + return; + } + + // Check if the command response ID is correct + if ((MC_MCP_CMD_GET_MOBICORE_VERSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) { + LOG_E("getMobiCoreVersion(): MC_MCP_CMD_GET_MOBICORE_VERSION got invalid MCP response"); + return; + } + + uint32_t mcRet = mcpMessage->rspGetMobiCoreVersion.rspHeader.result; + pRspGetMobiCoreVersionPayload->mcResult = mcRet; + + if(MC_MCP_RET_OK != mcRet) { + LOG_E("getMobiCoreVersion(): MC_MCP_CMD_GET_MOBICORE_VERSION error %d",mcRet); + return; + } + + pRspGetMobiCoreVersionPayload->versionInfo = mcpMessage->rspGetMobiCoreVersion.versionInfo; + + // Store MobiCore info for future reference. + mcVersionInfo = new mcVersionInfo_t(); + *mcVersionInfo = pRspGetMobiCoreVersionPayload->versionInfo; + } +} + +//------------------------------------------------------------------------------ +void MobiCoreDevice::queueUnknownNotification( + notification_t notification +) { + notifications.push(notification); +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/NotificationQueue.cpp b/mobicore/daemon/Daemon/Device/NotificationQueue.cpp new file mode 100644 index 0000000..c9a79ff --- /dev/null +++ b/mobicore/daemon/Daemon/Device/NotificationQueue.cpp @@ -0,0 +1,77 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "NotificationQueue.h" +#include <stddef.h> + +#define LOG_TAG "McDaemon" +#include "log.h" + +//------------------------------------------------------------------------------ +NotificationQueue::NotificationQueue( + notificationQueue_t *i, + notificationQueue_t *o, + uint32_t size +) : in(i), out(o) { + in->hdr.queueSize = size; + out->hdr.queueSize = size; +} + + +//------------------------------------------------------------------------------ +void NotificationQueue::putNotification( + notification_t *notification +) { + mutex.lock(); + if ((out->hdr.writeCnt - out->hdr.readCnt) < out->hdr.queueSize) { + out->notification[out->hdr.writeCnt & (out->hdr.queueSize - 1)] + = *notification; + out->hdr.writeCnt++; + } + mutex.unlock(); +} + + +//------------------------------------------------------------------------------ +notification_t *NotificationQueue::getNotification( + void +) { + notification_t *ret = NULL; + mutex.lock(); + if ((in->hdr.writeCnt - in->hdr.readCnt) > 0) { + ret = &(in->notification[in->hdr.readCnt & (in->hdr.queueSize - 1)]); + in->hdr.readCnt++; + } + mutex.unlock(); + return ret; +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/NotificationQueue.h b/mobicore/daemon/Daemon/Device/NotificationQueue.h new file mode 100644 index 0000000..c3f60bf --- /dev/null +++ b/mobicore/daemon/Daemon/Device/NotificationQueue.h @@ -0,0 +1,86 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * MobiCore Notification Queue handling. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 NOTIFICATIONQUEUE_H_ +#define NOTIFICATIONQUEUE_H_ + +#include <inttypes.h> //C99 data +#include "Mci/mcinq.h" +#include "CMutex.h" + + +class NotificationQueue { + +public: + + /** NQ Constructor, initializes the NQ component. + * + * makes the given queue object usable with the queue<Command> type of functions + * + * @param in queue to initialize + * @param out beginning of queue header + * @param queueSize Size of the queue + */ + NotificationQueue( + notificationQueue_t *in, + notificationQueue_t *out, + uint32_t size + ); + + /** Places an element to the outgoing queue. + * + * @param notification Data to be placed in queue. + */ + void putNotification( + notification_t *notification + ); + + /** Retrieves the first element from the queue. + * + * @return first notification Queue element. + * @return NULL if the queue is empty. + */ + notification_t *getNotification( + void + ); + +private: + + notificationQueue_t *in; + notificationQueue_t *out; + CMutex mutex; + +}; + +#endif /* NOTIFICATIONQUEUE_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/Platforms/Android.mk b/mobicore/daemon/Daemon/Device/Platforms/Android.mk new file mode 100644 index 0000000..c367952 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/Platforms/Android.mk @@ -0,0 +1,15 @@ +# ============================================================================= +# +# Makefile pointing to the platform specific makefile. +# +# ============================================================================= + +PLATFORMS_PATH := $(call my-dir) + +# Always include the Generic code +include $(PLATFORMS_PATH)/Generic/Android.mk + +ifneq ($(filter-out Generic,$(PLATFORM)),) + $(info PLATFORM: $(PLATFORM)) + include $(PLATFORMS_PATH)/$(PLATFORM)/Android.mk +endif diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/Android.mk b/mobicore/daemon/Daemon/Device/Platforms/Generic/Android.mk new file mode 100644 index 0000000..50cf589 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/Android.mk @@ -0,0 +1,17 @@ +# ============================================================================= +# +# Generic TrustZone device includes +# +# ============================================================================= + +# This is not a separate module. +# Only for inclusion by other modules. + +GENERIC_PATH := $(call my-dir) +GENERIC_PATH_REL := Device/Platforms/Generic + +# Add new source files here +LOCAL_SRC_FILES +=$(GENERIC_PATH_REL)/TrustZoneDevice.cpp + +# Header files for components including this module +LOCAL_C_INCLUDES += $(call my-dir) diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp new file mode 100644 index 0000000..51dfb69 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp @@ -0,0 +1,698 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <cstdlib> +#include <fstream> +#include <inttypes.h> +#include <list> + +#include "McTypes.h" +#include "mc_drv_module_api.h" +#include "Mci/mci.h" +#include "mcVersionHelper.h" + +#include "CSemaphore.h" +#include "CMcKMod.h" + +#include "MobiCoreDevice.h" +#include "TrustZoneDevice.h" +#include "NotificationQueue.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + + +#define NQ_NUM_ELEMS (16) +#define NQ_BUFFER_SIZE (2 * (sizeof(notificationQueueHeader_t)+ NQ_NUM_ELEMS * sizeof(notification_t))) +#define MCP_BUFFER_SIZE (sizeof(mcpBuffer_t)) +#define MCI_BUFFER_SIZE (NQ_BUFFER_SIZE + MCP_BUFFER_SIZE) + +//------------------------------------------------------------------------------ +MC_CHECK_VERSION(MCI,0,2); + +//------------------------------------------------------------------------------ +__attribute__ ((weak)) MobiCoreDevice* getDeviceInstance( + void +) { + return new TrustZoneDevice(); +} + + +//------------------------------------------------------------------------------ +TrustZoneDevice::TrustZoneDevice( + void +) { + // nothing to do +} + + +//------------------------------------------------------------------------------ +TrustZoneDevice::~TrustZoneDevice( + void +) { + delete pMcKMod; + delete pWsmMcp; + delete nq; +} + + +//------------------------------------------------------------------------------ +static int loadMobiCoreImage( + addr_t virtAddr, + int32_t size, + const char* mobicorePath +) { + + LOG_I("MobiCore path: %s", mobicorePath); + + int ret = 1; + + do { + // Open MobiCore binary for reading only + fstream fs(mobicorePath, ios_base::in | ios_base::binary); + if (!fs) { + LOG_E("MobiCore not found: %s", mobicorePath); + break; + } + + // Get the MobiCore file size + fs.seekg(0, ios::end); + int32_t fileSize = fs.tellg(); + fs.seekg(0, ios::beg); + LOG_I("File size: %i", fileSize); + // Check if file is too big + if (fileSize > size) { + LOG_E("MobiCore size exceeds expectations. Size is: %i", fileSize); + break; + } + + fs.read((char*)virtAddr, fileSize); + + //Create an visible line with different content at the end + memset((void*)((uint32_t)virtAddr+fileSize),0xff,4096); + + // Close file + fs.close(); + ret = 0; + } while (false); + + return ret; +} + + +#define SIZE_DDRAM (256 * 1024) +#define MOBICORE_BINARY_PATH "/data/app/mobicore.img" +//------------------------------------------------------------------------------ +/** + * Set up MCI and wait till MC is initialized + * @return true if mobicore is already initialized + */ +bool TrustZoneDevice::initDevice( + const char *devFile, + bool loadMobiCore, + const char *mobicoreImage, + bool enableScheduler +) throw (ExcDevice) { + + notificationQueue_t* nqStartOut; + notificationQueue_t* nqStartIn; + addr_t mciBuffer; + + pMcKMod = new CMcKMod(); + if (!pMcKMod->open(devFile)) + { + LOG_E("open() kernel module device failed"); + return false; + } + if (!pMcKMod->checkKmodVersionOk()) + { + LOG_E("kernel module version mismatch"); + return false; + } + + // Start MobiCore from DDRAM + if (loadMobiCore) { + // 1. Allocate DDRAM as pseudo IRAM + mobicoreInDDR = allocateContiguousPersistentWsm(SIZE_DDRAM); + if (NULL == mobicoreInDDR) { + LOG_E("Allocation of additional RAM failed"); + return false; + } + memset(mobicoreInDDR->virtAddr,0xCC,SIZE_DDRAM); + + int ret = loadMobiCoreImage(mobicoreInDDR->virtAddr, SIZE_DDRAM, + mobicoreImage); + if (0 != ret) { + LOG_E("loading Mobicore file failed: %d", ret); + return false; + } + + ret = pMcKMod->fcExecute( + mobicoreInDDR->physAddr, + MCP_BUFFER_SIZE); + if (0 != ret) { + LOG_E("pMcKMod->fcExecute() failed : %d", ret); + return false; + } + } + this->schedulerEnabled = enableScheduler; + + // Init MC with NQ and MCP buffer addresses + + // Set up MCI buffer + if(!getMciInstance(MCI_BUFFER_SIZE, &pWsmMcp, &mciReused)) { + return false; + } + mciBuffer = pWsmMcp->virtAddr; + + if(!checkMciVersion()) { + return false; + } + + // Only do a fastcall if MCI has not been reused (MC already initialized) + if (!mciReused) + { + // Wipe memory before first usage + bzero(mciBuffer, MCI_BUFFER_SIZE); + + // Init MC with NQ and MCP buffer addresses + int ret = pMcKMod->fcInit( + pWsmMcp->physAddr, + 0, + NQ_BUFFER_SIZE, + NQ_BUFFER_SIZE, + MCP_BUFFER_SIZE); + if (0 != ret) + { + LOG_E("pMcKMod->fcInit() failed"); + return false; + } + + // First empty N-SIQ which results in set up of the MCI structure + if(!nsiq()) { + return false; + } + + // Wait until MobiCore state switches to MC_STATUS_INITIALIZED + // It is assumed that MobiCore always switches state at a certain point in time. + while(1) + { + uint32_t status = getMobicoreStatus(); + + if (MC_STATUS_INITIALIZED == status) + { + break; + } + else if (MC_STATUS_NOT_INITIALIZED == status) + { + // Switch to MobiCore to give it more CPU time. + if(!yield()) { + return false; + } + } + else if (MC_STATUS_HALT == status) + { + dumpMobicoreStatus(); + LOG_E("MobiCore halted during init !!!, state is 0x%x", status); + return false; + } + else // MC_STATUS_BAD_INIT or anything else + { + LOG_E("MCI buffer init failed, state is 0x%x", status); + return false; + } + } + } + + nqStartOut = (notificationQueue_t *) mciBuffer; + nqStartIn = (notificationQueue_t *) ((uint8_t *) nqStartOut + + sizeof(notificationQueueHeader_t) + NQ_NUM_ELEMS + * sizeof(notification_t)); + + // Set up the NWd NQ + nq = new NotificationQueue(nqStartIn, nqStartOut, NQ_NUM_ELEMS); + + mcpBuffer_t *mcpBuf = (mcpBuffer_t*) ((uint8_t *) mciBuffer + NQ_BUFFER_SIZE); + + // Set up the MC flags + mcFlags = &(mcpBuf->mcFlags); + + // Set up the MCP message + mcpMessage = &(mcpBuf->mcpMessage); + + // convert virtual address of mapping to physical address for the init. + LOG_I("MCP: virt=%p, phys=%p, reused=%s", + pWsmMcp->virtAddr, + pWsmMcp->physAddr, + mciReused ? "true" : "false"); + return true; +} + + +//------------------------------------------------------------------------------ +void TrustZoneDevice::initDeviceStep2( + void +) { + // not needed +} + + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::yield( + void +) { + int32_t ret = pMcKMod->fcYield(); + if (ret != 0) { + LOG_E("pMcKMod->fcYield() failed: %d", ret); + } + return ret == 0; +} + + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::nsiq( + void +) { + // There is no need to set the NON-IDLE flag here. Sending an N-SIQ will + // make the MobiCore run until it could set itself to a state where it + // set the flag itself. IRQs and FIQs are disbaled for this period, so + // there is no way the NWd can interrupt here. + + // not needed: mcFlags->schedule = MC_FLAG_SCHEDULE_NON_IDLE; + + int32_t ret = pMcKMod->fcNSIQ(); + if (ret != 0) { + LOG_E("pMcKMod->fcNSIQ() failed : %d", ret); + return false; + } + // now we have to wake the scheduler, so MobiCore gets CPU time. + schedSync.signal(); + return true; +} + + +//------------------------------------------------------------------------------ +void TrustZoneDevice::notify( + uint32_t sessionId +) { + do + { + // Check if it is MCP session - handle openSession() command + if (SID_MCP != sessionId) + { + // Check if session ID exists to avoid flooding of nq by clients + TrustletSession* ts = getTrustletSession(sessionId); + if (NULL == ts) + { + LOG_E("notify(): no session with id=%d", sessionId); + break; + } + } + + LOG_I("notify(): Send notification for id=%d", sessionId); + // Notify MobiCore about new data + + notification_t notification = { + // C++ does not support C99 designated initializers + /* .sessionId = */ sessionId, + /* .payload = */ 0 + }; + + nq->putNotification(¬ification); + //IMPROVEMENT-2012-03-07-maneaval What happens when/if nsiq fails? + //In the old days an exception would be thrown but it was uncertain + //where it was handled, some server(sock or Netlink). In that case + //the server would just die but never actually signaled to the client + //any error condition + nsiq(); + + } while(0); +} + +//------------------------------------------------------------------------------ +uint32_t TrustZoneDevice::getMobicoreStatus( + void +) { + uint32_t status; + //IMPROVEMENT-2012-03-07-maneaval Can fcInfo ever fail? Before it threw an + //exception but the handler depended on the context. + pMcKMod->fcInfo(0, &status, NULL); + + return status; +} + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::checkMciVersion( + void +) { + int ret; + uint32_t version = 0; + + ret = pMcKMod->fcInfo(MC_EXT_INFO_ID_MCI_VERSION, NULL, &version); + if (ret != 0) { + LOG_E("pMcKMod->fcInfo() failed with %d", ret); + return false; + } + + // Run-time check. + char* errmsg; + if (!checkVersionOkMCI(version, &errmsg)) { + LOG_E("%s", errmsg); + return false; + } + LOG_I("%s", errmsg); + return true; +} + +//------------------------------------------------------------------------------ +void TrustZoneDevice::dumpMobicoreStatus( + void +) { + int ret; + uint32_t status, info; + // read additional info about exception-point and print + LOG_E("MobiCore halted !!!"); + ret = pMcKMod->fcInfo(1, &status, &info); + LOG_W("MC_HALT: flags : 0x%8x", info); + ret = pMcKMod->fcInfo(2, &status, &info); + LOG_W("MC_HALT: haltCode : 0x%8x", info); + ret = pMcKMod->fcInfo(3, &status, &info); + LOG_W("MC_HALT: haltIp : 0x%8x", info); + ret = pMcKMod->fcInfo(4, &status, &info); + LOG_W("MC_HALT: faultRec.cnt : 0x%8x", info); + ret = pMcKMod->fcInfo(5, &status, &info); + LOG_W("MC_HALT: faultRec.cause : 0x%8x", info); + ret = pMcKMod->fcInfo(6, &status, &info); + LOG_W("MC_HALT: faultRec.meta : 0x%8x", info); + ret = pMcKMod->fcInfo(7, &status, &info); + LOG_W("MC_HALT: faultRec.thread : 0x%8x", info); + ret = pMcKMod->fcInfo(8, &status, &info); + LOG_W("MC_HALT: faultRec.ip : 0x%8x", info); + ret = pMcKMod->fcInfo(9, &status, &info); + LOG_W("MC_HALT: faultRec.sp : 0x%8x", info); + ret = pMcKMod->fcInfo(10, &status, &info); + LOG_W("MC_HALT: faultRec.arch.dfsr : 0x%8x", info); + ret = pMcKMod->fcInfo(11, &status, &info); + LOG_W("MC_HALT: faultRec.arch.adfsr : 0x%8x", info); + ret = pMcKMod->fcInfo(12, &status, &info); + LOG_W("MC_HALT: faultRec.arch.dfar : 0x%8x", info); + ret = pMcKMod->fcInfo(13, &status, &info); + LOG_W("MC_HALT: faultRec.arch.ifsr : 0x%8x", info); + ret = pMcKMod->fcInfo(14, &status, &info); + LOG_W("MC_HALT: faultRec.arch.aifsr : 0x%8x", info); + ret = pMcKMod->fcInfo(15, &status, &info); + LOG_W("MC_HALT: faultRec.arch.ifar : 0x%8x", info); + ret = pMcKMod->fcInfo(16, &status, &info); + LOG_W("MC_HALT: mcData.flags : 0x%8x", info); + ret = pMcKMod->fcInfo(19, &status, &info); + LOG_W("MC_HALT: mcExcep.partner : 0x%8x", info); + ret = pMcKMod->fcInfo(20, &status, &info); + LOG_W("MC_HALT: mcExcep.peer : 0x%8x", info); + ret = pMcKMod->fcInfo(21, &status, &info); + LOG_W("MC_HALT: mcExcep.message : 0x%8x", info); + ret = pMcKMod->fcInfo(22, &status, &info); + LOG_W("MC_HALT: mcExcep.data : 0x%8x", info); +} + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::waitSsiq( + void +) { + uint32_t cnt; + if (!pMcKMod->waitSSIQ(&cnt)) + { + LOG_E("pMcKMod->SSIQ() failed"); + return false; + } + LOG_I("SSIQ Received, COUNTER = %u", cnt); + return true; +} + + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::getMciInstance( + uint32_t len, + CWsm_ptr *mci, + bool *reused +) { + addr_t virtAddr; + uint32_t handle; + addr_t physAddr; + bool isMci = true; + if (0 == len) + { + LOG_E("allocateWsm() length is 0"); + return false; + } + + int ret = pMcKMod->mmap( + len, + &handle, + &virtAddr, + &physAddr, + &isMci); + if (0 != ret) + { + LOG_E("pMcKMod->mmap() failed: %d", ret); + return false; + } + *mci = new CWsm(virtAddr, len, handle, physAddr); + // isMci will be set to true if buffer has been reused + *reused = isMci; + return true; +} + + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::freeWsm( + CWsm_ptr pWsm +) { + + int ret = pMcKMod->free(pWsm->handle); + if (ret != 0) + { + LOG_E("pMcKMod->free() failed: %d", ret); + return false; + } + delete pWsm; + return true; +} + + +//------------------------------------------------------------------------------ +CWsm_ptr TrustZoneDevice::registerWsmL2( + addr_t buffer, + uint32_t len, + uint32_t pid +) { + addr_t physAddr; + uint32_t handle; + + int ret = pMcKMod->registerWsmL2( + buffer, + len, + pid, + &handle, + &physAddr); + if (ret != 0) + { + LOG_E("ipMcKMod->registerWsmL2() failed: %d", ret); + return NULL; + } + + return new CWsm(buffer,len,handle,physAddr); +} + + +//------------------------------------------------------------------------------ +CWsm_ptr TrustZoneDevice::allocateContiguousPersistentWsm( + uint32_t len +) { + CWsm_ptr pWsm = NULL; + do + { + if (0 == len) + { + break; + } + + // Allocate shared memory + addr_t virtAddr; + uint32_t handle; + addr_t physAddr; + int ret = pMcKMod->mapPersistent( + len, + &handle, + &virtAddr, + &physAddr); + if (0 != ret) + { + break; + } + + // Register (vaddr,paddr) with device + pWsm = new CWsm(virtAddr,len,handle,physAddr); + + } while(0); + + // Return pointer to the allocated memory + return pWsm; +} + + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::unregisterWsmL2( + CWsm_ptr pWsm +) { + int ret = pMcKMod->unregisterWsmL2(pWsm->handle); + if (ret != 0) { + LOG_E("pMcKMod->unregisterWsmL2 failed: %d", ret); + //IMPROVEMENT-2012-03-07 maneaval Make sure we don't leak objects + return false; + } + delete pWsm; + return true; +} + +// REV add unregister (used after OPEN_SESSION) + +//------------------------------------------------------------------------------ +bool TrustZoneDevice::schedulerAvailable( + void +){ + return schedulerEnabled; +} + +//------------------------------------------------------------------------------ +//TODO Schedulerthread to be switched off if MC is idle. Will be woken up when +// driver is called again. +void TrustZoneDevice::schedule( + void +) { + uint32_t timeslice = SCHEDULING_FREQ; + // loop forever + for (;;) + { + // Scheduling decision + if (MC_FLAG_SCHEDULE_IDLE == mcFlags->schedule) + { + // MobiCore is IDLE + + // Prevent unnecessary consumption of CPU cycles -> Wait until S-SIQ received + schedSync.wait(); + + } else { + // MobiCore is not IDLE (anymore) + + // Check timeslice + if (0 == timeslice) + { + // Slice expired, so force MC internal scheduling decision + timeslice = SCHEDULING_FREQ; + if(!nsiq()) { + break; + } + } else { + // Slice not used up, simply hand over control to the MC + timeslice--; + if(!yield()) { + break; + } + } + } + } +} +//------------------------------------------------------------------------------ +void TrustZoneDevice::handleIrq( + void + ) { + LOG_I("Starting NQ IRQ handler..."); + for (;;) + { + LOG_I("NQ empty now"); + if(!waitSsiq()) { + LOG_E("Waiting for SSIQ failed"); + break; + } + LOG_I("S-SIQ received"); + + // Save all the + for (;;) + { + notification_t *notification = nq->getNotification(); + if (NULL == notification) { + break; + } + LOG_I("Received notification, sessionId=%d, payload=%d", + notification->sessionId, notification->payload); + + // check if the notification belongs to the MCP session + if (notification->sessionId == SID_MCP) { + // Signal main thread of the driver to continue after MCP + // command has been processed by the MC + signalMcpNotification(); + } + else + { + // Get the NQ connection for the session ID + Connection *connection = getSessionConnection(notification->sessionId, notification); + if (connection == NULL) { + /* Couldn't find the session for this notifications + * In practice this only means one thing: there is + * a race condition between RTM and the Daemon and + * RTM won. But we shouldn't drop the notification + * right away we should just queue it in the device + */ + LOG_W("Notification for unknown session ID"); + queueUnknownNotification(*notification); + } + else + { + LOG_I("Write notification!"); + // Forward session ID and additional payload of + // notification to the TLC/Application layer + connection->writeData((void *)notification, + sizeof(notification_t)); + } + } + } + + // Wake up scheduler + schedSync.signal(); + } + LOG_E("S-SIQ exception"); + // Tell main thread that "something happened" + // MSH thread MUST not block! + DeviceIrqHandler::setExiting(); + signalMcpNotification(); +} +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.h b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.h new file mode 100644 index 0000000..58d0cbf --- /dev/null +++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.h @@ -0,0 +1,172 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * Class for TrustZone Devices. + * TrustZone device implements communication functions needed for + * accessing MobiCore located in an TrustZone environment. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 TRUSTZONEDEVICE_H_ +#define TRUSTZONEDEVICE_H_ + + +#include <stdint.h> + +#include "McTypes.h" + +#include "CSemaphore.h" +#include "CMcKMod.h" +#include "CWsm.h" + +#include "ExcDevice.h" +#include "MobiCoreDevice.h" + + +#define SCHEDULING_FREQ 5 /**< N-SIQ every n-th time */ + +class TrustZoneDevice : public MobiCoreDevice { + +protected: + bool schedulerEnabled; /**< NQ IRQ Scheduler enabling */ + CSemaphore schedSync; /**< Semaphore to synchronize S-SIQs with scheduler thread */ + CMcKMod_ptr pMcKMod; /**< kernel module */ + CWsm_ptr pWsmMcp; /**< WSM use for MCP */ + CWsm_ptr mobicoreInDDR; /**< WSM used for Mobicore binary */ + bool mciReused; + + /** Access functions to the MC Linux kernel module + */ + bool yield( + void + ); + + bool nsiq( + void + ); + + bool waitSsiq( + void + ); + +public: + + TrustZoneDevice( + void + ); + + virtual ~TrustZoneDevice( + void + ); + +// static MobiCoreDevice* getDeviceInstance( +// void +// ); + /** Set up MCI and wait till MC is initialized + * + * @param devFile the device node to speak to. + * @param loadMobiCore + * @param mobicoreImage + * @param enableScheduler + * + * @return true if mobicore is initialized + * @trows ExcDevice + */ + bool initDevice( + const char *devFile, + bool loadMobiCore, + const char *mobicoreImage, + bool enableScheduler + ); + + void initDeviceStep2( + void + ); + + void notify( + uint32_t sessionId + ); + + void dumpMobicoreStatus( + void + ); + + uint32_t getMobicoreStatus( + void + ); + + bool checkMciVersion( + void + ); + + /** Memory allocation functions + */ + // TODO xgal: move memory registration from TzDevice to Device class + bool getMciInstance( + uint32_t len, + CWsm_ptr *mci, + bool *reused + ); + + bool freeWsm( + CWsm_ptr pWsm + ); + + CWsm_ptr registerWsmL2( + addr_t buffer, + uint32_t len, + uint32_t pid + ); + + bool unregisterWsmL2( + CWsm_ptr pWsm + ); + + /** + * Allocates persistent WSM memory for TL (won't be fried when TLC exits). + */ + CWsm_ptr allocateContiguousPersistentWsm( + uint32_t len + ); + + bool schedulerAvailable( + void + ); + + void schedule( + void + ); + + void handleIrq( + void + ); +}; + +#endif /* TRUSTZONEDEVICE_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/TrustletSession.cpp b/mobicore/daemon/Daemon/Device/TrustletSession.cpp new file mode 100644 index 0000000..c0dfe4e --- /dev/null +++ b/mobicore/daemon/Daemon/Device/TrustletSession.cpp @@ -0,0 +1,83 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "TrustletSession.h" +#include <cstdlib> + +#define LOG_TAG "McDaemon" +#include "log.h" + + +//------------------------------------------------------------------------------ +TrustletSession::TrustletSession( + Connection *deviceConnection, + uint32_t sessionId +) { + this->deviceConnection = deviceConnection; + this->notificationConnection = NULL; + this->sessionId = sessionId; + sessionMagic = rand(); +} + + +//------------------------------------------------------------------------------ +TrustletSession::~TrustletSession( + void +) { + delete notificationConnection; +} + +//------------------------------------------------------------------------------ +void TrustletSession::queueNotification( + notification_t *notification +) { + notifications.push(*notification); +} + +//------------------------------------------------------------------------------ +void TrustletSession::processQueuedNotifications( + void +) { + // Nothing to do here! + if(notificationConnection == NULL) + return; + + while (!notifications.empty()) + { + // Forward session ID and additional payload of + // notification to the just established connection + notificationConnection->writeData((void *)¬ifications.front(), + sizeof(notification_t)); + notifications.pop(); + } +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/TrustletSession.h b/mobicore/daemon/Daemon/Device/TrustletSession.h new file mode 100644 index 0000000..026f78b --- /dev/null +++ b/mobicore/daemon/Daemon/Device/TrustletSession.h @@ -0,0 +1,74 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 TRUSTLETSESSION_H_ +#define TRUSTLETSESSION_H_ + +#include "NotificationQueue.h" + +#include "Connection.h" +#include <queue> + + +class TrustletSession { + +public: + + TrustletSession( + Connection *deviceConnection, + uint32_t sessionId + ); + + ~TrustletSession( + void + ); + + void queueNotification( + notification_t *notification + ); + + void processQueuedNotifications( + void + ); + + uint32_t sessionId; + uint32_t sessionMagic; // Random data + Connection *deviceConnection; + Connection *notificationConnection; +private: + std::queue<notification_t> notifications; +}; + +typedef std::list<TrustletSession*> trustletSessionList_t; +typedef trustletSessionList_t::iterator trustletSessionIterator_t; + +#endif /* TRUSTLETSESSION_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/public/ExcDevice.h b/mobicore/daemon/Daemon/Device/public/ExcDevice.h new file mode 100644 index 0000000..cb55352 --- /dev/null +++ b/mobicore/daemon/Daemon/Device/public/ExcDevice.h @@ -0,0 +1,68 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * Device exceptions. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 EXCDEVICE_H_ +#define EXCDEVICE_H_ + +#include <stdint.h> +#include <exception> +#include <cstdio> +#include <cstdlib> + +#define ERROR_MCI_VERSION_MISMATCH ((int)(-2)) +#define ERROR_KMOD_VERSION_MISMATCH ((int)(-3)) + +class ExcDevice: public std::exception { + +public: + + ExcDevice(const char *description, int cause) : + cause(cause), description(description) { + } + + virtual int getCause() const throw () { + return cause; + } + + virtual const char *getDescription() const throw () { + return description; + } + +private: + + int cause; + const char *description; +}; + +#endif /* EXCDEVICE_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Device/public/MobiCoreDevice.h b/mobicore/daemon/Daemon/Device/public/MobiCoreDevice.h new file mode 100644 index 0000000..1ac2dda --- /dev/null +++ b/mobicore/daemon/Daemon/Device/public/MobiCoreDevice.h @@ -0,0 +1,259 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_DEV + * @{ + * @file + * + * MobiCore device. + * The MobiCore device class handles the MCP processing within the driver. + * Concrete devices implementing the communication behavior for the platforms have to be derived + * from this. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MOBICOREDEVICE_H_ +#define MOBICOREDEVICE_H_ + +#include <stdint.h> +#include <vector> + +#include "McTypes.h" + +#include "Mci/mcimcp.h" +#include "mcLoadFormat.h" +#include "MobiCoreDriverCmd.h" + +#include "Connection.h" +#include "CWsm.h" + +#include "ExcDevice.h" +#include "DeviceScheduler.h" +#include "DeviceIrqHandler.h" +#include "NotificationQueue.h" +#include "TrustletSession.h" +#include "mcVersionInfo.h" + + +class MobiCoreDevice; + +typedef struct { + addr_t baseAddr; /**< Physical address of the data to load. */ + uint32_t offs; /**< Offset to the data. */ + uint32_t len; /**< Length of the data to load. */ + mclfHeader_ptr tlHeader; /**< Pointer to trustlet header. */ +} loadDataOpenSession_t, *loadDataOpenSession_ptr; + +/** + * Factory method to return the platform specific MobiCore device. + * Implemented in the platform specific *Device.cpp + */ +extern MobiCoreDevice* getDeviceInstance(void); + +class MobiCoreDevice : public DeviceScheduler, public DeviceIrqHandler { + +protected: + + NotificationQueue *nq; /**< Pointer to the notification queue within the MCI buffer */ + mcFlags_t *mcFlags; /**< Pointer to the MC flags within the MCI buffer */ + mcpMessage_t *mcpMessage; /**< Pointer to the MCP message structure within the MCI buffer */ + CSemaphore mcpSessionNotification; /**< Semaphore to synchronize incoming notifications for the MCP session */ + + trustletSessionList_t trustletSessions; /**< Available Trustlet Sessions */ + mcVersionInfo_t *mcVersionInfo; /**< MobiCore version info. */ + bool mcFault; /**< Signal RTM fault */ + + /* In a special case a trustlet can create a race condition in the daemon. + * If at trustlet start it detects an error of some sort and calls the + * exit function before waiting for any notifications from NWD then the daemon + * will receive the openSession notification from RTM and the error notification + * from the trustlet at the same time but because the internal objects in + * the daemon are not yet completely setup then the error notification will + * never be sent to the TLC! + * + * This queue holds notifications received between the time the daemon + * puts the MCP command for open session until the internal session objects + * are setup corectly. + */ + std::queue<notification_t> notifications; /**< Notifications queue for open session notification */ + + MobiCoreDevice(); + + void signalMcpNotification( + void + ); + + bool waitMcpNotification( + void + ); + +private: + + virtual bool yield( + void + ) =0; + + virtual bool nsiq( + void + ) =0; + + virtual bool waitSsiq( + void + ) =0; + +public: + + virtual ~MobiCoreDevice(); + + TrustletSession* getTrustletSession( + uint32_t sessionId + ); + + Connection* getSessionConnection( + uint32_t sessionId, + notification_t *notification + ); + + bool open( + Connection *connection); + + void close( + Connection *connection); + + void openSession( + Connection *deviceConnection, + loadDataOpenSession_ptr pLoadDataOpenSession, + mcDrvCmdOpenSessionPayload_ptr pCmdOpenSessionPayload, + mcDrvRspOpenSessionPayload_ptr pRspOpenSessionPayload); + + TrustletSession *registerTrustletConnection( + Connection *connection, + mcDrvCmdNqConnectPayload_ptr pCmdNqConnectPayload); + + bool closeSession( + Connection *deviceConnection, + uint32_t sessionId); + + virtual void notify( + uint32_t sessionId + ) = 0; + + void mapBulk( + Connection *deviceConnection, + mcDrvCmdMapBulkMemPayload_ptr pCmdMapBulkMemPayload, + mcDrvRspMapBulkMemPayload_ptr pRspMapBulkMemPayload); + + void unmapBulk( + Connection *deviceConnection, + mcDrvCmdUnmapBulkMemPayload_ptr pCmdUnmapBulkMemPayload, + mcDrvRspUnmapBulkMemPayload_ptr pRspUnmapBulkMemPayload); + + void start(); + + void donateRam( + const uint32_t donationSize + ); + + void getMobiCoreVersion( + mcDrvRspGetMobiCoreVersionPayload_ptr pRspGetMobiCoreVersionPayload + ); + + bool getMcFault() { return mcFault; } + + void queueUnknownNotification( + notification_t notification + ); + + virtual void dumpMobicoreStatus( + void + ) = 0; + + virtual uint32_t getMobicoreStatus( + void + ) = 0; + + virtual bool schedulerAvailable( + void + ) = 0; + + virtual void schedule( + void + ) = 0; + + virtual void handleIrq( + void + ) = 0; + + virtual bool freeWsm( + CWsm_ptr pWsm + ) = 0; + + /** + * Initialize MobiCore. + * + * @param devFile the device node to speak to. + * @param loadMobiCore + * @param mobicoreImage + * @param enableScheduler + * + * @returns true if MobiCore is already initialized. + * */ + virtual bool initDevice( + const char *devFile, + bool loadMobiCore, + const char *mobicoreImage, + bool enableScheduler + ) = 0; + + virtual void initDeviceStep2( + void + ) = 0; + + virtual bool getMciInstance( + uint32_t len, + CWsm_ptr *mci, + bool *reused + ) = 0; + + virtual CWsm_ptr registerWsmL2( + addr_t buffer, + uint32_t len, + uint32_t pid + ) = 0; + + virtual bool unregisterWsmL2( + CWsm_ptr pWsm + ) = 0; + + /** + * Allocates persistent WSM memory for TL (won't be released when TLC exits). + */ + virtual CWsm_ptr allocateContiguousPersistentWsm( + uint32_t len + ) = 0; +}; + +#endif /* MOBICOREDEVICE_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/MobiCoreDriverDaemon.cpp b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.cpp new file mode 100644 index 0000000..bde00f3 --- /dev/null +++ b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.cpp @@ -0,0 +1,1110 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_CONHDLR + * @{ + * @file + * + * Entry of the MobiCore Driver. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <cstdlib> +#include <signal.h> +#include <fcntl.h> +#include <fstream> +#include <cassert> + +#include "MobiCoreDriverCmd.h" +#include "mcVersion.h" +#include "mcVersionHelper.h" +#include "mc_drv_module_api.h" + +#include "MobiCoreDriverDaemon.h" +#include "MobiCoreRegistry.h" +#include "MobiCoreDevice.h" + +#include "NetlinkServer.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + +#define DRIVER_TCI_LEN 100 + +#include "Mci/mci.h" + +MC_CHECK_VERSION(MCI, 0, 2); +MC_CHECK_VERSION(SO, 2, 0); +MC_CHECK_VERSION(MCLF, 2, 0); +MC_CHECK_VERSION(CONTAINER, 2, 0); + +static void checkMobiCoreVersion(MobiCoreDevice* mobiCoreDevice); + +//------------------------------------------------------------------------------ +MobiCoreDriverDaemon::MobiCoreDriverDaemon( + bool enableScheduler, + bool loadMobicore, + std::string mobicoreImage, + unsigned int donateRamSize, + bool loadDriver, + std::string driverPath +) { + mobiCoreDevice = NULL; + + this->enableScheduler = enableScheduler; + this->loadMobicore = loadMobicore; + this->mobicoreImage = mobicoreImage; + this->donateRamSize = donateRamSize; + this->loadDriver = loadDriver; + this->driverPath = driverPath; + + for (int i = 0; i < MAX_SERVERS; i++) { + servers[i] = NULL; + } +} + +//------------------------------------------------------------------------------ +MobiCoreDriverDaemon::~MobiCoreDriverDaemon( + void +) { + // Unload any device drivers might have been loaded + driverResourcesList_t::iterator it; + for(it = driverResources.begin(); it != driverResources.end(); it++) { + MobicoreDriverResources *res = *it; + mobiCoreDevice->closeSession(res->conn, res->sessionId); + mobiCoreDevice->unregisterWsmL2(res->pTciWsm); + } + delete mobiCoreDevice; + for (int i = 0; i < MAX_SERVERS; i++) { + delete servers[i]; + servers[i] = NULL; + } +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::run( + void +) { + LOG_I("Daemon starting up..."); + LOG_I("Socket interface version is %u.%u", DAEMON_VERSION_MAJOR, DAEMON_VERSION_MINOR); +#ifdef MOBICORE_COMPONENT_BUILD_TAG + LOG_I("%s", MOBICORE_COMPONENT_BUILD_TAG); +#else + #warning "MOBICORE_COMPONENT_BUILD_TAG is not defined!" +#endif + LOG_I("Build timestamp is %s %s", __DATE__, __TIME__); + + int i; + + mobiCoreDevice = getDeviceInstance(); + + LOG_I("Daemon scheduler is %s", enableScheduler? "enabled" : "disabled"); + if(!mobiCoreDevice->initDevice( + MC_DRV_MOD_DEVNODE_FULLPATH, + loadMobicore, + mobicoreImage.c_str(), + enableScheduler)) { + LOG_E("%s: Failed to initialize MobiCore!", __FUNCTION__); + return; + } + mobiCoreDevice->start(); + + checkMobiCoreVersion(mobiCoreDevice); + + if (donateRamSize > 0) { + // Donate additional RAM to MC + LOG_I("Donating %u Kbytes to Mobicore", donateRamSize / 1024); + mobiCoreDevice->donateRam(donateRamSize); + } + + // Load device driver if requested + if (loadDriver) { + loadDeviceDriver(driverPath); + } + + LOG_I("Servers will be created!"); + // Start listening for incoming TLC connections + servers[0] = new NetlinkServer(this); + servers[1] = new Server(this, SOCK_PATH); + LOG_I("Servers created!"); + + // Start all the servers + for (i = 0; i < MAX_SERVERS; i++) { + servers[i]->start(); + } + + // then wait for them to exit + for (i = 0; i < MAX_SERVERS; i++) { + servers[i]->join(); + } +} + + +//------------------------------------------------------------------------------ +MobiCoreDevice *MobiCoreDriverDaemon::getDevice( + uint32_t deviceId +) { + // Always return the trustZoneDevice as it is currently the only one supported + if(MC_DEVICE_ID_DEFAULT != deviceId) + return NULL; + return mobiCoreDevice; +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::dropConnection( + Connection *connection +) { + // Check if a Device has already been registered with the connection + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + + if (device != NULL) { + LOG_I("dropConnection(): closing still open device."); + // A connection has been found and has to be closed + device->close(connection); + } +} + + +//------------------------------------------------------------------------------ +size_t MobiCoreDriverDaemon::writeResult( + Connection *connection, + mcDrvRsp_t code +) { + if (0 != code) { + LOG_E("writeResult(): set error code %d",code); + } + return connection->writeData(&code, sizeof(mcDrvRsp_t)); +} + +//------------------------------------------------------------------------------ +bool MobiCoreDriverDaemon::loadDeviceDriver( + std::string driverPath +) { + bool ret = false; + CWsm_ptr pWsm = NULL, pTciWsm = NULL; + regObject_t *regObj = NULL; + Connection *conn = NULL; + uint8_t *tci = NULL; + mcDrvRspOpenSession_t rspOpenSession; + + do + { + //mobiCoreDevice + ifstream fs(driverPath.c_str(), ios_base::binary); + if (!fs) { + LOG_E("%s: failed: cannot open %s", __func__, driverPath.c_str()); + break; + } + + LOG_I("%s: loading %s", __func__, driverPath.c_str()); + + regObj = mcRegistryGetDriverBlob(driverPath.c_str()); + if (regObj == NULL) { + break;; + } + + LOG_I("registering L2 in kmod, p=%p, len=%i", + regObj->value, regObj->len); + + // Prepare the interface structure for memory registration, then + // register virtual memory in kernel module, create L2 table + // TODO xgal: refactor naming of datatypes and WSM handling + pWsm = mobiCoreDevice->registerWsmL2( + (addr_t)(regObj->value), regObj->len, 0); + if (pWsm == NULL) + { + LOG_E("allocating WSM for Trustlet failed"); + break; + } + // Initialize information data of open session command + loadDataOpenSession_t loadDataOpenSession; + loadDataOpenSession.baseAddr = pWsm->physAddr; + loadDataOpenSession.offs = ((uint32_t) regObj->value) & 0xFFF; + loadDataOpenSession.len = regObj->len; + loadDataOpenSession.tlHeader = (mclfHeader_ptr) regObj->value; + + mcDrvCmdOpenSessionPayload_t openSessionPayload; + tci = (uint8_t*)malloc(DRIVER_TCI_LEN); + pTciWsm = mobiCoreDevice->registerWsmL2( + (addr_t)tci, DRIVER_TCI_LEN, 0); + if (pTciWsm == NULL) + { + LOG_E("allocating WSM TCI for Trustlet failed"); + break; + } + openSessionPayload.deviceId = MC_DEVICE_ID_DEFAULT; + openSessionPayload.tci = (uint32_t)pTciWsm->physAddr; + openSessionPayload.len = DRIVER_TCI_LEN; + + conn = new Connection(); + mobiCoreDevice->openSession( + conn, + &loadDataOpenSession, + &openSessionPayload, + &(rspOpenSession.payload)); + + // Unregister physical memory from kernel module. + // This will also destroy the WSM object. + mobiCoreDevice->unregisterWsmL2(pWsm); + pWsm = NULL; + + // Free memory occupied by Trustlet data + free(regObj); + regObj = NULL; + + if (rspOpenSession.payload.mcResult != MC_MCP_RET_OK) + { + LOG_E("%s: rspOpenSession mcResult %d", __func__, + rspOpenSession.payload.mcResult); + break; + } + + ret = true; + } while (false); + // Free all allocated resources + if (ret == false) { + LOG_I("%s: Freeing previously allocated resources!", __func__); + if (pWsm != NULL) { + if(!mobiCoreDevice->unregisterWsmL2(pWsm)) { + // At least make sure we don't leak the WSM object + delete pWsm; + } + } + // No matter if we free NULL objects + free(regObj); + + if (conn != NULL) { + delete conn; + } + } else if (conn != NULL) { + driverResources.push_back(new MobicoreDriverResources( + conn, tci, pTciWsm, rspOpenSession.payload.sessionId)); + } + + return ret; +} + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processOpenDevice( + Connection *connection +) { + do + { + // Read entire command data + mcDrvCmdOpenDevicePayload_t cmdOpenDevicePayload; + uint32_t rlen = connection->readData( + &(cmdOpenDevicePayload), + sizeof(cmdOpenDevicePayload)); + if (rlen != sizeof(cmdOpenDevicePayload)) + { + LOG_E("processOpenDevice(): OpenSession length error: %d", rlen); + writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // Check if device has been registered to the connection + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL != device) + { + LOG_E("processOpenDevice(): device already set"); + writeResult(connection, MC_DRV_RSP_DEVICE_ALREADY_OPENED); + break; + } + + LOG_I("processOpenDevice(): deviceId is %d", + cmdOpenDevicePayload.deviceId); + + // Get device for device ID + device = getDevice(cmdOpenDevicePayload.deviceId); + + // Check if a device for the given name has been found + if (NULL == device) + { + LOG_E("invalid deviceId"); + writeResult(connection, MC_DRV_INVALID_DEVICE_NAME); + break; + } + + // Register device object with connection + if (false == device->open(connection)) + { + LOG_E("processOpenDevice(): device->open() failed"); + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + + // Return result code to client lib (no payload) + writeResult(connection, MC_DRV_RSP_OK); + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processCloseDevice( + Connection *connection +) { + do + { + // there is no payload to read + + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) + { + LOG_E("processCloseDevice(): no device"); + writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED); + break; + } + + // No command data will be read + // Unregister device object with connection + device->close(connection); + + // there is no payload + writeResult(connection, MC_DRV_RSP_OK); + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processOpenSession( + Connection *connection +) { + do + { + // Read entire command data + mcDrvCmdOpenSessionPayload_t cmdOpenSessionPayload; + uint32_t rlen = connection->readData( + &cmdOpenSessionPayload, + sizeof(cmdOpenSessionPayload)); + if (rlen != sizeof(cmdOpenSessionPayload)) + { + LOG_E("processOpenSession(): OpenSession length error: %d", rlen); + writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) + { + writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED); + break; + } + + // Get service blob from registry + regObject_t *regObj = mcRegistryGetServiceBlob( + (mcUuid_t*) &(cmdOpenSessionPayload.uuid)); + + // Call preinstalled variant of method + mcDrvRspOpenSession_t rspOpenSession; + if (NULL == regObj) + { + writeResult(connection, MC_DRV_RSP_TRUSTLET_NOT_FOUND); + break; + } + if (0 == regObj->len) + { + free(regObj); + writeResult(connection, MC_DRV_RSP_TRUSTLET_NOT_FOUND); + break; + } + else + { + // Trustlet retrieved from registry + + LOG_I("registering L2 in kmod, p=%p, len=%i", + regObj->value, + regObj->len); + + // Prepare the interface structure for memory registration, then + // register virtual memory in kernel module, create L2 table + // TODO xgal: refactor naming of datatypes and WSM handling + CWsm_ptr pWsm = device->registerWsmL2( + (addr_t)(regObj->value), + regObj->len, + 0); + if (NULL == pWsm) + { + LOG_E("allocating WSM for Trustlet failed"); + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + // Initialize information data of open session command + loadDataOpenSession_t loadDataOpenSession; + loadDataOpenSession.baseAddr = pWsm->physAddr; + loadDataOpenSession.offs = ((uint32_t) regObj->value) & 0xFFF; + loadDataOpenSession.len = regObj->len; + loadDataOpenSession.tlHeader = (mclfHeader_ptr) regObj->value; + + device->openSession( + connection, + &loadDataOpenSession, + &cmdOpenSessionPayload, + &(rspOpenSession.payload)); + + // Unregister physical memory from kernel module. + // This will also destroy the WSM object. + if(!device->unregisterWsmL2(pWsm)) { + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + + // Free memory occupied by Trustlet data + free(regObj); + } + + uint32_t mcResult = rspOpenSession.payload.mcResult; + + mcDrvRsp_t responseId = MC_DRV_RSP_FAILED; + + switch (mcResult) + { + case MC_MCP_RET_OK: + responseId = MC_DRV_RSP_OK; + break; + case MC_MCP_RET_ERR_WRONG_PUBLIC_KEY: + responseId = MC_DRV_RSP_WRONG_PUBLIC_KEY; + break; + case MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH: + responseId = MC_DRV_RSP_CONTAINER_TYPE_MISMATCH; + break; + case MC_MCP_RET_ERR_CONTAINER_LOCKED: + responseId = MC_DRV_RSP_CONTAINER_LOCKED; + break; + case MC_MCP_RET_ERR_SP_NO_CHILD: + responseId = MC_DRV_RSP_SP_NO_CHILD; + break; + case MC_MCP_RET_ERR_TL_NO_CHILD: + responseId = MC_DRV_RSP_TL_NO_CHILD; + break; + case MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED: + responseId = MC_DRV_RSP_UNWRAP_ROOT_FAILED; + break; + case MC_MCP_RET_ERR_UNWRAP_SP_FAILED: + responseId = MC_DRV_RSP_UNWRAP_SP_FAILED; + break; + case MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED: + responseId = MC_DRV_RSP_UNWRAP_TRUSTLET_FAILED; + break; + } + + if (MC_MCP_RET_OK != mcResult) + { + LOG_E("rspOpenSession mcResult %d", mcResult); + writeResult(connection, responseId); + break; + } + + rspOpenSession.header.responseId = responseId; + connection->writeData( + &rspOpenSession, + sizeof(rspOpenSession)); + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processCloseSession( + Connection *connection +) { + do + { + // Read entire command data + mcDrvCmdCloseSessionPayload_t cmdCloseSessionPayload; + uint32_t rlen = connection->readData( + &cmdCloseSessionPayload, + sizeof(cmdCloseSessionPayload)); + if (rlen != sizeof(cmdCloseSessionPayload)) + { + LOG_E("processCloseSession(): CloseSessionPayload length error: %d",rlen); + writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) + { + LOG_E("processCloseSession(): device is NULL"); + writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED); + break; + } + + device->closeSession( + connection, + cmdCloseSessionPayload.sessionId); + + // there is no payload + writeResult(connection, MC_DRV_RSP_OK); + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processNqConnect( + Connection *connection +) { + do + { + // Set up the channel for sending SWd notifications to the client + // MC_DRV_CMD_NQ_CONNECT is only allowed on new connections not + // associated with a device. If a device is registered to the + // connection NQ_CONNECT is not allowed. + + // Read entire command data + mcDrvCmdNqConnectPayload_t cmdNqConnectPayload; + size_t rlen = connection->readData( + &(cmdNqConnectPayload), + sizeof(cmdNqConnectPayload)); + if (rlen != sizeof(cmdNqConnectPayload)) + { + LOG_E("processNqConnect(): NqConnect length error: %d",rlen); + writeResult(connection,MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // device must be empty + MobiCoreDevice *device = (MobiCoreDevice *)(connection->connectionData); + if (NULL != device) + { + LOG_E("processNqConnect(): device already set\n"); + writeResult(connection,MC_DRV_RSP_COMMAND_NOT_ALLOWED); + break; + } + + // Remove the connection from the list of known client connections + for (int i = 0; i < MAX_SERVERS; i++) { + servers[i]->detachConnection(connection); + } + + device = getDevice(cmdNqConnectPayload.deviceId); + if (NULL == device) + { + //TODO xgal: how about ...NO_SUCH_DEVICE + LOG_E("processNqConnect(): no device found\n"); + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + + TrustletSession* ts = device->registerTrustletConnection( + connection, + &cmdNqConnectPayload); + if (!ts) { + LOG_E("processNqConnect(): registerTrustletConnection() failed!"); + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + + writeResult(connection, MC_DRV_RSP_OK); + ts->processQueuedNotifications(); + + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processNotify( + Connection *connection +) { + do + { + // Read entire command data + mcDrvCmdNotifyPayload_t cmdNotifyPayload; + uint32_t rlen = connection->readData( + &cmdNotifyPayload, + sizeof(cmdNotifyPayload)); + if (sizeof(cmdNotifyPayload) != rlen) + { + LOG_E("processNotify(): NotifyPayload length error: %d", rlen); + // NOTE: notify fails silently + // writeResult(connection,MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) + { + LOG_E("processNotify(): device is NULL"); + // NOTE: notify fails silently + // writeResult(connection,MC_DRV_RSP_DEVICE_NOT_OPENED); + break; + } + + // REV axh: we cannot trust the clientLib to give us a valid + // sessionId here. Thus we have to check that it belongs to + // the clientLib's process. + + device->notify(cmdNotifyPayload.sessionId); + // NOTE: for notifications there is no response at all + } while(0); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processMapBulkBuf( + Connection *connection +) { + do + { + // Read entire command data + mcDrvCmdMapBulkMemPayload_t cmdMapBulkMemPayload; + uint32_t rlen = connection->readData( + &cmdMapBulkMemPayload, + sizeof(cmdMapBulkMemPayload)); + if (rlen != sizeof(cmdMapBulkMemPayload)) + { + LOG_E("processMapBulkBuf(): MapBulkMemPayload length error: %d", rlen); + writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) + { + LOG_E("processMapBulkBuf(): device is NULL"); + writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED); + break; + } + + // Map bulk memory to secure world + mcDrvRspMapBulkMem_t rspMapBulk; + device->mapBulk( + connection, + &cmdMapBulkMemPayload, + &(rspMapBulk.payload)); + + uint32_t mcResult = rspMapBulk.payload.mcResult; + if (MC_MCP_RET_OK != mcResult) + { + LOG_E("processMapBulkBuf(): rspMapBulk.mcResult=%d", mcResult); + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + + rspMapBulk.header.responseId = MC_DRV_RSP_OK; + connection->writeData(&rspMapBulk, sizeof(rspMapBulk)); + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processUnmapBulkBuf( + Connection *connection +) { + do + { + // Read entire command data + mcDrvCmdUnmapBulkMemPayload_t cmdUnmapBulkMemPayload; + uint32_t rlen = connection->readData( + &cmdUnmapBulkMemPayload, + sizeof(cmdUnmapBulkMemPayload)); + if (rlen != sizeof(cmdUnmapBulkMemPayload)) + { + LOG_E("processMapBulkBuf(): UnmapBulkMem length error: %d", rlen); + writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR); + break; + } + + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) + { + writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED); + break; + } + + // Unmap bulk memory from secure world + mcDrvRspUnmapBulkMem_t rspUnmpaBulk; + + device->unmapBulk( + connection, + &cmdUnmapBulkMemPayload, + &(rspUnmpaBulk.payload)); + + uint32_t mcResult = rspUnmpaBulk.payload.mcResult; + if (MC_MCP_RET_OK != mcResult) + { + LOG_E("processUnmapBulkBuf(): rspUnmpaBulk mcResult %d", mcResult); + writeResult(connection, MC_DRV_RSP_FAILED); + break; + } + + rspUnmpaBulk.header.responseId = MC_DRV_RSP_OK; + connection->writeData( + &rspUnmpaBulk, + sizeof(rspUnmpaBulk)); + + } while (false); +} + + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processGetVersion( + Connection *connection +) { + mcDrvRspGetVersion_t rspGetVersion; + rspGetVersion.payload.version = MC_MAKE_VERSION(DAEMON_VERSION_MAJOR, DAEMON_VERSION_MINOR); + + rspGetVersion.header.responseId = MC_DRV_RSP_OK; + connection->writeData( + &rspGetVersion, + sizeof(rspGetVersion)); +} + +//------------------------------------------------------------------------------ +void MobiCoreDriverDaemon::processGetMobiCoreVersion( + Connection *connection +) { + // Device required + MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData); + if (NULL == device) { + writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED); + return; + } + + // Get MobiCore version info from secure world. + mcDrvRspGetMobiCoreVersion_t rspGetMobiCoreVersion; + + device->getMobiCoreVersion( + &rspGetMobiCoreVersion.payload); + + uint32_t mcResult = rspGetMobiCoreVersion.payload.mcResult; + if (MC_MCP_RET_OK != mcResult) { + LOG_E("processGetMobiCoreVersion(): rspGetMobiCoreVersion mcResult %d", mcResult); + writeResult(connection, MC_DRV_RSP_FAILED); + return; + } + + rspGetMobiCoreVersion.header.responseId = MC_DRV_RSP_OK; + connection->writeData( + &rspGetMobiCoreVersion, + sizeof(rspGetMobiCoreVersion)); +} + + +//------------------------------------------------------------------------------ +bool MobiCoreDriverDaemon::handleConnection( + Connection *connection +) { + bool ret = false; + static CMutex mutex; + + /* In case of RTM fault do not try to signal anything to MobiCore + * just answer NO to all incoming connections! */ + if (mobiCoreDevice->getMcFault()) { + return false; + } + + mutex.lock(); + do + { + // Read header + mcDrvCommandHeader_t mcDrvCommandHeader; + uint32_t rlen = connection->readData( + &(mcDrvCommandHeader), + sizeof(mcDrvCommandHeader)); + + if (0 == rlen) + { + LOG_I("handleConnection(): Connection closed."); + break; + } + if (sizeof(mcDrvCommandHeader) != rlen) + { + LOG_E("handleConnection(): Header length error: %d", rlen); + break; + } + ret = true; + + switch (mcDrvCommandHeader.commandId) + { + //----------------------------------------- + case MC_DRV_CMD_OPEN_DEVICE: + processOpenDevice(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_CLOSE_DEVICE: + processCloseDevice(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_OPEN_SESSION: + processOpenSession(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_CLOSE_SESSION: + processCloseSession(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_NQ_CONNECT: + processNqConnect(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_NOTIFY: + processNotify(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_MAP_BULK_BUF: + processMapBulkBuf(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_UNMAP_BULK_BUF: + processUnmapBulkBuf(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_GET_VERSION: + processGetVersion(connection); + break; + //----------------------------------------- + case MC_DRV_CMD_GET_MOBICORE_VERSION: + processGetMobiCoreVersion(connection); + break; + //----------------------------------------- + + default: + LOG_E("handleConnection(): unknown command: %d=0x%x", + mcDrvCommandHeader.commandId, + mcDrvCommandHeader.commandId); + ret = false; + break; + } + } while(0); + mutex.unlock(); + + return ret; +} + +//------------------------------------------------------------------------------ +/** + * Print daemon command line options + */ + +void printUsage( + int argc, + char *args[] +) { + fprintf(stderr, "usage: %s [-mdsbh]\n", args[0]); + fprintf(stderr, "Start MobiCore Daemon\n\n"); + fprintf(stderr, "-h\t\tshow this help\n"); + fprintf(stderr, "-b\t\tfork to background\n"); + fprintf(stderr, "-m IMAGE\tload mobicore from IMAGE to DDR\n"); + fprintf(stderr, "-s\t\tdisable daemon scheduler(default enabled)\n"); + fprintf(stderr, "-d SIZE\t\tdonate SIZE bytes to mobicore(disabled on most platforms)\n"); + fprintf(stderr, "-r DRIVER\t\tMobiCore driver to load at start-up\n"); +} + +//------------------------------------------------------------------------------ +/** + * Signal handler for daemon termination + * Using this handler instead of the standard libc one ensures the daemon + * can cleanup everything -> read() on a FD will now return EINTR + */ +void terminateDaemon( + int signum +) { + LOG_E("Signal %d received\n", signum); +} + +//------------------------------------------------------------------------------ +/** + * Main entry of the MobiCore Driver Daemon. + */ +int main( + int argc, + char *args[] +) { + // Create the MobiCore Driver Singleton + MobiCoreDriverDaemon *mobiCoreDriverDaemon = NULL; + // Process signal action + struct sigaction action; + + // Read the Command line options + extern char *optarg; + extern int optopt; + int c, errFlag = 0; + // Scheduler enabled by default + int schedulerFlag = 1; + // Mobicore loading disable by default + int mobicoreFlag = 0; + // Autoload driver at start-up + int driverLoadFlag = 0; + std::string mobicoreImage, driverPath; + // Ram donation disabled by default + int donationSize = 0; + // By default don't fork + bool forkDaemon = false; + while ((c = getopt(argc, args, "m:d:r:sbh")) != -1) { + switch(c) { + case 'h': /* Help */ + errFlag++; + break; + case 's': /* Disable Scheduler */ + schedulerFlag = 0; + break; + case 'd': /* Ram Donation size */ + donationSize = atoi(optarg); + break; + case 'm': /* Load mobicore image */ + mobicoreFlag = 1; + mobicoreImage = optarg; + break; + case 'b': /* Fork to background */ + forkDaemon = true; + break; + case 'r': /* Load mobicore driver at start-up */ + driverLoadFlag = 1; + driverPath = optarg; + break; + case ':': /* -d or -m without operand */ + fprintf(stderr, "Option -%c requires an operand\n", optopt); + errFlag++; + break; + case '?': + fprintf(stderr, + "Unrecognized option: -%c\n", optopt); + errFlag++; + } + } + if (errFlag) { + printUsage(argc, args); + exit(2); + } + + // We should fork the daemon to background + if (forkDaemon == true) { + int i = fork(); + if (i < 0) { + exit(1); + } + // Parent + else if (i > 0) { + exit(0); + } + + // obtain a new process group */ + setsid(); + /* close all descriptors */ + for (i = getdtablesize();i >= 0; --i) { + close(i); + } + // STDIN, STDOUT and STDERR should all point to /dev/null */ + i = open("/dev/null",O_RDWR); + dup(i); + dup(i); + /* ignore tty signals */ + signal(SIGTSTP,SIG_IGN); + signal(SIGTTOU,SIG_IGN); + signal(SIGTTIN,SIG_IGN); + } + + // Set up the structure to specify the new action. + action.sa_handler = terminateDaemon; + sigemptyset (&action.sa_mask); + action.sa_flags = 0; + sigaction (SIGINT, &action, NULL); + sigaction (SIGHUP, &action, NULL); + sigaction (SIGTERM, &action, NULL); + signal(SIGPIPE, SIG_IGN); + + mobiCoreDriverDaemon = new MobiCoreDriverDaemon( + /* Scheduler status */ + schedulerFlag, + /* Mobicore loading to DDR */ + mobicoreFlag, + mobicoreImage, + /* Ram Donation */ + donationSize, + /* Auto Driver loading */ + driverLoadFlag, + driverPath); + + // Start the driver + mobiCoreDriverDaemon->run(); + + delete mobiCoreDriverDaemon; + + // This should not happen + LOG_E("Exiting MobiCoreDaemon"); + + return EXIT_FAILURE; +} + +//------------------------------------------------------------------------------ +static void checkMobiCoreVersion( + MobiCoreDevice* mobiCoreDevice +) { + bool failed = false; + + // Get MobiCore version info. + mcDrvRspGetMobiCoreVersionPayload_t versionPayload; + mobiCoreDevice->getMobiCoreVersion(&versionPayload); + + if (versionPayload.mcResult != MC_MCP_RET_OK) { + LOG_E("Failed to obtain MobiCore version info. MCP return code: %u", versionPayload.mcResult); + failed = true; + + } else { + LOG_I("Product ID is %s", versionPayload.versionInfo.productId); + + // Check MobiCore version info. + char* msg; + if (!checkVersionOkMCI(versionPayload.versionInfo.versionMci, &msg)) { + LOG_E("%s", msg); + failed = true; + } + LOG_I("%s", msg); + if (!checkVersionOkSO(versionPayload.versionInfo.versionSo, &msg)) { + LOG_E("%s", msg); + failed = true; + } + LOG_I("%s", msg); + if (!checkVersionOkMCLF(versionPayload.versionInfo.versionMclf, &msg)) { + LOG_E("%s", msg); + failed = true; + } + LOG_I("%s", msg); + if (!checkVersionOkCONTAINER(versionPayload.versionInfo.versionContainer, &msg)) { + LOG_E("%s", msg); + failed = true; + } + LOG_I("%s", msg); + } + + if (failed) { + exit(1); + } +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/MobiCoreDriverDaemon.h b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.h new file mode 100644 index 0000000..a6ad2aa --- /dev/null +++ b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.h @@ -0,0 +1,193 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_CONHDLR + * @{ + * @file + * + * MobiCore driver class. + * The MobiCore driver class implements the ConnectionHandler interface. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MOBICOREDRIVER_H_ +#define MOBICOREDRIVER_H_ + +#include "Server/public/ConnectionHandler.h" +#include "Server/public/Server.h" + +#include "MobiCoreDevice.h" +#include <string> +#include <list> + + +#define MAX_SERVERS 2 + +class MobicoreDriverResources { +public: + Connection *conn; + CWsm* pTciWsm; + uint8_t *tci; + uint32_t sessionId; + + MobicoreDriverResources( + Connection *conn, + uint8_t* tci, + CWsm* pTciWsm, + uint32_t sessionId + ) { + this->conn = conn; + this->pTciWsm = pTciWsm; + this->sessionId = sessionId; + }; +}; + +typedef std::list<MobicoreDriverResources*> driverResourcesList_t; + +class MobiCoreDriverDaemon : ConnectionHandler { + +public: + + /** + * Create daemon object + * + * @param enableScheduler Enable NQ IRQ scheduler + * @param loadMobicore Load mobicore image to DDR + * @param mobicoreImage Mobicore image path + * @param donateRamSize Ram donation size in bytes + */ + MobiCoreDriverDaemon( + bool enableScheduler, + /**< Mobicore loading to DDR */ + bool loadMobicore, + std::string mobicoreImage, + unsigned int donateRamSize, + /**< Mobicore driver loading at start-up */ + bool loadDriver, + std::string driverPath + ); + + virtual ~MobiCoreDriverDaemon( + void + ); + + void dropConnection( + Connection *connection + ); + + bool handleConnection( + Connection *connection + ); + + void run( + void + ); + +private: + + MobiCoreDevice *mobiCoreDevice; + /**< Flag to start/stop the scheduler */ + bool enableScheduler; + /**< Flag to load mobicore image to DDR */ + bool loadMobicore; + /**< Mobicore image location */ + std::string mobicoreImage; + /**< Ram size to donate */ + unsigned int donateRamSize; + bool loadDriver; + std::string driverPath; + /**< List of resources for the loaded drivers */ + driverResourcesList_t driverResources; + /**< List of servers processing connections */ + Server *servers[MAX_SERVERS]; + + size_t writeResult( + Connection *connection, + mcDrvRsp_t code + ); + + /** + * Resolve a device ID to a MobiCore device. + * + * @param deviceId Device identifier of the device. + * @return Reference to the device or NULL if device could not be found. + */ + MobiCoreDevice *getDevice( + uint32_t deviceId + ); + + /** + * Load Device driver + * + * @param driverPath Path to the driver file + * @return True for success/false for failure + */ + bool loadDeviceDriver( + std::string driverPath + ); + + void processOpenDevice( + Connection *connection + ); + + void processOpenSession( + Connection *connection + ); + + void processNqConnect( + Connection *connection + ); + + void processCloseDevice( + Connection *connection + ); + + void processNotify( + Connection *connection + ); + + void processCloseSession( + Connection *connection + ); + + void processMapBulkBuf( + Connection *connection + ); + + void processUnmapBulkBuf( + Connection *connection + ); + + void processGetVersion( + Connection *connection + ); + + void processGetMobiCoreVersion( + Connection *connection + ); +}; + +#endif /* MOBICOREDRIVER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Server/Android.mk b/mobicore/daemon/Daemon/Server/Android.mk new file mode 100644 index 0000000..1831793 --- /dev/null +++ b/mobicore/daemon/Daemon/Server/Android.mk @@ -0,0 +1,18 @@ +# ============================================================================= +# +# MC driver server files +# +# ============================================================================= + +# This is not a separate module. +# Only for inclusion by other modules. + +MY_MCDRV_SERVER_PATH := $(call my-dir) +MY_MCDRV_SERVER_PATH_REL := Server + +# Add new folders with header files here +LOCAL_C_INCLUDES += $(MY_MCDRV_SERVER_PATH)/public + +# Add new source files here +LOCAL_SRC_FILES += $(MY_MCDRV_SERVER_PATH_REL)/Server.cpp \ + $(MY_MCDRV_SERVER_PATH_REL)/NetlinkServer.cpp diff --git a/mobicore/daemon/Daemon/Server/NetlinkServer.cpp b/mobicore/daemon/Daemon/Server/NetlinkServer.cpp new file mode 100644 index 0000000..3e12dc8 --- /dev/null +++ b/mobicore/daemon/Daemon/Server/NetlinkServer.cpp @@ -0,0 +1,273 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection server. + * + * Handles incoming socket connections from clients using the MobiCore driver. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "public/NetlinkServer.h" +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <linux/netlink.h> + +#include <stdlib.h> +#include "NetlinkConnection.h" +#include <signal.h> + +#define LOG_TAG "McDaemon" +#include "log.h" + +//------------------------------------------------------------------------------ +NetlinkServer::NetlinkServer( + ConnectionHandler * connectionHandler +):Server(connectionHandler, "dummy") { +} + + +//------------------------------------------------------------------------------ +void NetlinkServer::run( +) { + do + { + LOG_I("%s: start listening on netlink bus", __func__); + + // Open a socket + serverSock = socket(PF_NETLINK, SOCK_DGRAM, MC_DAEMON_NETLINK); + if (serverSock < 0) + { + LOG_E("run(): can't open socket, errno=%d", errno); + break; + } + + // Fill in address structure and bind to socket + struct sockaddr_nl src_addr; + struct nlmsghdr *nlh = NULL; + struct iovec iov; + struct msghdr msg; + uint32_t len; + + memset(&src_addr, 0, sizeof(src_addr)); + src_addr.nl_family = AF_NETLINK; + src_addr.nl_pid = MC_DAEMON_PID; /* daemon pid */ + src_addr.nl_groups = 0; /* not in mcast groups */ + if(bind(serverSock, (struct sockaddr*)&src_addr, sizeof(src_addr)) < 0){ + LOG_E("bind() to server socket failed, errno=%d(%s)", + errno, strerror(errno)); + close(serverSock); + break; + } + + // Start reading the socket + LOG_I("\n********* successfully initialized *********\n"); + + for (;;) + { + // This buffer will be taken over by the connection it was routed to + nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD)); + memset(&msg, 0, sizeof(msg)); + iov.iov_base = (void *)nlh; + iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = &src_addr; + msg.msg_namelen = sizeof(src_addr); + + memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); + + // Read the incomming message and route it to the connection based + // on the incomming PID + if ((len = recvmsg(serverSock, &msg, 0)) < 0) { + LOG_E("%s: recvmsg() failed, errno=%d(%s)", + __func__, errno, strerror(errno)); + break; + } + + if (NLMSG_OK(nlh, len)) { + handleMessage(nlh); + } else { + break; + } + } + } while(false); + + LOG_E("%s: exiting due to error, errno=%d(%s)", + __func__, errno, strerror(errno)); +} + +//------------------------------------------------------------------------------ +void NetlinkServer::handleMessage( + struct nlmsghdr *nlh +) { + uint32_t seq = nlh->nlmsg_seq; + uint32_t pid = nlh->nlmsg_pid; + //LOG_I("%s: Handling NQ message for pid %u seq %u...", __func__, pid, seq); + uint64_t hash = hashConnection(pid, seq); + /* First cleanup the connection list */ + cleanupConnections(); + + NetlinkConnection *connection = findConnection(hash); + // This is a message from a new client + if (connection == NULL) { + //LOG_I("%s: Cound't find the connection, creating a new one", __func__); + connection = new NetlinkConnection(this, serverSock, pid, seq); + // Add the new connection + insertConnection(hash, connection); + } + + connection->handleMessage(nlh); + + // Only handle connections which have not been detached + if(connection->detached == false) + { + if (!connectionHandler->handleConnection(connection)) + { + LOG_I("%s: No command processed.", __func__); + connection->socketDescriptor = -1; + //Inform the driver + connectionHandler->dropConnection(connection); + + // Remove connection from list + removeConnection(hash); + connection->socketDescriptor = -1; + delete connection; + } + // If connection data is set to NULL then device close has been called + // so we must remove all connections associated with this hash + else if (connection->connectionData == NULL && + connection->detached == false) + { + delete connection; + } + } +} + + +//------------------------------------------------------------------------------ +void NetlinkServer::detachConnection( + Connection *connection +) { + connection->detached = true; +} + + +//------------------------------------------------------------------------------ +NetlinkServer::~NetlinkServer( + void +) { + connectionMap_t::iterator i; + // Shut down the server socket + close(serverSock); + + // Destroy all client connections + for (i = peerConnections.begin(); i != peerConnections.end(); i++) { + if (i->second->detached == false) { + delete i->second; + } + } + peerConnections.clear(); +} + + +//------------------------------------------------------------------------------ +NetlinkConnection* NetlinkServer::findConnection( + uint64_t hash +) { + connectionMap_t::iterator i = peerConnections.find(hash); + if (i != peerConnections.end()) { + return i->second; + } + + return NULL; +} + + +//------------------------------------------------------------------------------ +void NetlinkServer::insertConnection( + uint64_t hash, + NetlinkConnection *connection +) { + peerConnections[hash] = connection; +} + +/* This is called from multiple threads! */ +//------------------------------------------------------------------------------ +void NetlinkServer::removeConnection( + uint64_t hash +) { + connectionMap_t::iterator i = peerConnections.find(hash); + if (i != peerConnections.end()){ + peerConnections.erase(i); + } +} + +//------------------------------------------------------------------------------ +void NetlinkServer::cleanupConnections( + void +) { + connectionMap_t::reverse_iterator i; + pid_t pid; + NetlinkConnection *connection = NULL; + // Destroy all client connections + for (i = peerConnections.rbegin(); i != peerConnections.rend(); ++i) { + connection = i->second; + // Only 16 bits are for the actual PID, the rest is session magic + pid = connection->peerPid & 0xFFFF; + //LOG_I("%s: checking PID %u", __func__, pid); + // Check if the peer pid is still alive + if (pid == 0) { + continue; + } + if (kill(pid, 0)) { + bool detached = connection->detached; + LOG_I("%s: PID %u has died, cleaning up session 0x%X", + __func__, pid, connection->peerPid); + + connection->socketDescriptor = -1; + //Inform the driver + connectionHandler->dropConnection(connection); + + // We aren't handling this connection anymore no matter what + removeConnection(connection->hash); + + // Remove connection from list only if detached, the detached + // connections are managed by the device + if (detached == false) { + delete connection; + } + if (peerConnections.size() == 0) { + break; + } + i = peerConnections.rbegin(); + } + } +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Server/Server.cpp b/mobicore/daemon/Daemon/Server/Server.cpp new file mode 100644 index 0000000..e61a8b2 --- /dev/null +++ b/mobicore/daemon/Daemon/Server/Server.cpp @@ -0,0 +1,251 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection server. + * + * Handles incoming socket connections from clients using the MobiCore driver. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "public/Server.h" +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#define LOG_TAG "McDaemon" +#include "log.h" + + +//------------------------------------------------------------------------------ +Server::Server( + ConnectionHandler * connectionHandler, + const char *localAddr +) :socketAddr(localAddr) +{ + this->connectionHandler = connectionHandler; +} + + +//------------------------------------------------------------------------------ +void Server::run( + void +) { + do + { + LOG_I("run(): start listening on socket %s", socketAddr.c_str()); + + // Open a socket (a UNIX domain stream socket) + serverSock = socket(AF_UNIX, SOCK_STREAM, 0); + if (serverSock < 0) + { + LOG_E("run(): can't open stream socket, errno=%d", errno); + break; + } + + // Fill in address structure and bind to socket + struct sockaddr_un serverAddr; + serverAddr.sun_family = AF_UNIX; + strncpy(serverAddr.sun_path, socketAddr.c_str(), sizeof(serverAddr.sun_path) - 1); + + uint32_t len = strlen(serverAddr.sun_path) + sizeof(serverAddr.sun_family); + // Make the socket in the Abstract Domain(no path but everyone can connect) + serverAddr.sun_path[0] = 0; + if (bind(serverSock, (struct sockaddr *) &serverAddr, len) < 0) + { + LOG_E("bind() to server socket failed, errno=%d", errno); + } + + // Start listening on the socket + if (listen(serverSock, LISTEN_QUEUE_LEN) < 0) + { + LOG_E("run(): listen() failed, errno=%d", errno); + break; + } + + LOG_I("\n********* successfully initialized *********\n"); + + for (;;) + { + fd_set fdReadSockets; + + // Clear FD for select() + FD_ZERO(&fdReadSockets); + + // Select server socket descriptor + FD_SET(serverSock, &fdReadSockets); + int maxSocketDescriptor = serverSock; + + // Select socket descriptor of all connections + for (connectionIterator_t iterator = peerConnections.begin(); + iterator != peerConnections.end(); + ++iterator) + { + Connection *connection = (*iterator); + int peerSocket = connection->socketDescriptor; + FD_SET(peerSocket, &fdReadSockets); + if (peerSocket > maxSocketDescriptor) + { + maxSocketDescriptor = peerSocket; + } + } + + // Wait for activities, select() returns the number of sockets + // which require processing + LOG_I("run(): waiting on sockets"); + int numSockets = select( + maxSocketDescriptor + 1, + &fdReadSockets, + NULL, NULL, NULL); + + // Check if select failed + if (numSockets < 0) + { + LOG_E("run(): select() failed, errno=%d", errno); + break; + } + + // actually, this should not happen. + if (0 == numSockets) + { + LOG_W("run(): select() returned 0, spurious event?."); + continue; + } + + LOG_I("run(): events on %d socket(s).", numSockets); + + // Check if a new client connected to the server socket + if (FD_ISSET(serverSock, &fdReadSockets)) + { + do + { + LOG_I("run(): new connection"); + numSockets--; + + struct sockaddr_un clientAddr; + socklen_t clientSockLen = sizeof(clientAddr); + int clientSock = accept( + serverSock, + (struct sockaddr*) &clientAddr, + &clientSockLen); + + if (clientSock <= 0) + { + LOG_E("run(): accept() failed, errno=%d", errno); + break; + } + + Connection *connection = new Connection(clientSock, &clientAddr); + peerConnections.push_back(connection); + LOG_I("run(): added new connection"); + } while (false); + + // we can ignore any errors from accepting a new connection. + // If this fail, the client has to deal with it, we are done + // and nothing has changed. + } + + // Handle traffic on existing client connections + connectionIterator_t iterator = peerConnections.begin(); + while ( (iterator != peerConnections.end()) + && (numSockets > 0) ) + { + Connection *connection = (*iterator); + int peerSocket = connection->socketDescriptor; + + if (!FD_ISSET(peerSocket, &fdReadSockets)) + { + ++iterator; + continue; + } + + numSockets--; + + // the connection will be terminated if command processing + // fails + if (!connectionHandler->handleConnection(connection)) + { + LOG_I("run(): No command processed."); + + //Inform the driver + connectionHandler->dropConnection(connection); + + // Remove connection from list + delete connection; + iterator = peerConnections.erase(iterator); + continue; + } + + ++iterator; + } + } + + } while (false); + + LOG_E("run(): exiting due to error, errno=%d", errno); +} + + +//------------------------------------------------------------------------------ +void Server::detachConnection( + Connection *connection +) { + LOG_I("Detaching NQ connection..."); + + for (connectionIterator_t iterator = peerConnections.begin(); + iterator != peerConnections.end(); + ++iterator) + { + Connection *tmpConnection = (*iterator); + if (tmpConnection == connection) + { + peerConnections.erase(iterator); + LOG_I("NQ connection detached"); + break; + } + } +} + + +//------------------------------------------------------------------------------ +Server::~Server( + void +) { + // Shut down the server socket + close(serverSock); + + // Destroy all client connections + connectionIterator_t iterator = peerConnections.begin(); + while (iterator != peerConnections.end()) + { + Connection *tmpConnection = (*iterator); + delete tmpConnection; + iterator = peerConnections.erase(iterator); + } +} + +/** @} */ diff --git a/mobicore/daemon/Daemon/Server/public/ConnectionHandler.h b/mobicore/daemon/Daemon/Server/public/ConnectionHandler.h new file mode 100644 index 0000000..3d9a002 --- /dev/null +++ b/mobicore/daemon/Daemon/Server/public/ConnectionHandler.h @@ -0,0 +1,68 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Interface for connection handlers used by Server. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CONNECTIONHANDLER_H_ +#define CONNECTIONHANDLER_H_ + +#include "Connection.h" + + +class ConnectionHandler { + +public: + virtual ~ConnectionHandler() {}; + + /** + * Handle connection activities. + * The connection handler shall process pending connection activities. + * + * @param [in] connection Reference to the connection which has data to process. + */ + virtual bool handleConnection( + Connection *connection + ) = 0; + + /** + * Connection has been closed. + * The connection handler shall clean up all resources associated with the given connection. + * After the method has been executed the connection object will be deleted. + * + * @param [in] connection Reference to the connection which will be deleted. + */ + virtual void dropConnection( + Connection *connection + ) = 0; +}; + +#endif /* CONNECTIONHANDLER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Server/public/NetlinkServer.h b/mobicore/daemon/Daemon/Server/public/NetlinkServer.h new file mode 100644 index 0000000..48d51a2 --- /dev/null +++ b/mobicore/daemon/Daemon/Server/public/NetlinkServer.h @@ -0,0 +1,156 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection server. + * + * Handles incoming socket connections from clients using the MobiCore driver. + * + * Iterative socket server using Netlink dgram protocol. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 NETLINKSERVER_H_ +#define NETLINKSERVER_H_ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <linux/netlink.h> +#include <cstdio> +#include <map> + +#include "NetlinkConnection.h" +#include "ConnectionHandler.h" +#include "Server.h" + +class NetlinkServer: public Server, public NetlinkConnectionManager { +public: + /** + * Server contructor. + * + * @param connectionHanler Connection handler to pass incoming connections to. + */ + NetlinkServer( + ConnectionHandler * connectionHandler + ); + + /** + * Server destructor. + * All available connections will be terminated. Resources will be freed. + */ + virtual ~NetlinkServer( + void + ); + + /** + * Start server and listen for incoming connections. + * Implements the central socket server loop. Incoming connections will be stored. + */ + virtual void run( + void + ); + + /** + * Remove a connection object from the list of available connections. + * Detaching is required for notification connections wich are never used to transfer command + * data from TLCs to the driver. If the function succeeds, freeing the connection will no longer + * be the server's responsability. + * + * @param connection The connection object to remove. + */ + virtual void detachConnection( + Connection *connection + ); + +private: + /** + * Handle incomming Netlink message. + * It routes the incomming packet to the apropriate connection based on the packet's + * session magic. + * + * @param nlh The netlink message's header + payload + */ + void handleMessage( + struct nlmsghdr *nlh + ); + + /** + * Retreive connection based on hash. + * Search the peer connections hashmap for a hash and return + * the associated Connection object + * + * @param seq The seq to search + * @return The NetlinkConnection object if found or NULL if not found + */ + NetlinkConnection* findConnection( + uint64_t hash + ); + + /** + * Insert a connection in the peer connection hashmap + * Insert a new connection in the peer connections hashmap. If there is + * already such a connection it will be overriden! + * + * @param seq The seq to use + * @param connection The connection object to insert + */ + void insertConnection( + uint64_t hash, + NetlinkConnection *connection + ); + + /** + * Remove a connection from the peer connections + * Remove the connection associated with seq from the peer list. + * This doesn't actually free the connection object! + * If the seq is invalid nothing happens. + * + * @param seq The seq to use + */ + void removeConnection( + uint64_t hash + ); + + + /** + * Check for sessions started by applications that died(exited) + * Remove the connections to applications that are not active anymore + * If the application has died then all the sessions associated with it + * should be closed! + * + */ + void cleanupConnections( + void + ); + + connectionMap_t peerConnections; /**< Hashmap with connections to clients */ +}; + +#endif /* SERVER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/Server/public/Server.h b/mobicore/daemon/Daemon/Server/public/Server.h new file mode 100644 index 0000000..c14d22c --- /dev/null +++ b/mobicore/daemon/Daemon/Server/public/Server.h @@ -0,0 +1,107 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_SRV + * @{ + * @file + * + * Connection server. + * + * Handles incoming socket connections from clients using the MobiCore driver. + * + * Iterative socket server using UNIX domain stream protocol. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 SERVER_H_ +#define SERVER_H_ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <string> +#include <cstdio> +#include <vector> +#include "CThread.h" +#include "ConnectionHandler.h" + +/** Number of incoming connections that can be queued. + * Additional clients will generate the error ECONNREFUSED. */ +#define LISTEN_QUEUE_LEN (16) + + +class Server: public CThread { + +public: + /** + * Server contructor. + * + * @param connectionHanler Connection handler to pass incoming connections to. + * @param localAdrerss Pointer to a zero terminated string containing the file to listen to. + */ + Server( + ConnectionHandler * connectionHandler, + const char *localAddr + ); + + /** + * Server destructor. + * All available connections will be terminated. Resources will be freed. + */ + virtual ~Server( + void + ); + + /** + * Start server and listen for incoming connections. + * Implements the central socket server loop. Incoming connections will be stored. + */ + virtual void run( + ); + + /** + * Remove a connection object from the list of available connections. + * Detaching is required for notification connections wich are never used to transfer command + * data from TLCs to the driver. If the function succeeds, the connection object will no longer + * be handled by the server. + * + * @param connection The connection object to remove. + */ + virtual void detachConnection( + Connection *connection + ); + +protected: + int serverSock; + string socketAddr; + ConnectionHandler *connectionHandler; /**< Connection handler registered to the server */ + +private: + connectionList_t peerConnections; /**< Connections to devices */ + +}; + +#endif /* SERVER_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/public/MobiCoreDriverCmd.h b/mobicore/daemon/Daemon/public/MobiCoreDriverCmd.h new file mode 100644 index 0000000..15be3a6 --- /dev/null +++ b/mobicore/daemon/Daemon/public/MobiCoreDriverCmd.h @@ -0,0 +1,335 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON + * @{ + * @file + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MCDAEMON_H_ +#define MCDAEMON_H_ + +#include <inttypes.h> // ANSI C99 + + +#define SOCK_PATH "#mcdaemon" +#include "mcUuid.h" +#include "mcVersionInfo.h" + +typedef enum { + MC_DRV_CMD_PING = 0, + MC_DRV_CMD_GET_INFO = 1, + MC_DRV_CMD_OPEN_DEVICE = 2, + MC_DRV_CMD_CLOSE_DEVICE = 3, + MC_DRV_CMD_NQ_CONNECT = 4, + MC_DRV_CMD_OPEN_SESSION = 5, + MC_DRV_CMD_CLOSE_SESSION = 6, + MC_DRV_CMD_NOTIFY = 7, + MC_DRV_CMD_MAP_BULK_BUF = 8, + MC_DRV_CMD_UNMAP_BULK_BUF = 9, + MC_DRV_CMD_GET_VERSION = 10, + MC_DRV_CMD_GET_MOBICORE_VERSION = 11, +} mcDrvCmd_t; + + +typedef enum { + MC_DRV_RSP_OK = 0, + MC_DRV_RSP_FAILED = 1, + MC_DRV_RSP_DEVICE_NOT_OPENED = 2, + MC_DRV_RSP_DEVICE_ALREADY_OPENED = 3, + MC_DRV_RSP_COMMAND_NOT_ALLOWED = 4, + MC_DRV_INVALID_DEVICE_NAME = 5, + MC_DRV_RSP_MAP_BULK_ERRO = 6, + MC_DRV_RSP_TRUSTLET_NOT_FOUND = 7, + MC_DRV_RSP_PAYLOAD_LENGTH_ERROR = 8, + MC_DRV_RSP_WRONG_PUBLIC_KEY = 9, /**< System Trustlet public key is wrong. */ + MC_DRV_RSP_CONTAINER_TYPE_MISMATCH = 10, /**< Wrong containter type(s). */ + MC_DRV_RSP_CONTAINER_LOCKED = 11, /**< Container is locked (or not activated). */ + MC_DRV_RSP_SP_NO_CHILD = 12, /**< SPID is not registered with root container. */ + MC_DRV_RSP_TL_NO_CHILD = 13, /**< UUID is not registered with sp container. */ + MC_DRV_RSP_UNWRAP_ROOT_FAILED = 14, /**< Unwrapping of root container failed. */ + MC_DRV_RSP_UNWRAP_SP_FAILED = 15, /**< Unwrapping of service provider container failed. */ + MC_DRV_RSP_UNWRAP_TRUSTLET_FAILED = 16, /**< Unwrapping of Trustlet container failed. */ +} mcDrvRsp_t; + + +typedef struct { + uint32_t commandId; +} mcDrvCommandHeader_t, *mcDrvCommandHeader_ptr; + +typedef struct { + uint32_t responseId; +} mcDrvResponseHeader_t, *mcDrvResponseHeader_ptr; + +#define MC_DEVICE_ID_DEFAULT 0 /**< The default device ID */ + + +//-------------------------------------------------------------- +typedef struct{ + uint32_t deviceId; +} mcDrvCmdOpenDevicePayload_t, *mcDrvCmdOpenDevicePayload_ptr; + +typedef struct{ + mcDrvCommandHeader_t header; + mcDrvCmdOpenDevicePayload_t payload; +} mcDrvCmdOpenDevice_t, *mcDrvCmdOpenDevice_ptr; + + +typedef struct{ + // empty +} mcDrvRspOpenDevicePayload_t, *mcDrvRspOpenDevicePayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspOpenDevicePayload_t payload; +} mcDrvRspOpenDevice_t, *mcDrvRspOpenDevice_ptr; + + +//-------------------------------------------------------------- +typedef struct{ + mcDrvCommandHeader_t header; + // no payload here because close has none. + // If we use an empty struct, C++ will count it as 4 bytes. + // This will write too much into the socket at write(cmd,sizeof(cmd)) +} mcDrvCmdCloseDevice_t, *mcDrvCmdCloseDevice_ptr; + + +typedef struct{ + // empty +} mcDrvRspCloseDevicePayload_t, *mcDrvRspCloseDevicePayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspCloseDevicePayload_t payload; +} mcDrvRspCloseDevice_t, *mcDrvRspCloseDevice_ptr; + + +//-------------------------------------------------------------- +typedef struct{ + uint32_t deviceId; + mcUuid_t uuid; + uint32_t tci; + uint32_t len; +} mcDrvCmdOpenSessionPayload_t, *mcDrvCmdOpenSessionPayload_ptr; + +typedef struct{ + mcDrvCommandHeader_t header; + mcDrvCmdOpenSessionPayload_t payload; +} mcDrvCmdOpenSession_t, *mcDrvCmdOpenSession_ptr; + + +typedef struct{ + uint32_t deviceId; + uint32_t sessionId; + uint32_t deviceSessionId; + uint32_t mcResult; + uint32_t sessionMagic; +} mcDrvRspOpenSessionPayload_t, *mcDrvRspOpenSessionPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspOpenSessionPayload_t payload; +} mcDrvRspOpenSession_t, *mcDrvRspOpenSession_ptr; + + +//-------------------------------------------------------------- +typedef struct{ + uint32_t sessionId; +} mcDrvCmdCloseSessionPayload_t, *mcDrvCmdCloseSessionPayload_ptr; + +typedef struct{ + mcDrvCommandHeader_t header; + mcDrvCmdCloseSessionPayload_t payload; +} mcDrvCmdCloseSession_t, *mcDrvCmdCloseSession_ptr; + + +typedef struct{ + // empty +} mcDrvRspCloseSessionPayload_t, *mcDrvRspCloseSessionPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspCloseSessionPayload_t payload; +} mcDrvRspCloseSession_t, *mcDrvRspCloseSession_ptr; + + +//-------------------------------------------------------------- +typedef struct{ + uint32_t sessionId; +} mcDrvCmdNotifyPayload_t, *mcDrvCmdNotifyPayload_ptr; + +typedef struct{ + mcDrvCommandHeader_t header; + mcDrvCmdNotifyPayload_t payload; +} mcDrvCmdNotify_t, *mcDrvCmdNotify_ptr; + + +typedef struct{ + // empty +} mcDrvRspNotifyPayload_t, *mcDrvRspNotifyPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspNotifyPayload_t payload; +} mcDrvRspNotify_t, *mcDrvRspNotify_ptr; + + +//-------------------------------------------------------------- +typedef struct{ + uint32_t sessionId; + uint32_t pAddrL2; + uint32_t offsetPayload; + uint32_t lenBulkMem; +} mcDrvCmdMapBulkMemPayload_t, *mcDrvCmdMapBulkMemPayload_ptr; + +typedef struct{ + mcDrvCommandHeader_t header; + mcDrvCmdMapBulkMemPayload_t payload; +} mcDrvCmdMapBulkMem_t, *mcDrvCmdMapBulkMem_ptr; + + +typedef struct{ + uint32_t sessionId; + uint32_t secureVirtualAdr; + uint32_t mcResult; +} mcDrvRspMapBulkMemPayload_t, *mcDrvRspMapBulkMemPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspMapBulkMemPayload_t payload; +} mcDrvRspMapBulkMem_t, *mcDrvRspMapBulkMem_ptr; + + +//-------------------------------------------------------------- +typedef struct{ + uint32_t sessionId; + uint32_t secureVirtualAdr; + uint32_t lenBulkMem; +} mcDrvCmdUnmapBulkMemPayload_t, *mcDrvCmdUnmapBulkMemPayload_ptr; + +typedef struct{ + mcDrvCommandHeader_t header; + mcDrvCmdUnmapBulkMemPayload_t payload; +} mcDrvCmdUnmapBulkMem_t, *mcDrvCmdUnmapBulkMem_ptr; + + +typedef struct{ + uint32_t responseId; + uint32_t sessionId; + uint32_t mcResult; +} mcDrvRspUnmapBulkMemPayload_t, *mcDrvRspUnmapBulkMemPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspUnmapBulkMemPayload_t payload; +} mcDrvRspUnmapBulkMem_t, *mcDrvRspUnmapBulkMem_ptr; + + +//-------------------------------------------------------------- +typedef struct { + uint32_t deviceId; + uint32_t sessionId; + uint32_t deviceSessionId; + uint32_t sessionMagic; //Random data +} mcDrvCmdNqConnectPayload_t, *mcDrvCmdNqConnectPayload_ptr; + +typedef struct { + mcDrvCommandHeader_t header; + mcDrvCmdNqConnectPayload_t payload; +} mcDrvCmdNqConnect_t, *mcDrvCmdNqConnect_ptr; + + +typedef struct { + // empty; +} mcDrvRspNqConnectPayload_t, *mcDrvRspNqConnectPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspNqConnectPayload_t payload; +} mcDrvRspNqConnect_t, *mcDrvRspNqConnect_ptr; + +//-------------------------------------------------------------- +typedef struct { + mcDrvCommandHeader_t header; +} mcDrvCmdGetVersion_t, *mcDrvCmdGetVersion_ptr; + + +typedef struct { + uint32_t version; +} mcDrvRspGetVersionPayload_t, *mcDrvRspGetVersionPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspGetVersionPayload_t payload; +} mcDrvRspGetVersion_t, mcDrvRspGetVersion_ptr; + +//-------------------------------------------------------------- +typedef struct { + mcDrvCommandHeader_t header; +} mcDrvCmdGetMobiCoreVersion_t, *mcDrvCmdGetMobiCoreVersion_ptr; + + +typedef struct { + uint32_t mcResult; + mcVersionInfo_t versionInfo; +} mcDrvRspGetMobiCoreVersionPayload_t, *mcDrvRspGetMobiCoreVersionPayload_ptr; + +typedef struct{ + mcDrvResponseHeader_t header; + mcDrvRspGetMobiCoreVersionPayload_t payload; +} mcDrvRspGetMobiCoreVersion_t, mcDrvRspGetMobiCoreVersion_ptr; + +//-------------------------------------------------------------- +typedef union { + mcDrvCommandHeader_t header; + mcDrvCmdOpenDevice_t mcDrvCmdOpenDevice; + mcDrvCmdCloseDevice_t mcDrvCmdCloseDevice; + mcDrvCmdOpenSession_t mcDrvCmdOpenSession; + mcDrvCmdCloseSession_t mcDrvCmdCloseSession; + mcDrvCmdNqConnect_t mcDrvCmdNqConnect; + mcDrvCmdNotify_t mcDrvCmdNotify; + mcDrvCmdMapBulkMem_t mcDrvCmdMapBulkMem; + mcDrvCmdUnmapBulkMem_t mcDrvCmdUnmapBulkMem; + mcDrvCmdGetVersion_t mcDrvCmdGetVersion; + mcDrvCmdGetMobiCoreVersion_t mcDrvCmdGetMobiCoreVersion; +} mcDrvCommand_t, *mcDrvCommand_ptr; + +typedef union { + mcDrvResponseHeader_t header; + mcDrvRspOpenDevice_t mcDrvRspOpenDevice; + mcDrvRspCloseDevice_t mcDrvRspCloseDevice; + mcDrvRspOpenSession_t mcDrvRspOpenSession; + mcDrvRspCloseSession_t mcDrvRspCloseSession; + mcDrvRspNqConnect_t mcDrvRspNqConnect; + mcDrvRspNotify_t mcDrvRspNotify; + mcDrvRspMapBulkMem_t mcDrvRspMapBulkMem; + mcDrvRspUnmapBulkMem_t mcDrvRspUnmapBulkMem; + mcDrvRspGetVersion_t mcDrvRspGetVersion; + mcDrvRspGetMobiCoreVersion_t mcDrvRspGetMobiCoreVersion; +} mcDrvResponse_t, *mcDrvResponse_ptr; + +#endif /* MCDAEMON_H_ */ + +/** @} */ diff --git a/mobicore/daemon/Daemon/public/mcVersion.h b/mobicore/daemon/Daemon/public/mcVersion.h new file mode 100644 index 0000000..e019562 --- /dev/null +++ b/mobicore/daemon/Daemon/public/mcVersion.h @@ -0,0 +1,35 @@ +/** + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 DAEMON_VERSION_H_ +#define DAEMON_VERSION_H_ + +#define DAEMON_VERSION_MAJOR 0 +#define DAEMON_VERSION_MINOR 2 + +#endif /** DAEMON_VERSION_H_ */ + diff --git a/mobicore/daemon/Kernel/Android.mk b/mobicore/daemon/Kernel/Android.mk new file mode 100644 index 0000000..9caae0e --- /dev/null +++ b/mobicore/daemon/Kernel/Android.mk @@ -0,0 +1,38 @@ +# ============================================================================= +# +# Module: libKernel.a - Kernel module access classes +# +# ============================================================================= + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libMcKernel + +# Include platform specific sub-makefiles +ifdef PLATFORM + include $(LOCAL_PATH)/Platforms/Generic/Android.mk + include $(LOCAL_PATH)/Platforms/$(PLATFORM)/Android.mk +else + include $(LOCAL_PATH)/Platforms/Generic/Android.mk +endif + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(COMP_PATH_MobiCoreDriverMod)/Public \ + $(APP_PROJECT_PATH)/Common \ + $(LOCAL_PATH) + +# Add new source files here +LOCAL_SRC_FILES +=\ + CKMod.cpp + +# Header files for components including this module +LOCAL_EXPORT_C_INCLUDES +=\ + $(LOCAL_PATH) + +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions + +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_STATIC_LIBRARY) diff --git a/mobicore/daemon/Kernel/CKMod.cpp b/mobicore/daemon/Kernel/CKMod.cpp new file mode 100644 index 0000000..a78b87d --- /dev/null +++ b/mobicore/daemon/Kernel/CKMod.cpp @@ -0,0 +1,122 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL + * @{ + * @file + * + * Kernel Module Interface. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <cstdlib> + +#include <fcntl.h> +#include <sys/mman.h> +#include <errno.h> + +#include "CKMod.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + + +//------------------------------------------------------------------------------ +CKMod::CKMod( + void +) { + fdKMod = ERROR_KMOD_NOT_OPEN; +} + + +//------------------------------------------------------------------------------ +CKMod::~CKMod( + void +) { + close(); +} + + +//------------------------------------------------------------------------------ +bool CKMod::isOpen( + void +) { + return (ERROR_KMOD_NOT_OPEN == fdKMod) ? false : true; +} + + +//------------------------------------------------------------------------------ +bool CKMod::open( + const char *deviceName +) { + bool ret = true; + + do + { + if (isOpen()) + { + LOG_W("already open"); + ret = false; + break; + } + + // open return -1 on error, "errno" is set with details + int openRet = ::open(deviceName, O_RDWR); + if (-1 == openRet) + { + LOG_E("open failed with errno: %d", errno); + ret = false; + break; + } + + fdKMod = openRet; + + } while(0); + + return ret; +} + + +//------------------------------------------------------------------------------ +void CKMod::close( + void +) { + if (isOpen()) + { + if (0 != ::close(fdKMod)) + { + LOG_E("close failed with errno: %d", errno); + } + else + { + fdKMod = ERROR_KMOD_NOT_OPEN; + } + } + else + { + LOG_W("not open"); + } +} + +/** @} */ diff --git a/mobicore/daemon/Kernel/CKMod.h b/mobicore/daemon/Kernel/CKMod.h new file mode 100644 index 0000000..bb1d54d --- /dev/null +++ b/mobicore/daemon/Kernel/CKMod.h @@ -0,0 +1,77 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL + * @{ + * @file + * + * Kernel Module Interface. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CKMOD_H_ +#define CKMOD_H_ + +#include <stdint.h> + + +#define ERROR_KMOD_NOT_OPEN ((int)(-1)) + +/** + * Base class for accessing a kernel module. + */ +class CKMod { + +protected: + + int fdKMod; + + /** + * Helper function to check if connected to kernel module. + */ + bool isOpen( + void + ); + +public: + + CKMod( + void + ); + + virtual ~CKMod( + void + ); + + bool open( + const char *deviceName + ); + + void close( + void + ); + +}; + +#endif // CKMOD_H_ diff --git a/mobicore/daemon/Kernel/Platforms/Generic/Android.mk b/mobicore/daemon/Kernel/Platforms/Generic/Android.mk new file mode 100644 index 0000000..ac816f1 --- /dev/null +++ b/mobicore/daemon/Kernel/Platforms/Generic/Android.mk @@ -0,0 +1,27 @@ +# ============================================================================= +# +# Generic TrustZone device includes +# +# ============================================================================= + +# This is not a separate module. +# Only for inclusion by other modules. + +GENERIC_MODULE_PATH := $(call my-dir) +GENERIC_MODULE_PATH_REL := Platforms/Generic + +# Add new source files here +LOCAL_SRC_FILES +=\ + $(GENERIC_MODULE_PATH_REL)/CMcKMod.cpp + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(GENERIC_MODULE_PATH)\ + $(COMP_PATH_MobiCore)/inc\ + $(COMP_PATH_MobiCoreDriverMod)/Public + +# Header files for components including this module +LOCAL_EXPORT_C_INCLUDES +=\ + $(GENERIC_MODULE_PATH)\ + $(COMP_PATH_MobiCoreDriverMod)/Public + \ No newline at end of file diff --git a/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.cpp b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.cpp new file mode 100644 index 0000000..1973ac1 --- /dev/null +++ b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.cpp @@ -0,0 +1,566 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL + * @{ + * @file + * + * MobiCore Driver Kernel Module Interface. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <cstdlib> + +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <inttypes.h> +#include <cstring> + +#include "McTypes.h" +#include "mc_drv_module_api.h" +#include "mcVersionHelper.h" + +#include "CMcKMod.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + +//------------------------------------------------------------------------------ +MC_CHECK_VERSION(MCDRVMODULEAPI,0,1); + +// TODO: rename this to mapWsm +//------------------------------------------------------------------------------ +int CMcKMod::mmap( + uint32_t len, + uint32_t *pHandle, + addr_t *pVirtAddr, + addr_t *pPhysAddr, + bool *pMciReuse +) { + int ret = 0; + do + { + LOG_I("mmap(): len=%d, mci_reuse=%x", len, *pMciReuse); + + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + // TODO: add type parameter to distinguish between non-freeing TCI, MCI and others + addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, + fdKMod, *pMciReuse ? MC_DRV_KMOD_MMAP_MCI + : MC_DRV_KMOD_MMAP_WSM); + if (MAP_FAILED == virtAddr) + { + LOG_E("mmap() failed with errno: %d", errno); + ret = ERROR_MAPPING_FAILED; + break; + } + + // mapping response data is in the buffer + struct mc_mmap_resp *pMmapResp = (struct mc_mmap_resp *) virtAddr; + + *pMciReuse = pMmapResp->is_reused; + + LOG_I("mmap(): virtAddr=%p, handle=%d, phys_addr=%p, is_reused=%s", + virtAddr, pMmapResp->handle, (addr_t) (pMmapResp->phys_addr), + pMmapResp->is_reused ? "true" : "false"); + + if (NULL != pVirtAddr) + { + *pVirtAddr = virtAddr; + } + + if (NULL != pHandle) + { + *pHandle = pMmapResp->handle; + } + + if (NULL != pPhysAddr) + { + *pPhysAddr = (addr_t) (pMmapResp->phys_addr); + } + + // clean memory + memset(pMmapResp, 0, sizeof(*pMmapResp)); + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::mapPersistent( + uint32_t len, + uint32_t *pHandle, + addr_t *pVirtAddr, + addr_t *pPhysAddr +) { + int ret = 0; + do + { + LOG_I("mapPersistent(): len=%d", len); + + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, + fdKMod, MC_DRV_KMOD_MMAP_PERSISTENTWSM); + + if (MAP_FAILED == virtAddr) + { + LOG_E("mmap() failed with errno: %d", errno); + ret = ERROR_MAPPING_FAILED; + break; + } + + // mapping response data is in the buffer + struct mc_mmap_resp *pMmapResp = (struct mc_mmap_resp *) virtAddr; + + LOG_I("mapPersistent(): virtAddr=%p, handle=%d, phys_addr=%p, is_reused=%s", + virtAddr, pMmapResp->handle, + (addr_t) (pMmapResp->phys_addr), + pMmapResp->is_reused ? "true" : "false"); + + if (NULL != pVirtAddr) + { + *pVirtAddr = virtAddr; + } + + if (NULL != pHandle) + { + *pHandle = pMmapResp->handle; + } + + if (NULL != pPhysAddr) + { + *pPhysAddr = (addr_t) (pMmapResp->phys_addr); + } + + // clean memory + memset(pMmapResp, 0, sizeof(*pMmapResp)); + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::read( + addr_t buffer, + uint32_t len +) { + int ret = 0; + + do + { + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + ret = ::read(fdKMod, buffer, len); + if(-1 == ret) + { + LOG_E("read() failed with errno: %d", errno); + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +bool CMcKMod::waitSSIQ( + uint32_t *pCnt +) { + int ret = true; + + do + { + uint32_t cnt; + int ret = read(&cnt, sizeof(cnt)); + if (sizeof(cnt) != ret) + { + ret = false; + } + + if (NULL != pCnt) + { + *pCnt = cnt; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::fcInit( + addr_t mciBuffer, + uint32_t nqOffset, + uint32_t nqLength, + uint32_t mcpOffset, + uint32_t mcpLength +) { + int ret = 0; + + do + { + if (!isOpen()) + { + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + // Init MC with NQ and MCP buffer addresses + union mc_ioctl_init_params fcInitParams = { + // C++ does not support C99 designated initializers + /* .in = */{ + /* .base = */(uint32_t) mciBuffer, + /* .nq_offset = */nqOffset, + /* .nq_length = */nqLength, + /* .mcp_offset = */mcpOffset, + /* .mcp_length = */mcpLength } }; + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_INIT, &fcInitParams); + if (ret != 0) + { + LOG_E("IOCTL_FC_INIT failed with ret = %d and errno = %d", ret, errno); + break; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::fcInfo( + uint32_t extInfoId, + uint32_t *pState, + uint32_t *pExtInfo +) { + int ret = 0; + + do + { + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + // Init MC with NQ and MCP buffer addresses + union mc_ioctl_info_params fcInfoParams = { + // C++ does not support C99 designated initializers + /* .in = */{ + /* .ext_info_id = */extInfoId } }; + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_INFO, &fcInfoParams); + if (ret != 0) + { + LOG_E("IOCTL_FC_INFO failed with ret = %d and errno = %d", ret, errno); + break; + } + + if (NULL != pState) + { + *pState = fcInfoParams.out.state; + } + + if (NULL != pExtInfo) + { + *pExtInfo = fcInfoParams.out.ext_info; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::fcYield( + void +) { + int ret = 0; + + do + { + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_YIELD, NULL); + if (ret != 0) + { + LOG_E("IOCTL_FC_YIELD failed with ret = %d and errno = %d", ret, errno); + break; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::fcNSIQ( + void +) { + int ret = 0; + + do + { + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_NSIQ, NULL); + if (ret != 0) + { + LOG_E("IOCTL_FC_NSIQ failed with ret = %d and errno = %d", ret, errno); + break; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::free( + uint32_t handle +) { + int ret = 0; + + do + { + LOG_I("free(): handle=%d", handle); + + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + union mc_ioctl_free_params freeParams = { + // C++ does not support c99 designated initializers + /* .in = */{ + /* .handle = */(uint32_t) handle } }; + + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FREE, &freeParams); + if (0 != ret) + { + LOG_E("IOCTL_FREE failed with ret = %d and errno = %d", ret, errno); + break; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::registerWsmL2( + addr_t buffer, + uint32_t len, + uint32_t pid, + uint32_t *pHandle, + addr_t *pPhysWsmL2 +) { + int ret = 0; + + do + { + LOG_I("registerWsmL2(): buffer=%p, len=%d, pid=%d", buffer, len, pid); + + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + union mc_ioctl_app_reg_wsm_l2_params params = { + // C++ does not support C99 designated initializers + /* .in = */{ + /* .buffer = */(uint32_t) buffer, + /* .len = */len, + /* .pid = */pid } }; + + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2, ¶ms); + if (0 != ret) + { + LOG_E("IOCTL_APP_REGISTER_WSM_L2 failed with ret = %d and errno = %d", ret, errno); + break; + } + + LOG_I("WSM L2 phys=%x, handle=%d", params.out.phys_wsm_l2_table, + params.out.handle); + + if (NULL != pHandle) + { + *pHandle = params.out.handle; + } + + if (NULL != pPhysWsmL2) + { + *pPhysWsmL2 = (addr_t) params.out.phys_wsm_l2_table; + } + + } while (0); + + return ret; +} + + +//------------------------------------------------------------------------------ +int CMcKMod::unregisterWsmL2( + uint32_t handle +) { + int ret = 0; + + do + { + LOG_I("unregisterWsmL2(): handle=%d", handle); + + if (!isOpen()) + { + LOG_E("no connection to kmod"); + ret = ERROR_KMOD_NOT_OPEN; + break; + } + + struct mc_ioctl_app_unreg_wsm_l2_params params = { + // C++ does not support c99 designated initializers + /* .in = */{ + /* .handle = */handle } }; + + int ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2, ¶ms); + if (0 != ret) + { + LOG_E("IOCTL_APP_UNREGISTER_WSM_L2 failed with ret = %d and errno = %d", ret, errno); + break; + } + + } while (0); + + return ret; +} + +//------------------------------------------------------------------------------ +int CMcKMod::fcExecute( + addr_t startAddr, + uint32_t areaLength +) { + int ret = 0; + union mc_ioctl_fc_execute_params params = { + /*.in =*/ { + /*.phys_start_addr = */ (uint32_t)startAddr, + /*.length = */ areaLength + } + }; + do + { + if (!isOpen()) + { + LOG_E("no connection to kmod"); + break; + } + + ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_EXECUTE, ¶ms); + if (ret != 0) + { + LOG_E("IOCTL_FC_EXECUTE failed with ret = %d and errno = %d", ret, errno); + break; + } + + } while(0); + + return ret; +} +//------------------------------------------------------------------------------ +bool CMcKMod::checkKmodVersionOk( + void +) { + bool ret = false; + + do + { + if (!isOpen()) + { + LOG_E("no connection to kmod"); + break; + } + + struct mc_ioctl_get_version_params params; + + int ioret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_GET_VERSION, ¶ms); + if (0 != ioret) + { + LOG_E("IOCTL_GET_VERSION failed with ret = %d and errno = %d", ret, errno); + break; + } + + // Run-time check. + char* errmsg; + if (!checkVersionOkMCDRVMODULEAPI(params.out.kernel_module_version, &errmsg)) { + LOG_E("%s", errmsg); + break; + } + LOG_I("%s", errmsg); + + ret = true; + + } while (0); + + return ret; +} + +/** @} */ diff --git a/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.h b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.h new file mode 100644 index 0000000..fa04bf2 --- /dev/null +++ b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.h @@ -0,0 +1,145 @@ +/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL + * @{ + * @file + * + * MobiCore Driver Kernel Module Interface. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 CMCKMOD_H_ +#define CMCKMOD_H_ + +#include <stdint.h> + +#include "McTypes.h" +#include "CKMod.h" + + +#define ERROR_MAPPING_FAILED ((int)(-2)) + +/** + * As this is also used by the ClientLib, we do not use exceptions. + */ +class CMcKMod : public CKMod { + +public: + + /** + * Map data. + * + * @param len + * @param pHandle + * @param pVirtAddr + * @param pPhysAddr + * @param pMciReuse [in|out] set to true [in] for reusing MCI buffer + * is set to true [out] if MCI buffer has been reused + * @return 0 if all went fine + * @return ERROR_KMOD_NOT_OPEN + * @return ERROR_MAPPING_FAILED + */ + int mmap( + uint32_t len, + uint32_t *pHandle, + addr_t *pVirtAddr, + addr_t *pPhysAddr, + bool *pMciReuse + ); + + /** + * Map persistent WSM which will not be freed up once the calling process dies. + */ + int mapPersistent( + uint32_t len, + uint32_t *pHandle, + addr_t *pVirtAddr, + addr_t *pPhysAddr + ); + + int read( + addr_t buffer, + uint32_t len + ); + + bool waitSSIQ( + uint32_t *pCnt + ); + + int fcInit( + addr_t mciBuffer, + uint32_t nqOffset, + uint32_t nqLength, + uint32_t mcpOffset, + uint32_t mcpLength + ); + + int fcInfo( + uint32_t extInfoId, + uint32_t *pState, + uint32_t *pExtInfo + ); + + int fcYield( + void + ); + + int fcNSIQ( + void + ); + + int free( + uint32_t handle + ); + + int registerWsmL2( + addr_t buffer, + uint32_t len, + uint32_t pid, + uint32_t *pHandle, + addr_t *pPhysWsmL2 + ); + + int unregisterWsmL2( + uint32_t handle + ); + + /** + * Tell stub to start MobiCore from given physical address + */ + int fcExecute( + addr_t startAddr, + uint32_t areaLength + ); + + bool checkKmodVersionOk( + void + ); + +}; + +typedef CMcKMod *CMcKMod_ptr; + +#endif // CMCKMOD_H_ diff --git a/mobicore/daemon/PaApi/Android.mk b/mobicore/daemon/PaApi/Android.mk new file mode 100644 index 0000000..4630bbe --- /dev/null +++ b/mobicore/daemon/PaApi/Android.mk @@ -0,0 +1,35 @@ +# ============================================================================= +# +# Module: libPaApi(Static and Shared variant) +# +# ============================================================================= + +LOCAL_PATH := $(call my-dir) + +#Now the Shared Object +include $(CLEAR_VARS) + +LOCAL_MODULE := libPaApi +LOCAL_MODULE_TAGS := eng +LOCAL_PRELINK_MODULE := false + +LOCAL_C_INCLUDES += bionic \ + external/stlport/stlport + +# Add your folders with header files here (absolute paths) +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/Public \ + $(COMP_PATH_MobiCore)/inc \ + $(COMP_PATH_MobiCore)/inc/TlCm \ + $(APP_PROJECT_PATH)/ClientLib/public + +# Add your source files here (relative paths) +LOCAL_SRC_FILES += tlcCmApi.cpp + +LOCAL_SHARED_LIBRARIES += libMcRegistry libMcClient +LOCAL_STATIC_LIBRARIES = libstlport_static +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions + +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_SHARED_LIBRARY) diff --git a/mobicore/daemon/PaApi/Public/paApi.h b/mobicore/daemon/PaApi/Public/paApi.h new file mode 100644 index 0000000..6c30026 --- /dev/null +++ b/mobicore/daemon/PaApi/Public/paApi.h @@ -0,0 +1,44 @@ +/** + * @file + * Proivisioning Agent API. + * + * This header file describes the Provisioning Agent API. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * @defgroup PA_API Provisioning Agent API + * @defgroup TLC_CONTENT_MANAGER Content Manager API + * @ingroup PA_API + * + * @defgroup MCD_MCDIMPL_DAEMON_REG Registry API + * @ingroup PA_API + */ + +#include "tlcCmApi.h" +#include "MobiCoreRegistry.h" + + diff --git a/mobicore/daemon/PaApi/Public/tlcCmApi.h b/mobicore/daemon/PaApi/Public/tlcCmApi.h new file mode 100644 index 0000000..a9ea100 --- /dev/null +++ b/mobicore/daemon/PaApi/Public/tlcCmApi.h @@ -0,0 +1,84 @@ +/** @addtogroup TLC_CONTENT_MANAGER + * @{ + * @file + * Content Manager API. + * + * This header file describes the interface to the content management trustlet + * connector (Content Manager). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "MobiCoreDriverApi.h" +#include "mcUuid.h" +#include "tlCmApi.h" +#include "tlCmError.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Opens a content management session. + * + * After opening a content management session the content manager is ready to + * accecpt content management requests. Upon successful execution, this function + * sets the cmp pointer to a content management protocol object that is to be + * used for subsequent content management operations. + * + * @param [out] cmp Content management protocol object. + * + * @return MC_DRV_OK or error code. + */ +mcResult_t cmOpen(cmp_t** cmp); + +/** Closes a content management session. + * + * @return MC_DRV_OK or error code. + */ +mcResult_t cmClose(void); + +/** Performs a content management operation. + * + * Executes the command contained in the content management protocol object + * + * returned from cmOpen. The result of the content management operation is also + * conveyed within the CMP object returned from cmOpen, unless the overall + * operation was aborted due to a low-level driver error, in which case the + * return value of this routine is different to MC_DRV_OK. + * + * @return Indication as to whether the content management operation was executed. + * MC_DRV_OK denotes that the operation was executed (see response contents of + * the cmp_t object for details about the result of the operation). + */ +mcResult_t cmManage(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ + diff --git a/mobicore/daemon/PaApi/tlcCmApi.cpp b/mobicore/daemon/PaApi/tlcCmApi.cpp new file mode 100644 index 0000000..86f213c --- /dev/null +++ b/mobicore/daemon/PaApi/tlcCmApi.cpp @@ -0,0 +1,122 @@ +/** @addtogroup TLC_CONTENT_MANAGER + * @{ + * @file + * Content Manager API (implementation). + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "tlcCmApi.h" +#include "tlCmUuid.h" + +#define LOG_TAG "TlcCmApi" +#include "log.h" + +#include <assert.h> +#include <stdlib.h> + + +static const uint32_t DEVICE_ID = MC_DEVICE_ID_DEFAULT; +static mcSessionHandle_t m_sessionHandle = { 0, 0 }; + +mcResult_t cmOpen(cmp_t** cmp) +{ + const mcUuid_t UUID = TL_CM_UUID; + mcResult_t result; + + if (NULL == cmp) { + LOG_E("Parameter cmp is NULL"); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + result = mcOpenDevice(DEVICE_ID); + if (MC_DRV_OK != result) { + LOG_E("Error opening device: %d", result); + return result; + } + result = mcMallocWsm(DEVICE_ID, 0, sizeof(cmp_t), (uint8_t **)cmp, 0); + if (MC_DRV_OK != result) { + LOG_E("Allocation of CMP WSM failed: %d", result); + return result; + } + + result = mcOpenSession(&m_sessionHandle, &UUID, (uint8_t *)*cmp, (uint32_t) sizeof(cmp_t)); + if (MC_DRV_OK != result) { + LOG_E("Open session failed: %d", result); + } + + return result; +} + +mcResult_t cmClose(void) +{ + mcResult_t result; + + if (0 == m_sessionHandle.sessionId) { + LOG_E("No session to close!"); + } + result = mcCloseSession(&m_sessionHandle); + if (MC_DRV_OK != result) { + LOG_E("Closing session failed: %d", result); + } + result = mcCloseDevice(DEVICE_ID); + if (MC_DRV_OK != result) { + LOG_E("Closing MobiCore device failed: %d", result); + } + + return result; +} + +mcResult_t cmManage(void) +{ + mcResult_t result; + + if (0 == m_sessionHandle.sessionId) { + LOG_E("No session."); + return MC_DRV_ERR_INIT; + } + + // Send CMP message to content management trustlet. + result = mcNotify(&m_sessionHandle); + + if (MC_DRV_OK != result) { + LOG_E("Notify failed: %d", result); + return result; + } + + // Wait for trustlet response. + result = mcWaitNotification(&m_sessionHandle, MC_INFINITE_TIMEOUT); + + if (MC_DRV_OK != result) { + LOG_E("Wait for response notification failed: %d", result); + return result; + } + + return MC_DRV_OK; +} + +/** @} */ diff --git a/mobicore/daemon/Registry/Android.mk b/mobicore/daemon/Registry/Android.mk new file mode 100644 index 0000000..af396f7 --- /dev/null +++ b/mobicore/daemon/Registry/Android.mk @@ -0,0 +1,72 @@ +# ============================================================================= +# +# Module: libMcRegistry.a - MobiCore driver registry +# +# ============================================================================= + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libMcRegistry + +# Prevent not-yet-used functions of being ignored by linker +LOCAL_LDLIBS := -Wl,-whole-archive + +LOCAL_C_INCLUDES += bionic \ + external/stlport/stlport + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(LOCAL_PATH)/Public\ + $(MY_CLIENTLIB_PATH)/public\ + $(COMP_PATH_MobiCore)/inc + +# Add new source files here +LOCAL_SRC_FILES += Registry.cpp + +# Header files for components including this module +LOCAL_EXPORT_C_INCLUDES +=\ + $(LOCAL_PATH)/Public\ + $(MY_CLIENTLIB_PATH)/public + +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_STATIC_LIBRARY) + +################################################## +## Shared Object +################################################## +include $(CLEAR_VARS) + +LOCAL_MODULE := libMcRegistry +LOCAL_MODULE_TAGS := eng +LOCAL_PRELINK_MODULE := false + +# Prevent not-yet-used functions of being ignored by linker +LOCAL_LDLIBS := -Wl,-whole-archive + +LOCAL_C_INCLUDES += bionic \ + external/stlport/stlport + +# Add new folders with header files here +LOCAL_C_INCLUDES +=\ + $(LOCAL_PATH)/Public\ + $(MY_CLIENTLIB_PATH)/public\ + $(COMP_PATH_MobiCore)/inc + +# Add new source files here +LOCAL_SRC_FILES += Registry.cpp + +# Header files for components including this module +LOCAL_EXPORT_C_INCLUDES +=\ + $(LOCAL_PATH)/Public\ + $(MY_CLIENTLIB_PATH)/public + +LOCAL_STATIC_LIBRARIES = libstlport_static +LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions + +include $(COMP_PATH_Logwrapper)/Android.mk + +include $(BUILD_SHARED_LIBRARY) diff --git a/mobicore/daemon/Registry/Public/MobiCoreRegistry.h b/mobicore/daemon/Registry/Public/MobiCoreRegistry.h new file mode 100644 index 0000000..96ca810 --- /dev/null +++ b/mobicore/daemon/Registry/Public/MobiCoreRegistry.h @@ -0,0 +1,178 @@ +/** + * @addtogroup MCD_MCDIMPL_DAEMON_REG + * @{ + * G&D MobiCore Registry + * + * @file + * Mobicore Driver Registry. + * + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 MOBICORE_REGISTRY_H_ +#define MOBICORE_REGISTRY_H_ + +#include "MobiCoreDriverApi.h" +#include "mcContainer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Registry object. + */ +typedef struct { + uint32_t len; + uint8_t value[]; +} regObject_t; + +/** Maximum size of a trustlet in bytes. */ +#define MAX_TL_SIZE (1 * 1024 * 1024) + +//----------------------------------------------------------------- + +/** Stores an authentication token in registry. + * @param so Authentication token secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryStoreAuthToken(const mcSoAuthTokenCont_t *so); + +/** Reads an authentication token from registry. + * @param[out] so Authentication token secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryReadAuthToken(mcSoAuthTokenCont_t *so); + +/** Deletes the authentication token secure object from the registry. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryDeleteAuthToken(void); + +/** Stores a root container secure object in the registry. + * @param so Root container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryStoreRoot(const mcSoRootCont_t *so); + +/** Reads a root container secure object from the registry. + * @param[out] so Root container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryReadRoot(mcSoRootCont_t *so); + +/** Stores a service provider container secure object in the registry. + * @param spid Service provider ID. + * @param so Service provider container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryStoreSp(mcSpid_t spid, const mcSoSpCont_t *so); + +/** Reads a service provider container secure object from the registry. + * @param spid Service provider ID. + * @param[out] so Service provider container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryReadSp(mcSpid_t spid, mcSoSpCont_t *so); + +/** Deletes a service provider recursively, including all trustlets and + * data. + * @param spid Service provider ID. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryCleanupSp(mcSpid_t spid); + +/** Stores a trustlet container secure object in the registry. + * @param uuid Trustlet UUID. + * @param so Trustlet container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSoTltCont_t *so); + +/** Reads a trustlet container secure object from the registry. + * @param uuid Trustlet UUID. + * @param[out] so Trustlet container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, mcSoTltCont_t *so); + +/** Deletes a trustlet container secure object and all of its associated data. + * @param uuid Trustlet UUID. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid); + +/** Stores a data container secure object in the registry. + * @param so Data container secure object. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryStoreData(const mcSoDataCont_t *so); + +/** Reads a data container secure object from the registry. + * @param context (service provider = 0; trustlet = 1). + * @param cid Service provider or UUID. + * @param pid Personalization data identifier. + * @param[out] so Data container secure object. + * @param maxLen Maximum size (in bytes) of the destination buffer (so). + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryReadData( + uint32_t context, + const mcCid_t *cid, + mcPid_t pid, + mcSoDataCont_t *so, + uint32_t maxLen +); + +/** Deletes the root container and all of its associated service provider + * containers. + * @return MC_DRV_OK if successful, otherwise error code. + */ +mcResult_t mcRegistryCleanupRoot(void); + +/** Returns a registry object for a given service. + * @param uuid service UUID + * @return Registry object. + * @note It is the responsibility of the caller to free the registry object + * allocated by this function. + */ +regObject_t *mcRegistryGetServiceBlob(const mcUuid_t *uuid); + +/** Returns a registry object for a given service. + * @param driverFilename driver filename + * @return Registry object. + * @note It is the responsibility of the caller to free the registry object + * allocated by this function. + */ +regObject_t *mcRegistryGetDriverBlob(const char *driverFilename); + +#ifdef __cplusplus +} +#endif + +#endif // MOBICORE_REGISTRY_H_ + +/** @} */ diff --git a/mobicore/daemon/Registry/Registry.cpp b/mobicore/daemon/Registry/Registry.cpp new file mode 100644 index 0000000..4d7fb8d --- /dev/null +++ b/mobicore/daemon/Registry/Registry.cpp @@ -0,0 +1,898 @@ +/** Mobicore Driver Registry. + * + * Implements the MobiCore driver registry which maintains trustlets. + * + * @file + * @ingroup MCD_MCDIMPL_DAEMON_REG + * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "MobiCoreRegistry.h" +#include <stdlib.h> +#include <dirent.h> +#include <fstream> +#include <sys/stat.h> +#include <assert.h> +#include <string> +#include <cstring> +#include <cstddef> +#include "mcLoadFormat.h" +#include "mcSpid.h" +#include "mcVersionHelper.h" + +#define LOG_TAG "McDaemon" +#include "log.h" + +MC_CHECK_DATA_OBJECT_VERSION(MCLF, 2, 0); +MC_CHECK_DATA_OBJECT_VERSION(CONTAINER, 2, 0); + +// Asserts expression at compile-time (to be used within a function body). +#define ASSERT_STATIC(e) do { enum { assert_static__ = 1 / (e) }; } while (0) + +using namespace std; + +static const string MC_REGISTRY_DEFAULT_PATH = "/data/app/mcRegistry"; +static const string AUTH_TOKEN_FILE_NAME = "00000000.authtokcont"; +static const string ROOT_FILE_NAME = "00000000.rootcont"; +static const string SP_CONT_FILE_EXT = ".spcont"; +static const string TL_CONT_FILE_EXT = ".tlcont"; +static const string TL_BIN_FILE_EXT = ".tlbin"; +static const string DATA_CONT_FILE_EXT = ".datacont"; + +static const string ENV_MC_REGISTRY_PATH = "MC_REGISTRY_PATH"; +static const string ENV_MC_REGISTRY_FALLBACK_PATH = "MC_REGISTRY_FALLBACK_PATH"; +static const string ENV_MC_AUTH_TOKEN_PATH = "MC_AUTH_TOKEN_PATH"; + +static const string getRegistryPath(); +static const string getAuthTokenFilePath(); +static const string getRootContFilePath(); +static const string getSpDataPath(mcSpid_t spid); +static const string getSpContFilePath(mcSpid_t spid); +static const string getTlContFilePath(const mcUuid_t* uuid); +static const string getTlDataPath(const mcUuid_t* uuid); +static const string getTlDataFilePath(const mcUuid_t* uuid, mcPid_t pid); +static const string getTlBinFilePath(const mcUuid_t* uuid); + +static const string uint32ToString(mcSpid_t spid); +static const string byteArrayToString(const void* bytes, size_t elems); +static bool doesDirExist(const char* path); + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreAuthToken( + const mcSoAuthTokenCont_t *so +) { + if (NULL == so) { + LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if (CONT_TYPE_SOC != so->coSoc.type) { + LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& authTokenFilePath = getAuthTokenFilePath(); + LOG_I("store AuthToken: %s", authTokenFilePath.c_str()); + fstream fs(authTokenFilePath.c_str(), ios_base::out | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::beg); + fs.write((char *)so, sizeof(mcSoAuthTokenCont_t)); + fs.flush(); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadAuthToken( + mcSoAuthTokenCont_t *so +) { + if (NULL == so) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& authTokenFilePath = getAuthTokenFilePath(); + LOG_I("read AuthToken: %s", authTokenFilePath.c_str()); + fstream fs(authTokenFilePath.c_str(), ios_base::in | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::end); + int32_t filesize = fs.tellg(); + if (sizeof(mcSoAuthTokenCont_t) != filesize) { + fs.close(); + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fs.seekg(0, ios::beg); + fs.read((char *)so, sizeof(mcSoAuthTokenCont_t)); + fs.close(); + return MC_DRV_OK; +} + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryDeleteAuthToken( + void +) { + remove(getAuthTokenFilePath().c_str()); + // @TODO: is return to check ? + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreRoot( + const mcSoRootCont_t *so +) { + if (NULL == so) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if(CONT_TYPE_ROOT != so->cont.type) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& rootContFilePath = getRootContFilePath(); + LOG_I("store Root: %s", rootContFilePath.c_str()); + fstream fs(rootContFilePath.c_str(), ios_base::out | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::beg); + fs.write((char *)so, sizeof(mcSoRootCont_t)); + fs.flush(); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadRoot( + mcSoRootCont_t *so +) { + if (NULL == so) { + LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& rootContFilePath = getRootContFilePath(); + LOG_I("read Root: %s", rootContFilePath.c_str()); + fstream fs(rootContFilePath.c_str(), ios_base::in | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::end); + int32_t filesize = fs.tellg(); + if (sizeof(mcSoRootCont_t) != filesize) { + fs.close(); + LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fs.seekg(0, ios::beg); + fs.read((char *)so, sizeof(mcSoRootCont_t)); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreSp( + mcSpid_t spid, + const mcSoSpCont_t *so +) { + if ((0 == spid) || (NULL == so)) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if(CONT_TYPE_SP != so->cont.type) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& spContFilePath = getSpContFilePath(spid); + LOG_I("store SP: %s", spContFilePath.c_str()); + fstream fs(spContFilePath.c_str(), ios_base::out | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::beg); + fs.write((char *)so, sizeof(mcSoSpCont_t)); + fs.flush(); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadSp( + mcSpid_t spid, + mcSoSpCont_t *so +) { + if ((0 == spid) || (NULL == so)) { + LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& spContFilePath = getSpContFilePath(spid); + LOG_I("read SP: %s", spContFilePath.c_str()); + fstream fs(spContFilePath.c_str(), ios_base::in | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::end); + int32_t filesize = fs.tellg(); + if (sizeof(mcSoSpCont_t) != filesize) { + fs.close(); + LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fs.seekg(0, ios::beg); + fs.read((char *)so, sizeof(mcSoSpCont_t)); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreTrustletCon( + const mcUuid_t *uuid, + const mcSoTltCont_t *so +) { + if ((NULL == uuid) || (NULL == so)) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if(CONT_TYPE_TLCON != so->cont.type) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& tlContFilePath = getTlContFilePath(uuid); + LOG_I("store TLc: %s", tlContFilePath.c_str()); + fstream fs(tlContFilePath.c_str(), ios_base::out | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::beg); + fs.write((char *)so, sizeof(mcSoTltCont_t)); + fs.flush(); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadTrustletCon( + const mcUuid_t *uuid, + mcSoTltCont_t *so +) { + if ((NULL == uuid) || (NULL == so)) { + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string& tlContFilePath = getTlContFilePath(uuid); + LOG_I("read TLc: %s", tlContFilePath.c_str()); + fstream fs(tlContFilePath.c_str(), ios_base::in | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::end); + int32_t filesize = fs.tellg(); + if (sizeof(mcSoTltCont_t) != filesize) { + fs.close(); + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d. Size=%i, expected=%i", MC_DRV_ERR_OUT_OF_RESOURCES,filesize,sizeof(mcSoTltCont_t)); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fs.seekg(0, ios::beg); + fs.read((char *)so, sizeof(mcSoTltCont_t)); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreData( + const mcSoDataCont_t *so +) { + if (NULL == so) { + LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + string pathname, filename; + + switch (so->cont.type) { + case CONT_TYPE_SPDATA: + LOG_E("SPDATA not supported"); + return MC_DRV_ERR_INVALID_PARAMETER; + break; + case CONT_TYPE_TLDATA: + pathname = getTlDataPath(&so->cont.uuid); + filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid); + break; + default: + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + mkdir(pathname.c_str(), 0777); + + LOG_I("store DT: %s", filename.c_str()); + fstream fs(filename.c_str(), ios_base::out | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::beg); + fs.write((char *)so, MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen)); + fs.flush(); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadData( + uint32_t context, + const mcCid_t *cid, + mcPid_t pid, + mcSoDataCont_t *so, + uint32_t maxLen +) { + if ((NULL == cid) || (NULL == so)) { + LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + string filename; + switch (context) { + case 0: + LOG_E("SPDATA not supported"); + return MC_DRV_ERR_INVALID_PARAMETER; + break; + case 1: + filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid); + break; + default: + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + LOG_I("read DT: %s", filename.c_str()); + fstream fs(filename.c_str(), ios_base::in | ios_base::binary); + if (!fs) { + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + fs.seekg(0, ios::end); + uint32_t filesize = fs.tellg(); + if (maxLen < filesize) { + fs.close(); + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fs.seekg(0, ios::beg); + char* p = (char*) so; + fs.read(p, sizeof(mcSoHeader_t)); + p += sizeof(mcSoHeader_t); + fs.read(p, MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t)); + fs.close(); + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryCleanupTrustlet( + const mcUuid_t *uuid +) { + DIR *dp; + struct dirent *de; + int e; + + if (NULL == uuid) { + LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + string pathname = getTlDataPath(uuid); + if (NULL != (dp = opendir(pathname.c_str()))) { + while (NULL != (de = readdir(dp))) { + if (de->d_name[0] != '.') { + string dname = pathname + "/" + string (de->d_name); + LOG_I("delete DT: %s", dname.c_str()); + if (0 != (e = remove(dname.c_str()))) { + LOG_E("remove UUID-data %s failed! error: %d", dname.c_str(), e); + return MC_DRV_ERR_UNKNOWN; + } + } + } + LOG_I("delete dir: %s", pathname.c_str()); + if (0 != (e = rmdir(pathname.c_str()))) { + LOG_E("remove UUID-dir failed! errno: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + } + string tlBinFilePath = getTlBinFilePath(uuid); + LOG_I("delete Tlb: %s", tlBinFilePath.c_str()); + if (0 != (e = remove(tlBinFilePath.c_str()))) { + LOG_E("remove Tlb failed! errno: %d", e); +// return MC_DRV_ERR_UNKNOWN; // a trustlet-binary must not be present ! (registered but not usable) + } + string tlContFilePath = getTlContFilePath(uuid); + LOG_I("delete Tlc: %s", tlContFilePath.c_str()); + if (0 != (e = remove(tlContFilePath.c_str()))) { + LOG_E("remove Tlc failed! errno: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryCleanupSp( + mcSpid_t spid +) { + mcResult_t ret; + mcSoSpCont_t data; + uint32_t i; + DIR *dp; + struct dirent *de; + int e; + + if (0 == spid) { + LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + ret = mcRegistryReadSp(spid, &data); + if (MC_DRV_OK != ret) { + LOG_E("read SP->UUID aborted! Return code: %d", ret); + return ret; + } + for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) { + if (0 != strncmp((const char *)&(data.cont.children[i]), (const char *)&MC_UUID_FREE, sizeof(mcUuid_t))) { + ret = mcRegistryCleanupTrustlet(&(data.cont.children[i])); + } + } + if (MC_DRV_OK != ret) { + LOG_E("delete SP->UUID failed! Return code: %d", ret); + return ret; + } + string pathname = getSpDataPath(spid); + + if (NULL != (dp = opendir(pathname.c_str()))) { + while (NULL != (de = readdir(dp))) { + if (de->d_name[0] != '.') { + string dname = pathname + "/" + string (de->d_name); + LOG_I("delete DT: %s", dname.c_str()); + if (0 != (e = remove(dname.c_str()))) { + LOG_E("remove SPID-data %s failed! error: %d", dname.c_str(), e); + return MC_DRV_ERR_UNKNOWN; + } + } + } + LOG_I("delete dir: %s", pathname.c_str()); + if (0 != (e = rmdir(pathname.c_str()))) { + LOG_E("remove SPID-dir failed! error: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + } + string spContFilePath = getSpContFilePath(spid); + LOG_I("delete Sp: %s", spContFilePath.c_str()); + if (0 != (e = remove(spContFilePath.c_str()))) { + LOG_E("remove SP failed! error: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryCleanupRoot(void) { + mcResult_t ret; + mcSoRootCont_t data; + uint32_t i; + int e; + + ret = mcRegistryReadRoot(&data); + if (MC_DRV_OK != ret) { + LOG_E("read Root aborted! Return code: %d", ret); + return ret; + } + for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) { + mcSpid_t spid = data.cont.children[i]; + if (spid != MC_SPID_FREE) { + ret = mcRegistryCleanupSp(spid); + if (MC_DRV_OK != ret) { + LOG_E("Cleanup SP failed! Return code: %d", ret); + return ret; + } + } + } + + string rootContFilePath = getRootContFilePath(); + LOG_I("Delete root: %s", rootContFilePath.c_str()); + if (0 != (e = remove(rootContFilePath.c_str()))) { + LOG_E("Delete root failed! error: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +regObject_t *mcRegistryGetServiceBlob( + const mcUuid_t *uuid +) { + regObject_t* regobj = NULL; + + // Ensure that a UUID is provided. + if (NULL == uuid) { + LOG_E("mcRegistryGetServiceBlob() failed. No UUID given"); + return NULL; + } + + // Open service blob file. + string tlBinFilePath = getTlBinFilePath(uuid); + LOG_I("mcRegistryGetServiceBlob() Loading service: %s", tlBinFilePath.c_str()); + + ifstream fs(tlBinFilePath.c_str(), ios_base::binary); + if (!fs) { + LOG_E("mcRegistryGetServiceBlob() failed: cannot open %s", tlBinFilePath.c_str()); + return NULL; + } + + // Determine and check service blob size. + fs.seekg(0, ios::end); + int32_t tlSize = fs.tellg(); + fs.seekg(0, ios::beg); + if (MAX_TL_SIZE < tlSize) { + LOG_E("mcRegistryGetServiceBlob() failed: service blob too big: %d", tlSize); + return NULL; + } + + // Check TL magic value. + fs.seekg(offsetof(mclfIntro_t, magic), ios::beg); + uint32_t magic; + fs.read((char*)&magic, sizeof(magic)); + if (magic != MC_SERVICE_HEADER_MAGIC_BE) { + LOG_E("mcRegistryGetServiceBlob() failed: wrong header magic value: %d", magic); + return NULL; + } + + // Check header version. + fs.seekg(offsetof(mclfIntro_t, version), ios::beg); + uint32_t version; + fs.read((char*)&version, sizeof(version)); + + char* msg; + if (!checkVersionOkDataObjectMCLF(version, &msg)) { + LOG_E("mcRegistryGetDriverBlob() failed: Trustlet header incompatible with MobiCore interface version. Check your SDK version!"); + // msg is null for release version + LOG_E("%s", msg); + return NULL; + } + + // Get service type. + fs.seekg(offsetof(mclfHeaderV1_t, serviceType), ios::beg); + serviceType_t serviceType; + fs.read((char*)&serviceType, sizeof(serviceType)); + fs.seekg(0, ios::beg); + + LOG_I("mcRegistryGetServiceBlob() Service is of type: %d", serviceType); + + // If loadable driver or system trustlet. + if (SERVICE_TYPE_DRIVER == serviceType || SERVICE_TYPE_SYSTEM_TRUSTLET == serviceType) { + // Take trustlet blob 'as is'. + if (NULL == (regobj = (regObject_t*) (malloc(sizeof(regObject_t) + tlSize)))) { + LOG_E("mcRegistryGetServiceBlob() failed: Out of memory"); + return NULL; + } + regobj->len = tlSize; + fs.read((char *)regobj->value, tlSize); + fs.close(); + // If user trustlet. + } else if (SERVICE_TYPE_SP_TRUSTLET == serviceType) { + // Take trustlet blob and append root, sp, and tl container. + size_t regObjValueSize = tlSize + sizeof(mcSoContainerPath_t); + + // Prepare registry object. + if (NULL == (regobj = (regObject_t*) malloc(sizeof(regObject_t) + regObjValueSize))) { + LOG_E("mcRegistryGetServiceBlob() failed: Out of memory"); + return NULL; + } + regobj->len = regObjValueSize; + + // Read and fill in trustlet blob at beginning. + fs.read((char*)regobj->value, tlSize); + fs.close(); + + // Goto end of allocated space and fill in tl container, sp container, + // and root container from back to front. Final registry object value + // looks like this: + // + // +---------------------------+-----------+---------+---------+ + // | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont | + // +---------------------------+-----------+-------------------+ + // /------ Trustlet BLOB ------/ + // + // /------------------ regobj->header.len ---------------------/ + + uint8_t* p = regobj->value + regobj->len; + mcResult_t ret; + do { + char* msg; + + // Fill in TL container. + p -= sizeof(mcSoTltCont_t); + mcSoTltCont_t* soTlt = (mcSoTltCont_t*)p; + if (MC_DRV_OK != (ret = mcRegistryReadTrustletCon(uuid, soTlt))) { + break; + } + mcTltCont_t* tltCont = &soTlt->cont; + if (!checkVersionOkDataObjectCONTAINER(tltCont->version, &msg)) { + LOG_E("Tlt container %s", msg); + ret = MC_DRV_ERR_CONTAINER_VERSION; + break; + } + + // Fill in SP container. + mcSpid_t spid = tltCont->parent; + p -= sizeof(mcSoSpCont_t); + mcSoSpCont_t* soSp = (mcSoSpCont_t*)p; + if (MC_DRV_OK != (ret = mcRegistryReadSp(spid, soSp))) { + break; + } + mcSpCont_t* spCont = &soSp->cont; + if (!checkVersionOkDataObjectCONTAINER(spCont->version, &msg)) { + LOG_E("SP container %s", msg); + ret = MC_DRV_ERR_CONTAINER_VERSION; + break; + } + + // Fill in root container. + p -= sizeof(mcSoRootCont_t); + mcSoRootCont_t* soRoot = (mcSoRootCont_t*)p; + if (MC_DRV_OK != (ret = mcRegistryReadRoot(soRoot))) { + break; + } + mcRootCont_t* rootCont = &soRoot->cont; + if (!checkVersionOkDataObjectCONTAINER(rootCont->version, &msg)) { + LOG_E("Root container %s", msg); + ret = MC_DRV_ERR_CONTAINER_VERSION; + break; + } + + // Ensure order of elements in registry object value. + assert(p - tlSize - sizeof(regObject_t) == (uint8_t*)regobj); + } while (false); + + if (MC_DRV_OK != ret) { + LOG_E("mcRegistryGetServiceBlob() failed: Error code: %d", ret); + free(regobj); + return NULL; + } + // Any other service type. + } else { + LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", serviceType); + } + + return regobj; +} + +//------------------------------------------------------------------------------ +regObject_t *mcRegistryGetDriverBlob( + const char *driverFilename +) { + regObject_t* regobj = NULL; + + // Open service blob file. + ifstream fs(driverFilename, ios_base::binary); + if (!fs) { + LOG_E("mcRegistryGetDriverBlob() failed: cannot open %s", driverFilename); + return NULL; + } + + // Determine and check service blob size. + fs.seekg(0, ios::end); + int32_t tlSize = fs.tellg(); + fs.seekg(0, ios::beg); + if (MAX_TL_SIZE < tlSize) { + LOG_E("mcRegistryGetDriverBlob() failed: service blob too big: %d", tlSize); + return NULL; + } + + // Check TL magic value. + fs.seekg(offsetof(mclfIntro_t, magic), ios::beg); + uint32_t magic; + fs.read((char*)&magic, sizeof(magic)); + if (magic != MC_SERVICE_HEADER_MAGIC_BE) { + LOG_E("mcRegistryGetDriverBlob() failed: wrong header magic value: %d", magic); + return NULL; + } + + // Check header version. + fs.seekg(offsetof(mclfIntro_t, version), ios::beg); + uint32_t version; + fs.read((char*)&version, sizeof(version)); + + char* msg; + if (!checkVersionOkDataObjectMCLF(version, &msg)) { + LOG_E("mcRegistryGetDriverBlob() failed: Driver header incompatible with MobiCore interface version. Check your SDK version!"); + // msg is null for release version + LOG_E("%s", msg); + return NULL; + } + + // Get service type. + fs.seekg(offsetof(mclfHeaderV1_t, serviceType), ios::beg); + serviceType_t serviceType; + fs.read((char*)&serviceType, sizeof(serviceType)); + fs.seekg(0, ios::beg); + + LOG_I("mcRegistryGetDriverBlob() Service is of type: %d", serviceType); + + // If loadable driver or system trustlet. + if (SERVICE_TYPE_DRIVER == serviceType) { + // Take trustlet blob 'as is'. + if (NULL == (regobj = (regObject_t*) (malloc(sizeof(regObject_t) + tlSize)))) { + LOG_E("mcRegistryGetDriverBlob() failed: Out of memory"); + return NULL; + } + regobj->len = tlSize; + fs.read((char *)regobj->value, tlSize); + fs.close(); + // Otherwise we are not interested + } else { + LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", serviceType); + } + + return regobj; +} + +//------------------------------------------------------------------------------ +static const string getRegistryPath() { + const char* path; + string registryPath; + + // First, attempt to use regular registry environment variable. + path = getenv(ENV_MC_REGISTRY_PATH.c_str()); + if (doesDirExist(path)) { + LOG_I("getRegistryPath(): Using MC_REGISTRY_PATH %s", path); + registryPath = path; + } else { + // Second, attempt to use fallback registry environment variable. + path = getenv(ENV_MC_REGISTRY_FALLBACK_PATH.c_str()); + if (doesDirExist(path)) { + LOG_I("getRegistryPath(): Using MC_REGISTRY_FALLBACK_PATH %s", path); + registryPath = path; + } + } + + // As a last resort, use the default registry path. + if (registryPath.length() == 0) { + registryPath = MC_REGISTRY_DEFAULT_PATH; + LOG_I("getRegistryPath(): Using default registry path %s", registryPath.c_str()); + } + + assert(registryPath.length() != 0); + + return registryPath; +} + +//------------------------------------------------------------------------------ +static const string getAuthTokenFilePath() { + const char* path; + string authTokenPath; + + // First, attempt to use regular auth token path environment variable. + path = getenv(ENV_MC_AUTH_TOKEN_PATH.c_str()); + if (doesDirExist(path)) { + LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path); + authTokenPath = path; + } else { + authTokenPath = getRegistryPath(); + LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath.c_str()); + } + + return authTokenPath + "/" + AUTH_TOKEN_FILE_NAME; +} + +//------------------------------------------------------------------------------ +static const string getRootContFilePath() { + return getRegistryPath() + "/" + ROOT_FILE_NAME; +} + +//------------------------------------------------------------------------------ +static const string getSpDataPath(mcSpid_t spid) { + return getRegistryPath() + "/" + uint32ToString(spid); +} + +//------------------------------------------------------------------------------ +static const string getSpContFilePath(mcSpid_t spid) { + return getRegistryPath() + "/" + uint32ToString(spid) + SP_CONT_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static const string getTlContFilePath(const mcUuid_t* uuid) { + return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_CONT_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static const string getTlDataPath(const mcUuid_t* uuid) { + return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)); +} + +//------------------------------------------------------------------------------ +static const string getTlDataFilePath(const mcUuid_t* uuid, mcPid_t pid) { + return getTlDataPath(uuid) + "/" + uint32ToString(pid.data) + DATA_CONT_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static const string getTlBinFilePath(const mcUuid_t* uuid) { + return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static const string byteArrayToString(const void* bytes, size_t elems) { + char hx[elems * 2 + 1]; + + for (size_t i = 0; i < elems; i++) { + sprintf(&hx[i * 2], "%02x", ((uint8_t*)bytes)[i]); + } + return string(hx); +} + +//------------------------------------------------------------------------------ +static const string uint32ToString( + uint32_t value +) { + char hx[sizeof(uint32_t) * 2 + 1]; + uint32_t i; + + for (i = 0; i < (2 * sizeof(value)); i++) { + hx[i] = (value >> (28 - (i * 4))) & 0x0F; + if (hx[i] > 9) { + hx[i] = (hx[i] - 9) | 0x40; + } else { + hx[i] |= 0x30; + } + } + hx[i] = '\0'; + return string(hx); +} + +//------------------------------------------------------------------------------ +static bool doesDirExist(const char* path) { + struct stat ss; + if (path != NULL && stat(path, &ss) == 0 && S_ISDIR(ss.st_mode)) { + return true; + } + return false; +} + + +/** @} */ diff --git a/mobicore/daemon/buildTag.h b/mobicore/daemon/buildTag.h new file mode 100644 index 0000000..dc1d4b9 --- /dev/null +++ b/mobicore/daemon/buildTag.h @@ -0,0 +1 @@ +#define MOBICORE_COMPONENT_BUILD_TAG "*** SAMSUNG Exynos 5250 MC1.2 V002 release ###" diff --git a/mobicore/include/Public/mc_drv_module_api.h b/mobicore/include/Public/mc_drv_module_api.h new file mode 100644 index 0000000..8c52ed5 --- /dev/null +++ b/mobicore/include/Public/mc_drv_module_api.h @@ -0,0 +1,315 @@ +/** @addtogroup MCD_MCDIMPL_KMOD_API Mobicore Driver Module API + * @ingroup MCD_MCDIMPL_KMOD + * @{ + * Interface to Mobicore Driver Kernel Module. + * @file + * + * <h2>Introduction</h2> + * The MobiCore Driver Kernel Module is a Linux device driver, which represents + * the command proxy on the lowest layer to the secure world (Swd). Additional + * services like memory allocation via mmap and generation of a L2 tables for + * given virtual memory are also supported. IRQ functionallity receives + * information from the SWd in the non secure world (NWd). + * As customary the driver is handled as linux device driver with "open", + * "close" and "ioctl" commands. Access to the driver is possible after the + * device "/dev/mobicore" has been opened. + * The MobiCore Driver Kernel Module must be installed via + * "insmod mcDrvModule.ko". + * + * + * <h2>Version history</h2> + * <table class="customtab"> + * <tr><td width="100px"><b>Date</b></td><td width="80px"><b>Version</b></td> + * <td><b>Changes</b></td></tr> + * <tr><td>2010-05-25</td><td>0.1</td><td>Initial Release</td></tr> + * </table> + * + * <!-- Copyright Giesecke & Devrient GmbH 2010-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _MC_DRV_MODULEAPI_H_ +#define _MC_DRV_MODULEAPI_H_ + +#include "version.h" + +#define MC_DRV_MOD_DEVNODE "mobicore" +#define MC_DRV_MOD_DEVNODE_FULLPATH "/dev/" MC_DRV_MOD_DEVNODE + +/** + * Data exchange structure of the MC_DRV_MODULE_INIT ioctl command. + * INIT request data to SWD + */ +union mc_ioctl_init_params { + struct { + /** base address of mci buffer 4KB align */ + uint32_t base; + /** notification buffer start/length [16:16] [start, length] */ + uint32_t nq_offset; + /** length of notification queue */ + uint32_t nq_length; + /** mcp buffer start/length [16:16] [start, length] */ + uint32_t mcp_offset; + /** length of mcp buffer */ + uint32_t mcp_length; + } in; + struct { + /* nothing */ + } out; +}; + + +/** + * Data exchange structure of the MC_DRV_MODULE_INFO ioctl command. + * INFO request data to the SWD + */ +union mc_ioctl_info_params { + struct { + uint32_t ext_info_id; /**< extended info ID */ + } in; + struct { + uint32_t state; /**< state */ + uint32_t ext_info; /**< extended info */ + } out; +}; + +/** + * Mmap allocates and maps contiguous memory into a process. + * We use the third parameter, void *offset, to distinguish between some cases + * offset = MC_DRV_KMOD_MMAP_WSM usual operation, pages are registered in + * device structure and freed later. + * offset = MC_DRV_KMOD_MMAP_MCI get Instance of MCI, allocates or mmaps + * the MCI to daemon + * offset = MC_DRV_KMOD_MMAP_PERSISTENTWSM special operation, without + * registration of pages + * + * In mmap(), the offset specifies which of several device I/O pages is + * requested. Linux only transfers the page number, i.e. the upper 20 bits to + * kernel module. Therefore we define our special offsets as multiples of page + * size. + */ +enum mc_mmap_memtype { + MC_DRV_KMOD_MMAP_WSM = 0, + MC_DRV_KMOD_MMAP_MCI = 4096, + MC_DRV_KMOD_MMAP_PERSISTENTWSM = 8192 +}; + +struct mc_mmap_resp { + uint32_t handle; /**< WSN handle */ + uint32_t phys_addr; /**< physical address of WSM (or NULL) */ + bool is_reused; /**< if WSM memory was reused, or new allocated */ +}; + +/** + * Data exchange structure of the MC_DRV_KMOD_IOCTL_FREE ioctl command. + */ +union mc_ioctl_free_params { + struct { + uint32_t handle; /**< driver handle */ + uint32_t pid; /**< process id */ + } in; + struct { + /* nothing */ + } out; +}; + + +/** + * Data exchange structure of the MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2 command. + * + * Allocates a physical L2 table and maps the buffer into this page. + * Returns the physical address of the L2 table. + * The page alignment will be created and the appropriated pSize and pOffsetL2 + * will be modified to the used values. + */ +union mc_ioctl_app_reg_wsm_l2_params { + struct { + uint32_t buffer; /**< base address of the virtual address */ + uint32_t len; /**< size of the virtual address space */ + uint32_t pid; /**< process id */ + } in; + struct { + uint32_t handle; /**< driver handle for locked memory */ + uint32_t phys_wsm_l2_table; /* physical address of the L2 table */ + } out; +}; + + +/** + * Data exchange structure of the MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2 + * command. + */ +struct mc_ioctl_app_unreg_wsm_l2_params { + struct { + uint32_t handle; /**< driver handle for locked memory */ + uint32_t pid; /**< process id */ + } in; + struct { + /* nothing */ + } out; +}; + + +/** + * Data exchange structure of the MC_DRV_KMOD_IOCTL_DAEMON_LOCK_WSM_L2 command. + */ +struct mc_ioctl_daemon_lock_wsm_l2_params { + struct { + uint32_t handle; /**< driver handle for locked memory */ + } in; + struct { + uint32_t phys_wsm_l2_table; + } out; +}; + + +/** + * Data exchange structure of the MC_DRV_KMOD_IOCTL_DAEMON_UNLOCK_WSM_L2 + * command. + */ +struct mc_ioctl_daemon_unlock_wsm_l2_params { + struct { + uint32_t handle; /**< driver handle for locked memory */ + } in; + struct { + /* nothing */ + } out; +}; + +/** + * Data exchange structure of the MC_DRV_MODULE_FC_EXECUTE ioctl command. + * internal, unsupported + */ +union mc_ioctl_fc_execute_params { + struct { + /**< base address of mobicore binary */ + uint32_t phys_start_addr; + /**< length of DDR area */ + uint32_t length; + } in; + struct { + /* nothing */ + } out; +}; + +/** + * Data exchange structure of the MC_DRV_MODULE_GET_VERSION ioctl command. + */ +struct mc_ioctl_get_version_params { + struct { + uint32_t kernel_module_version; + } out; +}; + +/* @defgroup Mobicore_Driver_Kernel_Module_Interface IOCTL */ + + + + +/* TODO: use IOCTL macros like _IOWR. + * See Documentation/ioctl/ioctl-number.txt, + * Documentation/ioctl/ioctl-decoding.txt */ +/** + * defines for the ioctl mobicore driver module function call from user space. + */ +enum mc_kmod_ioctl { + + /* + * get detailed MobiCore Status + * internal, unsupported + */ + MC_DRV_KMOD_IOCTL_DUMP_STATUS = 200, + + /* + * initialize MobiCore + */ + MC_DRV_KMOD_IOCTL_FC_INIT = 201, + + /* + * get MobiCore status + */ + MC_DRV_KMOD_IOCTL_FC_INFO = 202, + + /** + * ioctl parameter to send the YIELD command to the SWD. + * Only possible in Privileged Mode. + * ioctl(fd, MC_DRV_MODULE_YIELD) + */ + MC_DRV_KMOD_IOCTL_FC_YIELD = 203, + /** + * ioctl parameter to send the NSIQ signal to the SWD. + * Only possible in Privileged Mode + * ioctl(fd, MC_DRV_MODULE_NSIQ) + */ + MC_DRV_KMOD_IOCTL_FC_NSIQ = 204, + /** + * ioctl parameter to tzbsp to start Mobicore binary from DDR. + * Only possible in Privileged Mode + * ioctl(fd, MC_DRV_KMOD_IOCTL_FC_EXECUTE) + * internal, unsupported + */ + MC_DRV_KMOD_IOCTL_FC_EXECUTE = 205, + + /** + * Free's memory which is formerly allocated by the driver's mmap + * command. The parameter must be this mmaped address. + * The internal instance data regarding to this address are deleted as + * well as each according memory page and its appropriated reserved bit + * is cleared (ClearPageReserved). + * Usage: ioctl(fd, MC_DRV_MODULE_FREE, &address) with address beeing of + * type long address + */ + MC_DRV_KMOD_IOCTL_FREE = 218, + + /** + * Creates a L2 Table of the given base address and the size of the + * data. + * Parameter: mc_ioctl_app_reg_wsm_l2_params + */ + MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2 = 220, + + /** + * Frees the L2 table created by a MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2 + * ioctl. + * Parameter: mc_ioctl_app_unreg_wsm_l2_params + */ + MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2 = 221, + + + /* TODO: comment this. */ + MC_DRV_KMOD_IOCTL_DAEMON_LOCK_WSM_L2 = 222, + MC_DRV_KMOD_IOCTL_DAEMON_UNLOCK_WSM_L2 = 223, + + /** + * Return kernel driver version. + * Parameter: mc_ioctl_get_version_params + */ + MC_DRV_KMOD_IOCTL_GET_VERSION = 224, +}; + + +#endif /* _MC_DRV_MODULEAPI_H_ */ +/** @} */ diff --git a/mobicore/include/Public/mc_kernel_api.h b/mobicore/include/Public/mc_kernel_api.h new file mode 100644 index 0000000..fdfc618 --- /dev/null +++ b/mobicore/include/Public/mc_kernel_api.h @@ -0,0 +1,100 @@ +/** @addtogroup MCD_MCDIMPL_KMOD_KAPI Mobicore Driver Module API inside Kernel. + * @ingroup MCD_MCDIMPL_KMOD + * @{ + * Interface to Mobicore Driver Kernel Module inside Kernel. + * @file + * + * Interface to be used by module MobiCoreKernelAPI. + * + * <!-- Copyright Giesecke & Devrient GmbH 2010-2012 --> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _MOBICORE_KERNELMODULE_API_H_ +#define _MOBICORE_KERNELMODULE_API_H_ + +struct mc_instance; + +/** + * Initialize a new mobicore API instance object + * + * @return Instance or NULL if no allocation was possible. + */ +struct mc_instance *mobicore_open( + void +); + +/** + * Release a mobicore instance object and all objects related to it + * @param instance instance + * @return 0 if Ok or -E ERROR + */ +int mobicore_release( + struct mc_instance *instance +); + +/** + * Free a WSM buffer allocated with mobicore_allocate_wsm + * @param instance + * @param handle handle of the buffer + * + * @return 0 if no error + * + */ +int mobicore_allocate_wsm( + struct mc_instance *instance, + unsigned long requested_size, + uint32_t *handle, + void **kernel_virt_addr, + void **phys_addr +); + +/** + * Free a WSM buffer allocated with mobicore_allocate_wsm + * @param instance + * @param handle handle of the buffer + * + * @return 0 if no error + * + */ +int mobicore_free( + struct mc_instance *instance, + uint32_t handle +); + +/** + * Map a virtual memory buffer structure to Mobicore + * @param instance + * @param addr address of the buffer(NB it must be kernel virtual!) + * @param len buffer length + * @param handle pointer to handle + * @param phys_wsm_l2_table pointer to physical L2 table(?) + * + * @return 0 if no error + * + */ +int mobicore_map_vmem( + struct mc_instance *instance, + void *addr, + uint32_t len, + uint32_t *handle, + void **phys_wsm_l2_table +); + +/** + * Unmap a virtual memory buffer from mobicore + * @param instance + * @param handle + * + * @return 0 if no error + * + */ +int mobicore_unmap_vmem( + struct mc_instance *instance, + uint32_t handle +); +#endif /* _MOBICORE_KERNELMODULE_API_H_ */ +/** @} */ diff --git a/mobicore/include/Public/version.h b/mobicore/include/Public/version.h new file mode 100644 index 0000000..9b2dbca --- /dev/null +++ b/mobicore/include/Public/version.h @@ -0,0 +1,36 @@ +/** @addtogroup MCD_MCDIMPL_KMOD + * @{ + * <!-- Copyright Giesecke & Devrient GmbH 2010-2012 --> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _MC_DRV_VERSION_H_ +#define _MC_DRV_VERSION_H_ + +#define MCDRVMODULEAPI_VERSION_MAJOR 0 +#define MCDRVMODULEAPI_VERSION_MINOR 1 + +#endif /* _MC_DRV_VERSION_H_ */ diff --git a/mobicore/provlib/Android.mk b/mobicore/provlib/Android.mk new file mode 100644 index 0000000..f66549c --- /dev/null +++ b/mobicore/provlib/Android.mk @@ -0,0 +1,12 @@ +# ============================================================================= +# +# Makefile pointing to all makefiles within the project. +# +# ============================================================================= + +PROJECT_PATH := $(call my-dir) + +$(call import-module,$(COMP_PATH_MobiCoreDriverLib)) + +# Include the Scripts +include $(PROJECT_PATH)/jni/Android.mk \ No newline at end of file diff --git a/mobicore/provlib/Application.mk b/mobicore/provlib/Application.mk new file mode 100644 index 0000000..91ea85c --- /dev/null +++ b/mobicore/provlib/Application.mk @@ -0,0 +1,21 @@ +# ============================================================================= +# +# Main build file defining the project modules and their global variables. +# +# ============================================================================= + +# Don't remove this - mandatory +APP_PROJECT_PATH := $(call my-dir) + +# Don't optimize for better debugging +APP_OPTIM := debug + +# Show all warnings +#APP_CFLAGS := -Wall + +MC_INCLUDE_DIR := $(COMP_PATH_MobiCore)/inc \ + $(COMP_PATH_MobiCore)/inc/TlCm \ + $(COMP_PATH_MobiCoreDriverLib)/Public +MC_DEBUG := _DEBUG +SYSTEM_LIB_DIR=/system/lib +GDM_PROVLIB_SHARED_LIBS=MobiCoreDriver \ No newline at end of file diff --git a/mobicore/provlib/buildTag.h b/mobicore/provlib/buildTag.h new file mode 100644 index 0000000..dc1d4b9 --- /dev/null +++ b/mobicore/provlib/buildTag.h @@ -0,0 +1 @@ +#define MOBICORE_COMPONENT_BUILD_TAG "*** SAMSUNG Exynos 5250 MC1.2 V002 release ###" diff --git a/mobicore/provlib/inc_private/gdmcdevicebinding.h b/mobicore/provlib/inc_private/gdmcdevicebinding.h new file mode 100644 index 0000000..c466a18 --- /dev/null +++ b/mobicore/provlib/inc_private/gdmcdevicebinding.h @@ -0,0 +1,70 @@ +#ifndef _INC_GDMCDEVICEBINDING_H +#define _INC_GDMCDEVICEBINDING_H + +#include <gdmcprovlib.h> +#include <gdmcprovprotocol.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _KSoCAuthSNTS KSoCAuthSNTS; + +struct _KSoCAuthSNTS +{ + mcSymmetricKey_t kSoCAuth; + _u64 serialNumber; + _u64 timeStamp; +}; + +#ifdef __cplusplus +} +#endif + +gderror GDMCComposeErrorMessage ( gdmcinst *inst, + gderror error, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size, + const char *pszmsg, ... ); + +gderror GDPROVAPI GDMCValidateProvMessage ( const _u8 *msg, + _u32 msgsize, + gdmc_msgheader **ppheader, + _u8 **ppbody, + gdmc_msgtrailer **pptrailer ); + +gderror GDPROVAPI GDMCHandleGetSUID ( gdmcinst *inst, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size ); + +gderror GDPROVAPI GDMCHandleGenAuthToken ( gdmcinst *inst, + gdmc_actmsg_req *req, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size ); + +gderror GDPROVAPI GDMCHandleValidateAuthToken ( gdmcinst *inst, + gdmc_so_authtok *validateSoAuthTok, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size ); + +#define ERRMSG_0001 "Unable to access memory region at %p (size: %u byte(s)) for READ." +#define ERRMSG_0002 "Unable to access memory region at %p (size: %u byte(s)) for WRITE." +#define ERRMSG_0003 "First in-message must be empty." +#define ERRMSG_0004 "Insufficient memory available." +#define ERRMSG_0005 "Message output buffer too small (%u but %u required to store message)." +#define ERRMSG_0006 "Message validation failed." +#define ERRMSG_0007 "Unexpected message received. Cannot evaluate message (ignored)." +#define ERRMSG_0008 "SUID of returned SO.AuthToken mismatches (my) internal SUID. SO.AuthToken discarded." +#define ERRMSG_0009 "Unable to generate SD.Receipt." +#define ERRMSG_000A "Expecting MC_GETSUID_REQ message from Production Station." +#define ERRMSG_000B "Unable to retrieve SUID from SoC (MobiCore)." +#define ERRMSG_000C "Unable to dump SO.AuthToken (MobiCore)." +#define ERRMSG_000D "Unable to retrieve SUID from SoC." +#define ERRMSG_000E "Unable to generate SO.AuthToken." +#define ERRMSG_000F "Validation of SO.AuthToken failed because no SO.AuthToken available." + +#endif // _INC_GDMCDEVICEBINDING_H diff --git a/mobicore/provlib/inc_private/gdmcinstance.h b/mobicore/provlib/inc_private/gdmcinstance.h new file mode 100644 index 0000000..0369f62 --- /dev/null +++ b/mobicore/provlib/inc_private/gdmcinstance.h @@ -0,0 +1,28 @@ +#ifndef _INC_GDMCINSTANCE_H +#define _INC_GDMCINSTANCE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _gdmcinst gdmcinst; + +#define GDMC_STATE_INITIAL ((_u32)0) ///< initial state +#define GDMC_STATE_HAVE_SUID ((_u32)1) ///< SUID retrieved from MobiCore +#define GDMC_STATE_HAVE_AUTHTOK ((_u32)2) ///< SO.AuthToken generated by MobiCore + +#define MAX_RESEND_TRIES 64 + +struct _gdmcinst +{ + _u32 state; ///< internal state of this instance + _u8 suid[SUID_LENGTH]; ///< SUID as retrieved from MobiCore + _u8 kSoCAuth[K_SOC_AUTH_LENGTH]; ///< the K.SoC.Auth delivered by KPH + gdmc_so_authtok authTok; ///< generated SO.AuthToken +}; + +#ifdef __cplusplus +} +#endif + +#endif // _INC_GDMCINSTANCE_H diff --git a/mobicore/provlib/inc_private/gdmcprovprotocol.h b/mobicore/provlib/inc_private/gdmcprovprotocol.h new file mode 100644 index 0000000..bd2686d --- /dev/null +++ b/mobicore/provlib/inc_private/gdmcprovprotocol.h @@ -0,0 +1,127 @@ +#ifndef _INC_GDMCPROVPROTOCOL_H_ +#define _INC_GDMCPROVPROTOCOL_H_ + +#include <gdmcprovlib.h> +#include <mobicore.h> + +#ifdef WIN32 + +#pragma warning ( disable : 4200 ) + +#pragma pack(push,1) + +#ifndef PACK_ATTR +#define PACK_ATTR +#endif // PACK_ATTR + +#else + +#ifndef PACK_ATTR +#define PACK_ATTR __attribute__((packed)) +#endif // PACK_ATTR + +#define IsBadReadPtr(p,c) (NULL==p) +#define IsBadWritePtr(p,c) (NULL==p) + +#endif + +#define AUTHENTICATION_TOKEN MC_SO_TYPE_REGULAR +#define CONTEXT_SYSTEM MC_SO_CONTEXT_TLT +#define SUID_LENGTH MC_SUID_LEN // 16 +#define K_SOC_AUTH_LENGTH MC_CONT_SYMMETRIC_KEY_SIZE // 32 +#define SHA256_HASH_LENGTH MC_SO_HASH_SIZE // 32 + +#undef AES_BLOCK_SIZE + +#define AES_BLOCK_SIZE MC_SO_ENCRYPT_BLOCK_SIZE // 16 + +typedef struct _gdmc_actmsg_req gdmc_actmsg_req; +typedef struct _gdmc_actmsg_resp gdmc_actmsg_resp; +typedef struct _gdmc_so_authtok gdmc_so_authtok; +typedef struct _gdmc_error_msg gdmc_error_msg; + +#define MC_GETSUID_REQ ((_u32)0x0100434D) +#define MC_GETSUID_RESP ((_u32)0x0200434D) +#define MC_GENAUTHTOKEN_REQ ((_u32)0x0300434D) +#define MC_GENAUTHTOKEN_RESP ((_u32)0x0400434D) +#define MC_VALIDATEAUTHTOKEN_REQ ((_u32)0x0500434D) +#define MC_ERROR ((_u32)0x0600434D) + +#ifndef CMP_GEN_AUTH_TOKEN_PSS_SIZE +#define CMP_GEN_AUTH_TOKEN_PSS_SIZE 256 +#endif + +/// G&D MobiCore error message +struct _gdmc_error_msg +{ + _u32 errorcode; ///< error code; you can safely cast this to gderror. + _u32 errmsg_length; ///< length of error message, may be 0 + _u8 errmsg[]; ///< error message (variable) +} PACK_ATTR; + +/// G&D MobiCore SO.AuthToken (authentication token) +struct _gdmc_so_authtok +{ + // Header + + _u32 type; + _u32 version; + _u32 context; + _u32 lifetime; // NEW2 -> ignore + _u32 producer_spid; // NEW2 -> ignore + _u8 producer_uuid[16]; // NEW2 -> ignore + _u32 plain_length; // OLD: 16 (SUID_LENGTH), NEW: 24 (two additional ints) + // NEW2: 28 (version is new) + _u32 encrypted_length; // here: K_SOC_AUTH_LENGTH + + // Plaintext Data + + _u32 contType; // NEW: contType_t = CONT_TYPE_SOC + _u32 contVersion; // NEW2: version + _u32 contState; // NEW: mcContainerState_t = MC_CONT_STATE_UNREGISTERED + _u8 suid[SUID_LENGTH]; + + // Encrypted Data (encrypted with K.Device.Ctxt) + + _u8 kSoCAuth[K_SOC_AUTH_LENGTH]; + _u8 md[SHA256_HASH_LENGTH]; + _u8 padding[AES_BLOCK_SIZE]; + +} PACK_ATTR; + +/// MobiCore activation message (request) +struct _gdmc_actmsg_req +{ + _u32 msg_type; ///< type of message = MC_CMP_CMD_GENERATE_AUTH_TOKEN + _u8 suid[SUID_LENGTH]; ///< SoC SUID + _u8 kSoCAuth[K_SOC_AUTH_LENGTH]; ///< K.SoC.Auth (AES-256bit key) + _u32 kid; ///< NEW: key id (currently: 1) + //_u8 md[SHA256_HASH_LENGTH]; ///< SHA-256 hash + _u8 dsig[CMP_GEN_AUTH_TOKEN_PSS_SIZE]; ///< new: hash substituted by PSS-SIG +} PACK_ATTR; + +/// MobiCore activation response +struct _gdmc_actmsg_resp +{ + _u32 msg_type; ///< type of message = MC_CMP_CMD_GENERATE_AUTH_TOKEN | 0x80000000 + _u32 retcode; ///< NEW: return code (status of operation) + gdmc_so_authtok authtok; ///< SO.AuthToken (124 bytes) +} PACK_ATTR; + +#ifdef WIN32 +#pragma pack(pop) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_u32 GDPROVAPI CalcCRC32 ( const _u8 *data, _u32 length ); + +void GDPROVAPI InitCRCTable ( void ); + +#ifdef __cplusplus +} +#endif + +#endif // _INC_GDMCPROVPROTOCOL_H_ diff --git a/mobicore/provlib/inc_private/mobicore.h b/mobicore/provlib/inc_private/mobicore.h new file mode 100644 index 0000000..1806f2b --- /dev/null +++ b/mobicore/provlib/inc_private/mobicore.h @@ -0,0 +1,174 @@ +/// @file mobicore.h +/// @author secunet AG (IKU) +/// +/// This file is a convenience header file (top-level) including +/// all MobiCore-related and platform-specific stuff. + +#ifndef _INC_MOBICORE_H_ +#define _INC_MOBICORE_H_ + +#if !defined(LINUX) && !defined(ANDROID_ARM) && !defined(WIN32) +#error "You MUST define either LINUX or ANDROID_ARM or WIN32" +#endif + +// standard C stuff... + +#if defined(__cplusplus) && !defined(ANDROID_ARM) +#include <string> +#include <vector> +#include <map> +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> + +#ifdef LINUX +#include <safemem.h> +#endif + +#if defined(WIN32) && defined(_DEBUG) // enable memory leak detection +#define _CRTDBG_MAP_ALLOC +#define _CRTDBG_MAP_ALLOC_NEW +#include <windows.h> +#include <crtdbg.h> +#define MYDEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__) +#define new MYDEBUG_NEW +#endif + +#ifndef _NO_OPENSSL_INCLUDES + +// OpenSSL stuff... + +#include <openssl/rand.h> +#include <openssl/sha.h> +#include <openssl/aes.h> +#include <openssl/rsa.h> +#include <openssl/bn.h> +#include <openssl/objects.h> +#include <openssl/err.h> + +#endif + +#ifdef WIN32 + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#pragma pack(push,4) + +#pragma warning ( disable : 4200 4996 ) + +#define GDPUBLIC +#define GDAPI __fastcall +#define PACK_ATTR +#define likely(cond) cond +#define unlikely(cond) cond + +#define bad_read_ptr(_p,_c) IsBadReadPtr((const void *)(_p),(UINT_PTR)(_c)) +#define bad_write_ptr(_p,_c) IsBadWritePtr((void *)(_p),(UINT_PTR)(_c)) + +#define PATH_SEPARATOR "\\" +#define PATH_SEP_CHAR '\\' +#define DYNLIB_PREFIX "" +#define DYNLIB_EXTENSION ".dll" + +#else + +#define GDPUBLIC __attribute__((visibility("default"))) +#define GDAPI +#define PACK_ATTR __attribute__((packed)) +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) + +#define bad_read_ptr(_p,_c) (NULL==(_p)) +#define bad_write_ptr(_p,_c) (NULL==(_p)) + +#define PATH_SEPARATOR "/" +#define PATH_SEP_CHAR '/' +#define DYNLIB_PREFIX "lib" +#define DYNLIB_EXTENSION ".so" + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <pthread.h> +#include <errno.h> +#include <time.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sched.h> +#include <dlfcn.h> +#include <signal.h> +#include <ctype.h> +#ifndef LINUX +#include <android/log.h> +#else +#include <syslog.h> +#endif + +#endif + +#include <stdbool.h> +#include <stdint.h> + +// MobiCore stuff... + +#ifdef WIN32 +#undef UUID +#undef uuid_t +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include <MobiCoreDriverApi.h> +#include <mcContainer.h> +#include <tlCmApi.h> +#include <tlCmUuid.h> +#include <mcVersionHelper.h> +#include <mcVersionInfo.h> + +enum _mcAuthState +{ + AUTH_NONE = 0, + AUTH_SOC, + AUTH_ROOT, + AUTH_SP +}; + +typedef enum _mcAuthState mcAuthState; + +#ifdef __cplusplus +} +#endif + +#ifdef WIN32 +#pragma pack(pop) +#endif + +#include <MobiCoreRegistry.h> + +#define IS_VALID_SPID(_x) ((0xFFFFFFFF!=(_x)) && (0xFFFFFFFE!=(_x))) +#define IS_VALID_ROOTID(_x) IS_VALID_SPID(_x) +#define IS_VALID_UUID(_x) ( ((_x).value[ 0]!=0xFF) && ((_x).value[ 1]!=0xFF) &&\ + ((_x).value[ 2]!=0xFF) && ((_x).value[ 3]!=0xFF) &&\ + ((_x).value[ 4]!=0xFF) && ((_x).value[ 5]!=0xFF) &&\ + ((_x).value[ 6]!=0xFF) && ((_x).value[ 7]!=0xFF) &&\ + ((_x).value[ 8]!=0xFF) && ((_x).value[ 9]!=0xFF) &&\ + ((_x).value[10]!=0xFF) && ((_x).value[11]!=0xFF) &&\ + ((_x).value[12]!=0xFF) && ((_x).value[13]!=0xFF) &&\ + ((_x).value[14]!=0xFF) && ((_x).value[15]!=0xFF) && ((_x).value[15]!=0xFE) ) + +#define MC_SO_PLAIN_SIZE(_struct) offsetof(_struct,co) +#define MC_SO_ENC_SIZE(_struct) sizeof(_struct.co) + +#endif // _INC_MOBICORE_H_ + diff --git a/mobicore/provlib/inc_public/gdmcprovlib.h b/mobicore/provlib/inc_public/gdmcprovlib.h new file mode 100644 index 0000000..71196ca --- /dev/null +++ b/mobicore/provlib/inc_public/gdmcprovlib.h @@ -0,0 +1,424 @@ +/// +/// @file gdmcprovlib.h +/// @author Giesecke & Devrient GmbH, Munich, Germany +/// +/// This header file declares simple data types and functions +/// comprising the G&D Provisioning API. +/// + +#ifndef _INC_GDPROVLIB_H_ +#define _INC_GDPROVLIB_H_ + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Check defines (macros)... + +#if !defined(WIN32) && !defined(LINUX) && !defined(ARM) +#error "You MUST define one of WIN32, LINUX, and ARM (platform)." +#endif + +#if !defined(_32BIT) && !defined(_64BIT) +#error "You MUST define either _32BIT or _64BIT." +#endif + +#if !defined(_LENDIAN) && !defined(_BENDIAN) +#error "You MUST define either _LENDIAN or _BENDIAN." +#endif + +// Declare simple signed and unsigned integer types + +/// a byte (octet), unsigned, 0..255 +typedef unsigned char _u8; + +/// a signed byte, -128..+127 +typedef signed char _i8; + +/// an unsigned 16bit integer, 0..65.535 +typedef unsigned short _u16; + +/// a signed 16bit integer, -32.768..+32.767 +typedef signed short _i16; + +/// an unsigned 32bit integer, 0..4.294.967.295 +typedef unsigned int _u32; + +/// a signed 32bit integer, -2.147.483.648..+2.147.483.647 +typedef signed int _i32; + +#ifdef WIN32 + +#define GDPUBLIC +#define GDPROVAPI __fastcall + +/// an unsigned 64bit integer, 0..18.446.744.073.709.551.615 +typedef unsigned __int64 _u64; + +/// a signed 64bit integer, -9.223.372.036.854.775.808..+9.223.372.036.854.775.807 +typedef signed __int64 _i64; + +#else + +#define GDPUBLIC __attribute__((visibility("default"))) +#define GDPROVAPI + +#ifdef _32BIT + +/// an unsigned 64bit integer, 0..18.446.744.073.709.551.615 +typedef unsigned long long _u64; + +/// a signed 64bit integer, -9.223.372.036.854.775.808..+9.223.372.036.854.775.807 +typedef signed long long _i64; + +#else // 64bit + +/// an unsigned 64bit integer, 0..18.446.744.073.709.551.615 +typedef unsigned long _u64; + +/// a signed 64bit integer, -9.223.372.036.854.775.808..+9.223.372.036.854.775.807 +typedef signed long _i64; + +#endif // _32BIT + +#endif // WIN32 + +////////////////////////////////////////////////////////////////////////////// + +/// G&D error codes, which are unsigned 32bit integers +typedef _u32 gderror; + +/// everything okay, operation successful +#define GDERROR_OK ((gderror)0x00000000) + +/// one or more of the input parameters to a function is/are invalid +#define GDERROR_PARAMETER ((gderror)0x00000001) + +/// connection problem occured, unable to establish a connection to the +/// Key Provisioning Host (KPH) +#define GDERROR_CONNECTION ((gderror)0x00000002) + +/// communication problem occured, unable to communicate with the +/// Key Provisioning Host (KPH) +#define GDERROR_COMMUNICATION ((gderror)0x00000003) + +/// GDMCProvShutdownLibrary was called without calling GDMCProvInitializeLibrary +#define GDERROR_NOT_INITIALIZED ((gderror)0x00000004) + +/// GDMCProvBeginProvisioning called but no more handles available +#define GDERROR_NO_MORE_HANDLES ((gderror)0x00000005) + +/// An unknown or invalid gdhandle was passed to a function +#define GDERROR_INVALID_HANDLE ((gderror)0x00000006) + +/// A so called structured exception occured, which is a severe error +/// (MS Windows only) +#define GDERROR_CPU_EXCEPTION ((gderror)0x00000007) + +/// Unable to retrieve the SUID of the SoC +#define GDERROR_CANT_GET_SUID ((gderror)0x00000008) + +/// Unable to generate the authentication token SO.AuthToken +#define GDERROR_CANT_BUILD_AUTHTOKEN ((gderror)0x00000009) + +/// Unable to dump the authentication token SO.AuthToken +#define GDERROR_CANT_DUMP_AUTHTOKEN ((gderror)0x0000000A) + +/// Unable to generate the receipt SD.Receipt +#define GDERROR_CANT_BUILD_RECEIPT ((gderror)0x0000000B) + +/// (only product version): Authentication KPH Connector <-> Key Provisioning Host (KPH) failed +#define GDERROR_AUTH_FAILED ((gderror)0x0000000C) + +/// validation of the device binding failed +#define GDERROR_VALIDATION_FAILURE ((gderror)0x0000000D) + +/// insufficient memory available +#define GDERROR_INSUFFICIENT_MEMORY ((gderror)0x0000000E) + +/// synchronization error occurred (thread concurrency) +#define GDERROR_SYNCHRONIZATION ((gderror)0x0000000F) + +/// the Key Provisioning Host (KPH) was not able to generate a random key (TRNG) +#define GDERROR_CANT_GENERATE_KEY ((gderror)0x00000010) + +/// the received cryptographic message format is erroneous +#define GDERROR_MESSAGE_FORMAT ((gderror)0x00000011) + +/// CRC32 checksum error +#define GDERROR_CRC32 ((gderror)0x00000012) + +/// Hash value (message digest) validation error +#define GDERROR_MESSAGE_DIGEST ((gderror)0x00000013) + +/// SUID comparison failed +#define GDERROR_SUID_MISMATCH ((gderror)0x00000014) + +/// the Device could not generate the authentication token SO.AuthToken for any reason +#define GDERROR_GENAUTHTOK_FAILED ((gderror)0x00000015) + +/// the Device could not wrap the authentication token in a secure object (SO) +#define GDERROR_WRAPOBJECT_FAILED ((gderror)0x00000016) + +/// the Device could not store SO.AuthToken for any reason +#define GDERROR_STORE_SO_FAILED ((gderror)0x00000017) + +/// the Key Provisioning Host (KPH) could not generate the receipt SD.Receipt for any reason +#define GDERROR_GENRECEIPT_FAILED ((gderror)0x00000018) + +/// the Key Provisioning Host (KPH) triggered a SO.AuthToken validation in the Device but no SO.AuthToken is available +#define GDERROR_NO_AUTHTOK_AVAILABLE ((gderror)0x00000019) + +/// the Device could not perform a read-back of the recently stored SO.AuthToken +#define GDERROR_AUTHTOK_RB_FAILED ((gderror)0x0000001A) + +/// the called API function is not implemented +#define GDERROR_NOT_IMPLEMENTED ((gderror)0x0000001B) + +/// generic (unspecified) error +#define GDERROR_UNKNOWN ((gderror)0x0000001C) + +/// MobiCore library initialization or cleanup failed +#define GDERROR_MOBICORE_LIBRARY ((gderror)0x0000001D) + +/// supplied (output) buffer too small +#define GDERROR_BUFFER_TOO_SMALL ((gderror)0x0000001E) + +/// cryptographic-related error occured, e.g. loading of RSA keys, etc. +#define GDERROR_CRYPTO_FAILURE ((gderror)0x0000001F) + +/// no error code: device binding completed successfully +#define GDERROR_PROVISIONING_DONE ((gderror)0x10000001) + +////////////////////////////////////////////////////////////////////////////// + +/// G&D handle (to one instance of the Provisioning API) +typedef _u32 gdhandle; + +/// Returns the current version of the Provisioning API. +/// +/// @return an unsigned 32bit integer consisting of four bytes aa|bb|cc|dd +/// with major version (aa), minor version (bb), patch level (cc), and +/// OEM (dd), which denotes the numeric ID of an OEM. +GDPUBLIC _u32 GDPROVAPI GDMCProvGetVersion ( void ); + +/// [PRODUCTION STATION ONLY] Formats an error message for an error code, +/// possibly containing more detailed information about the error. This function +/// is NOT implemented in the ARM version of the library because no diagnostic +/// messages can be displayed during the production. +/// +/// @param[in] provhandle the handle returned by GDMCProvBeginProvisioning; +/// can be null (0) to format a message for a global +/// error code (not context-specific) +/// @param[in] errorcode the G&D error code +/// @param[in/out] msgbuf pointer to buffer receiving the UTF-8 encoded +/// error message (in), buffer filled with error +/// message (out) +/// @param[in/out] size size of buffer pointed to by msgbuf specified +/// as wide characters (in), number of wide +/// characters copied into msgbuf (out) +/// +/// @return result code (e.g. buffer too small) +GDPUBLIC gderror GDPROVAPI GDMCProvFormatErrorMessage ( gdhandle provhandle, + gderror errorcode, + char *msgbuf, + _u32 *size ); + +/// Initializes the G&D Provisioning API (library) globally. If called +/// by the Production Software Station, then a TLS-secured channel to +/// the Key Provisioning Host (KPH) is established. +/// In a multithreaded environment, this function has to be called from +/// the primary thread (LWP 0). +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvInitializeLibrary ( void ); + +/// Performs a global shutdown of the G&D Provisioning API (library). +/// After this call, all resources are cleaned up and all handles are +/// closed. No functions except for GDMCProvInitializeLibrary may be +/// called anymore. +/// In a multithread environment, this function has to be called from +/// the primary thread (LWP 0). +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvShutdownLibrary ( void ); + +/// Creates one instance of the key provisioning (aka "device binding") +/// +/// @param[in/out] provhandle pointer to memory location receiving the +/// handle (in), the handle or 0 (out) +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvBeginProvisioning ( gdhandle *provhandle ); + +/// Destroys one instance of the key provisioning (aka "device binding") +/// +/// @param[in] provhandle the handle returned by GDMCProvBeginProvisioning +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvEndProvisioning ( gdhandle provhandle ); + +/// Executes one provisioning step of the full sequence. The caller has to +/// call this function in a loop until either an error is reported or the +/// error code GDERROR_PROVISIONING_DONE is returned (meaning successful +/// provisioning). Please refer to the MobiCore Provisioning API documentation +/// for details. +/// +/// @param[in] provhandle the handle returned by +/// GDMCProvBeginProvisioning +/// @param[in] msgin pointer to buffer containing the +/// input message; may be NULL if no message +/// available +/// @param[in] msgin_size size of buffer pointed to by msgin in bytes +/// @param[in/out] msgout pointer to buffer receiving the output +/// message (in); output message (out) +/// @param[in/out] msgout_size size of buffer pointed to by msgout in +/// bytes (in); number of bytes copied to msgout +/// (out) +/// +/// @return G&D error code; GDERROR_PROVISIONING_DONE +/// if provisioning successfully completed. +GDPUBLIC gderror GDPROVAPI GDMCProvExecuteProvisioningStep ( + gdhandle provhandle, + const _u8 *msgin, + _u32 msgin_size, + _u8 *msgout, + _u32 *msgout_size ); + +/// [PRODUCTION STATION ONLY] Convenience function to format an SD.Receipt +/// +/// @param[in] receipt pointer to buffer containing the +/// binary SD.Receipt +/// @param[in] receipt_size size of binary data pointed to by +/// receipt in bytes +/// @param[in/out] fmt_receipt pointer to buffer receiving the receipt as +/// a BASE64-encoded string (in); the string (out) +/// @param[in/out] fmt_receipt_size size of buffer pointed to by fmt_receipt in +/// bytes (in); number of bytes copied to +/// fmt_receipt (out) +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvFormatReceipt ( + const _u8 *receipt, + _u32 receipt_size, + _u8 *fmt_receipt, + _u32 *fmt_receipt_size ); + +/// [PRODUCTION STATION ONLY] Convenience function to query the SUID of +/// the currently provisioned device (e.g. can be used as primary key in +/// a production database) +/// +/// @param[in] provhandle the handle returned by +/// GDMCProvBeginProvisioning +/// @param[in/out] suid pointer to buffer (16 octets, in) receiving the +/// SUID of the current mobile device (out) +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvGetSUID ( + gdhandle provhandle, + _u8 *suid ); + +/// [DEVICE ONLY] Callback function called by the Provisioning API when +/// GDMCProvExecuteProvisioningStep is executed in the Device. This function +/// shall store the authentication token SO.AuthToken in a secure location. +/// +/// @param[in] authtok pointer to buffer containing SO.AuthToken +/// @param[in] authtok_size size of buffer pointed to be authtok; +/// shall be 124 octets +/// +/// @return G&D error code +typedef gderror (*authtok_writecb)( const _u8 *authtok, + _u32 authtok_size ); + +/// [DEVICE ONLY] Callback function called by the Provisioning API when +/// GDMCProvExecuteValidationStep is executed in the Device. This function +/// shall perform a read-back of the stored authentication token SO.AuthToken +/// +/// @param[in/out] authtok pointer to buffer receiving SO.AuthToken +/// (in); buffer filled with SO.AuthToken (out) +/// @param[in/out] authtok_size size of buffer pointed to be authtok (in); +/// number of bytes copied to authtok (out); +/// shall be 124 octets +/// +/// @return G&D error code +typedef gderror (*authtok_readcb)( _u8 *authtok, + _u32 *authtok_size ); + +/// [DEVICE ONLY] The OEM must provide two hook functions (callbacks) for the +/// reading and writing of the authentication token SO.AuthToken in the device. +/// +/// @param[in] writefunc callback function called by the Provisioning API +/// when an authentication token SO.AuthToken has to be +/// stored +/// @param[in] readfunc callback function called by the Provisioning API +/// when an authentication token SO.AuthToken has to be +/// read back (for validation purposes) +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvSetAuthTokenCallbacks ( + authtok_writecb writefunc, + authtok_readcb readfunc ); + +/// [PRODUCTION STATION ONLY] The configuration of the provisioning library +/// can be patched into the library binary file. If the OEM decided to perform +/// the configuration e.g. by providing the configuration information via the +/// production database, then this function can be called to configure the +/// provisioning library. +/// +/// @param[in] config_string a zero-terminated configuration string containing +/// the entire configuration information in a format +/// that will be defined by G&D; the exact format of +/// this configuration information can be OEM-specific +/// and will be specified in a separate document +/// +/// @return G&D error code +GDPUBLIC gderror GDPROVAPI GDMCProvSetConfigurationString ( + const char *config_string ); + +////////////////////////////////////////////////////////////////////////////// +// Declaration of message header and trailer +////////////////////////////////////////////////////////////////////////////// + +#ifdef WIN32 + +#pragma warning ( disable : 4200 ) + +#pragma pack(push,1) + +#define PACK_ATTR + +#else // Linux + +#define PACK_ATTR __attribute__((packed)) + +#endif + +typedef struct _gdmc_msgheader gdmc_msgheader; +typedef struct _gdmc_msgtrailer gdmc_msgtrailer; + +/// the G&D MobiCore message header +struct _gdmc_msgheader +{ + _u32 msg_type; ///< message type + _u32 body_size; ///< size of body (may be 0) +} PACK_ATTR; + +/// the G&D MobiCore message trailer +struct _gdmc_msgtrailer +{ + _u32 magic; /// message type (one's complement) + _u32 crc32; /// CRC32 checksum +} PACK_ATTR; + +#ifdef WIN32 +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _INC_GDPROVLIB_H_ + diff --git a/mobicore/provlib/jni/Android.mk b/mobicore/provlib/jni/Android.mk new file mode 100644 index 0000000..34971ab --- /dev/null +++ b/mobicore/provlib/jni/Android.mk @@ -0,0 +1,36 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := gdmcprov +LOCAL_MODULE_TAGS := eng + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc_private \ + $(LOCAL_PATH)/../inc_public \ + $(MC_INCLUDE_DIR) + +LOCAL_SRC_FILES := ../src/gdmcprovlib.cpp \ + ../src/crc32.c \ + ../src/mobicore.c \ + ../src/gdmcdevicebinding.cpp + +LOCAL_CFLAGS := -O2 -Wall -fomit-frame-pointer -DANDROID_ARM -DARM -D_LENDIAN -D_32BIT \ + -fvisibility=hidden -I$(OPENSSL_INC_DIR) \ + -DGDMCPROVLIB_VERSION=0x01000001 -D$(MC_DEBUG) \ + -D_NO_OPENSSL_INCLUDES + +LOCAL_CXXFLAGS := -O2 -Wall -fomit-frame-pointer -DANDROID_ARM -DARM -D_LENDIAN -D_32BIT \ + -fvisibility-inlines-hidden -fvisibility=hidden \ + -DGDMCPROVLIB_VERSION=0x01000001 -D$(MC_DEBUG) + +LOCAL_CPPFLAGS := -O2 -Wall -fomit-frame-pointer -DANDROID_ARM -DARM -D_LENDIAN -D_32BIT \ + -fvisibility-inlines-hidden -fvisibility=hidden \ + -DGDMCPROVLIB_VERSION=0x01000001 -D$(MC_DEBUG) + +LOCAL_LDFLAGS := -Wl,-rpath-link,$(SYSTEM_LIB_DIR) \ + -L$(SYSTEM_LIB_DIR) + +LOCAL_SHARED_LIBRARIES := $(GDM_PROVLIB_SHARED_LIBS) + +include $(BUILD_SHARED_LIBRARY) + diff --git a/mobicore/provlib/src/crc32.c b/mobicore/provlib/src/crc32.c new file mode 100644 index 0000000..37ac0c6 --- /dev/null +++ b/mobicore/provlib/src/crc32.c @@ -0,0 +1,49 @@ +#include <gdmcprovlib.h> +#include <string.h> + +static _u32 crctable[256]; + +_u32 GDPROVAPI CalcCRC32 ( const _u8 *data, _u32 length ) +{ + _u32 crc = 0xFFFFFFFF; + + while (length--) + crc = (crc>>8) ^ crctable[(crc&0xFF) ^ *data++]; + + return crc ^ 0xFFFFFFFF; +} + +static _u32 GDPROVAPI reflect ( _u32 refl, _u8 c ) +{ + int i; + _u32 value = 0; + + // Swap bit 0 for bit 7, bit 1 For bit 6, etc.... + for (i = 1; i < (c + 1); i++) + { + if (refl & 1) + value |= (1 << (c - i)); + refl >>= 1; + } + + return value; +} + +void GDPROVAPI InitCRCTable ( void ) +{ + int i,j; + + memset(crctable,0,sizeof(crctable)); + + for (i = 0; i <= 0xFF; i++) + { + crctable[i] = reflect(i, 8) << 24; + + for (j = 0; j < 8; j++) + crctable[i] = (crctable[i] << 1) + ^ ((crctable[i] & (1 << 31)) ? 0x04C11DB7 : 0); + + crctable[i] = reflect(crctable[i], 32); + } +} + diff --git a/mobicore/provlib/src/gdmcdevicebinding.cpp b/mobicore/provlib/src/gdmcdevicebinding.cpp new file mode 100644 index 0000000..27cd667 --- /dev/null +++ b/mobicore/provlib/src/gdmcdevicebinding.cpp @@ -0,0 +1,458 @@ +/// +/// @file gdmcdevicebinding.cpp +/// @author Giesecke & Devrient GmbH, Munich, Germany +/// +/// Implementation of the (internal) device binding +/// + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <gdmcprovlib.h> +#include <gdmcprovprotocol.h> +#include <gdmcinstance.h> + +extern "C" +{ + gderror MCGetSUID ( _u8 *suid ); + + gderror MCGenerateAuthToken ( gdmcinst *inst, const gdmc_actmsg_req *req, gdmc_so_authtok *authtok ); +} + +////////////////////////////////////////////////////////////////////////////// +// MS Windows-specific includes +////////////////////////////////////////////////////////////////////////////// + +#if defined(WIN32) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#ifdef _DEBUG +#include <crtdbg.h> +#endif + +////////////////////////////////////////////////////////////////////////////// +// Linux-specific includes +////////////////////////////////////////////////////////////////////////////// + +#elif defined(LINUX) + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <pthread.h> +#include <syslog.h> +#include <errno.h> +#include <time.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +////////////////////////////////////////////////////////////////////////////// +// ARM-specific includes +////////////////////////////////////////////////////////////////////////////// + +#else // ARM + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <pthread.h> +#include <errno.h> +#include <time.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#endif + +#include <gdmcprovprotocol.h> +#include <gdmcinstance.h> +#include <gdmcdevicebinding.h> + +#define MAX_MSGSIZE 4096 + +extern authtok_writecb g_authtok_writecb; +extern authtok_readcb g_authtok_readcb; + +#ifdef WIN32 +#define vsnprintf _vsnprintf + +#pragma warning ( disable : 4996 ) + +#endif + +gderror GDMCComposeErrorMessage ( gdmcinst *inst, gderror error, _u8 *msgout, _u32 *msgout_size, _u32 initial_msgout_size, const char *pszmsg, ... ) +{ + _u32 msgsize = 0; + gdmc_msgheader *header; + gdmc_error_msg *body; + gdmc_msgtrailer *trailer; + va_list ap; + char *buffer = NULL; + _u32 errmsgsize = 0; + _u32 errmsgsize_aligned; + + if (NULL!=pszmsg) + { + buffer = (char*)malloc(MAX_MSGSIZE); + + if (NULL!=buffer) + { + memset(buffer,0,MAX_MSGSIZE); + va_start(ap,pszmsg); + vsnprintf(buffer,MAX_MSGSIZE,pszmsg,ap); + va_end(ap); + + errmsgsize = ((_u32)strlen(buffer))+1; + if (1==errmsgsize) + errmsgsize--; // if empty message, then do not send anything + } + } + + errmsgsize_aligned = (errmsgsize+3)&(~3); + + // compose MC_ERROR message + + msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)+errmsgsize_aligned+sizeof(gdmc_msgtrailer); + + if (msgsize>initial_msgout_size) + { + if (NULL!=buffer) + free(buffer); + return GDERROR_BUFFER_TOO_SMALL; + } + + header = (gdmc_msgheader*)msgout; + body = (gdmc_error_msg*)(msgout+sizeof(gdmc_msgheader)); + trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)+errmsgsize_aligned); + + header->msg_type = MC_ERROR; + header->body_size = sizeof(gdmc_error_msg)+errmsgsize; + + body->errorcode = error; + body->errmsg_length = errmsgsize_aligned; + + if ((NULL!=buffer) && (0!=errmsgsize)) + { + memset(body->errmsg,0,errmsgsize_aligned); + memcpy(body->errmsg,buffer,errmsgsize); + } + + if (NULL!=buffer) + free(buffer); + + trailer->magic = ~MC_ERROR; + trailer->crc32 = CalcCRC32(msgout,msgsize-sizeof(_u32)); + + *msgout_size = msgsize; + + return GDERROR_OK; +} + +gderror GDPROVAPI GDMCValidateProvMessage ( const _u8 *msg, + _u32 msgsize, + gdmc_msgheader **ppheader, + _u8 **ppbody, + gdmc_msgtrailer **pptrailer ) +{ + _u32 expected_msgsize, aligned_body_size; + _u32 crc32; + gdmc_error_msg *errmsg; + gdmc_actmsg_resp *actmsg; + + *ppheader = NULL; + *ppbody = NULL; + *pptrailer = NULL; + + if (msgsize<(sizeof(gdmc_msgheader)+sizeof(gdmc_msgtrailer))) + return GDERROR_MESSAGE_FORMAT; + + if (msgsize&3) + return GDERROR_MESSAGE_FORMAT; + + if (IsBadReadPtr(msg,sizeof(gdmc_msgheader)+sizeof(gdmc_msgtrailer))) + return GDERROR_PARAMETER; + + *ppheader = (gdmc_msgheader*)msg; + + aligned_body_size = ((*ppheader)->body_size+3)&(~3); + + expected_msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_msgtrailer)+aligned_body_size; + + if (msgsize!=expected_msgsize) + return GDERROR_MESSAGE_FORMAT; + + if (IsBadReadPtr(msg,expected_msgsize)) + return GDERROR_PARAMETER; + + *ppbody = (_u8*)(msg+sizeof(gdmc_msgheader)); + *pptrailer = (gdmc_msgtrailer*)((*ppbody)+aligned_body_size); + + if ( (*ppheader)->msg_type != (~((*pptrailer)->magic)) ) + return GDERROR_MESSAGE_FORMAT; + + crc32 = CalcCRC32(msg,msgsize-sizeof(_u32)); + + if ( crc32 != (*pptrailer)->crc32 ) + return GDERROR_CRC32; + + switch((*ppheader)->msg_type) + { + case MC_GETSUID_REQ: + if ( 0!=(*ppheader)->body_size) + return GDERROR_MESSAGE_FORMAT; + break; + + case MC_GETSUID_RESP: + if ( SUID_LENGTH!=(*ppheader)->body_size) + return GDERROR_MESSAGE_FORMAT; + break; + + case MC_GENAUTHTOKEN_REQ: + if ( sizeof(gdmc_actmsg_req)!=(*ppheader)->body_size) + return GDERROR_MESSAGE_FORMAT; + if ( MC_CMP_CMD_GENERATE_AUTH_TOKEN != ((gdmc_actmsg_req*)(*ppbody))->msg_type ) + return GDERROR_MESSAGE_FORMAT; + break; + + case MC_GENAUTHTOKEN_RESP: + if ( sizeof(gdmc_actmsg_resp)!=(*ppheader)->body_size) + return GDERROR_MESSAGE_FORMAT; + actmsg = (gdmc_actmsg_resp*)*ppbody; + if ( (MC_CMP_CMD_GENERATE_AUTH_TOKEN|0x80000000) != actmsg->msg_type ) + return GDERROR_MESSAGE_FORMAT; + if ( (SUID_LENGTH+(sizeof(_u32)*3)) != actmsg->authtok.plain_length) + return GDERROR_MESSAGE_FORMAT; + if ( (K_SOC_AUTH_LENGTH/*+SHA256_HASH_LENGTH+AES_BLOCK_SIZE*/) != actmsg->authtok.encrypted_length ) + return GDERROR_MESSAGE_FORMAT; + if ( AUTHENTICATION_TOKEN != actmsg->authtok.type ) + return GDERROR_MESSAGE_FORMAT; + if ( CONTEXT_SYSTEM != actmsg->authtok.context ) + return GDERROR_MESSAGE_FORMAT; + if ( CONT_TYPE_SOC != actmsg->authtok.contType ) + return GDERROR_MESSAGE_FORMAT; + if ( MC_CONT_STATE_ACTIVATED != actmsg->authtok.contState ) + return GDERROR_MESSAGE_FORMAT; + break; + + case MC_VALIDATEAUTHTOKEN_REQ: + if ( sizeof(gdmc_so_authtok)!=(*ppheader)->body_size) + return GDERROR_MESSAGE_FORMAT; + break; + + case MC_ERROR: + if ( (*ppheader)->body_size<sizeof(gdmc_error_msg)) + return GDERROR_MESSAGE_FORMAT; + errmsg = (gdmc_error_msg*)*ppbody; + if ( (*ppheader)->body_size!=(errmsg->errmsg_length+sizeof(gdmc_error_msg)) ) + return GDERROR_MESSAGE_FORMAT; + break; + + default: + return GDERROR_MESSAGE_FORMAT; + } + + return GDERROR_OK; +} + +gderror GDPROVAPI GDMCHandleGetSUID ( gdmcinst *inst, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size ) +{ + _u32 msgsize = sizeof(gdmc_msgheader)+SUID_LENGTH+sizeof(gdmc_msgtrailer); + gdmc_msgheader *header = (gdmc_msgheader*)msgout; + _u8 *body = msgout+sizeof(gdmc_msgheader); + gdmc_msgtrailer *trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+SUID_LENGTH); + gderror error; + + if (msgsize>initial_msgout_size) + return GDMCComposeErrorMessage(inst,GDERROR_BUFFER_TOO_SMALL,msgout,msgout_size,initial_msgout_size, + ERRMSG_0005,initial_msgout_size,msgsize); + + if (inst->state<GDMC_STATE_HAVE_SUID) // request SUID from MobiCore + { + error = MCGetSUID(inst->suid); + + if (GDERROR_OK!=error) + return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size, + ERRMSG_000D); + + inst->state = GDMC_STATE_HAVE_SUID; + } + + // We have the SUID, so return the message to the caller + + header->msg_type = MC_GETSUID_RESP; + header->body_size = SUID_LENGTH; + + memcpy(body,inst->suid,SUID_LENGTH); + + trailer->magic = ~MC_GETSUID_RESP; + trailer->crc32 = CalcCRC32(msgout,msgsize-sizeof(_u32)); + + *msgout_size = msgsize; + + return GDERROR_OK; +} + +gderror GDPROVAPI GDMCHandleGenAuthToken ( gdmcinst *inst, + gdmc_actmsg_req *req, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size ) +{ + _u32 msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_actmsg_resp)+sizeof(gdmc_msgtrailer); + gdmc_msgheader *header = (gdmc_msgheader*)msgout; + gdmc_actmsg_resp *body = (gdmc_actmsg_resp*)(msgout+sizeof(gdmc_msgheader)); + gdmc_msgtrailer *trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+sizeof(gdmc_actmsg_resp)); + gderror error; + + if (msgsize>initial_msgout_size) + return GDMCComposeErrorMessage(inst,GDERROR_BUFFER_TOO_SMALL,msgout,msgout_size,initial_msgout_size, + ERRMSG_0005,initial_msgout_size,msgsize); + + switch(inst->state) + { + case GDMC_STATE_INITIAL: // We do not have the SUID, so get it... + error = GDMCHandleGetSUID(inst,msgout,msgout_size,initial_msgout_size); + if (GDERROR_OK!=error) + return error; + + // discard this message... + + memset(msgout,0,initial_msgout_size); + *msgout_size = 0; + + // fall through... + + case GDMC_STATE_HAVE_SUID: // We have the SUID but no SO.AuthToken (yet) + + GenerateAuthToken: + + memcpy(inst->kSoCAuth,req->kSoCAuth,sizeof(inst->kSoCAuth)); // save K.SoC.Auth + + error = MCGenerateAuthToken(inst,req,&inst->authTok); + + if (GDERROR_OK!=error) + return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,ERRMSG_000E); + + if (NULL!=g_authtok_writecb) + { + error = g_authtok_writecb((const _u8 *)&inst->authTok,sizeof(gdmc_so_authtok)); + if (GDERROR_OK!=error) + return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,ERRMSG_000C); + } + + header->msg_type = MC_GENAUTHTOKEN_RESP; + header->body_size = sizeof(gdmc_actmsg_resp); + + body->msg_type = MC_CMP_CMD_GENERATE_AUTH_TOKEN|0x80000000; + memcpy(&body->authtok,&inst->authTok,sizeof(gdmc_so_authtok)); + + trailer->magic = ~MC_GENAUTHTOKEN_RESP; + trailer->crc32 = CalcCRC32(msgout,msgsize-sizeof(_u32)); + + *msgout_size = msgsize; + + if (inst->state<GDMC_STATE_HAVE_AUTHTOK) + inst->state = GDMC_STATE_HAVE_AUTHTOK; + + return GDERROR_OK; + + default: //case GDMC_STATE_HAVE_AUTHTOK: -> We have already the SO.AuthTok, check if K.SoC.Auth still matches!!! + + if (memcmp(inst->kSoCAuth,req->kSoCAuth,sizeof(inst->kSoCAuth))) + { + // Oh oh... the KPH generated a new K.SoC.Auth and our SO.AuthToken is invalid now... (generate new one) + + memset(&inst->authTok,0,sizeof(inst->authTok)); + inst->state = GDMC_STATE_HAVE_SUID; + goto GenerateAuthToken; + } + + // Okay, K.SoC.Auth still matches and we still have the SO.AuthToken + + header->msg_type = MC_GENAUTHTOKEN_RESP; + header->body_size = sizeof(gdmc_actmsg_resp); + + body->msg_type = MC_CMP_CMD_GENERATE_AUTH_TOKEN|0x80000000; + memcpy(&body->authtok,&inst->authTok,sizeof(gdmc_so_authtok)); + + trailer->magic = ~MC_GENAUTHTOKEN_RESP; + trailer->crc32 = CalcCRC32(msgout,msgsize-sizeof(_u32)); + + *msgout_size = msgsize; + + return GDERROR_OK; + } +} + +gderror GDPROVAPI GDMCHandleValidateAuthToken ( gdmcinst *inst, + gdmc_so_authtok *validateSoAuthTok, + _u8 *msgout, + _u32 *msgout_size, + _u32 initial_msgout_size ) +{ + _u32 msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)+sizeof(gdmc_msgtrailer); + gdmc_msgheader *header = (gdmc_msgheader*)msgout; + gdmc_error_msg *body = (gdmc_error_msg*)(msgout+sizeof(gdmc_msgheader)); + gdmc_msgtrailer *trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)); + gderror error; + gdmc_so_authtok rb_authtok; + _u32 rb_authtok_size; + + if (msgsize>initial_msgout_size) + return GDMCComposeErrorMessage(inst,GDERROR_BUFFER_TOO_SMALL,msgout,msgout_size,initial_msgout_size, + ERRMSG_0005,initial_msgout_size,msgsize); + + if (GDMC_STATE_HAVE_AUTHTOK!=inst->state) // Too early call: We do not have an SO.AuthToken to be validated! + return GDMCComposeErrorMessage(inst,GDERROR_VALIDATION_FAILURE,msgout,msgout_size,initial_msgout_size, + ERRMSG_000F,initial_msgout_size,msgsize); + + header->msg_type = MC_ERROR; + header->body_size = sizeof(gdmc_error_msg); + + body->errorcode = GDERROR_PROVISIONING_DONE; + + // 1.) First of all, compare the delivered SO.AuthToken with the one we have stored in our instance + + if (memcmp(validateSoAuthTok,&inst->authTok,sizeof(gdmc_so_authtok))) + { + body->errorcode = GDERROR_VALIDATION_FAILURE; + } + else + { + // 2.) Perform readback (if available) and re-check auth token + + if (NULL!=g_authtok_readcb) + { + rb_authtok_size = sizeof(rb_authtok); + + error = g_authtok_readcb((_u8*)&rb_authtok,&rb_authtok_size); + + if (GDERROR_OK!=error) + body->errorcode = error; + else + { + if ( (rb_authtok_size!=sizeof(gdmc_so_authtok)) || + (memcmp(validateSoAuthTok,&rb_authtok,sizeof(gdmc_so_authtok))) ) + body->errorcode = GDERROR_VALIDATION_FAILURE; + } + } + } + + trailer->magic = ~MC_ERROR; + trailer->crc32 = CalcCRC32(msgout,msgsize-sizeof(_u32)); + + *msgout_size = msgsize; + + return GDERROR_PROVISIONING_DONE; +} + diff --git a/mobicore/provlib/src/gdmcprovlib.cpp b/mobicore/provlib/src/gdmcprovlib.cpp new file mode 100644 index 0000000..9c6dae7 --- /dev/null +++ b/mobicore/provlib/src/gdmcprovlib.cpp @@ -0,0 +1,399 @@ +/// +/// @file gdmcprovlib.cpp +/// @author Giesecke & Devrient GmbH, Munich, Germany +/// +/// Implementation of the API functions (Provisioning +/// Library) +/// + +#include <gdmcprovlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +////////////////////////////////////////////////////////////////////////////// +// MS Windows-specific includes +////////////////////////////////////////////////////////////////////////////// + +#if defined(WIN32) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +static HMODULE g_hInstance = NULL; + +////////////////////////////////////////////////////////////////////////////// +// Linux-specific includes +////////////////////////////////////////////////////////////////////////////// + +#elif defined(LINUX) + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <pthread.h> +#include <syslog.h> +#include <errno.h> +#include <time.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +////////////////////////////////////////////////////////////////////////////// +// ARM-specific includes +////////////////////////////////////////////////////////////////////////////// + +#else // ARM + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <pthread.h> +#include <errno.h> +#include <time.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#endif + +#include <gdmcprovprotocol.h> +#include <gdmcinstance.h> +#include <gdmcdevicebinding.h> + +extern "C" { +extern bool mccmOpen ( void ); +extern void mccmClose ( void ); +} + +authtok_writecb g_authtok_writecb = NULL; +authtok_readcb g_authtok_readcb = NULL; + +////////////////////////////////////////////////////////////////////////////// +// API functions (implementation) +////////////////////////////////////////////////////////////////////////////// + +// this API function is not available on ARM +static gderror GDPROVAPI _GDMCProvFormatErrorMessage ( + gdhandle provhandle, + gderror errorcode, + char *msgbuf, + _u32 *size ) +{ + return GDERROR_NOT_IMPLEMENTED; +} + +static gderror GDPROVAPI _GDMCProvInitializeLibrary ( void ) +{ + if (unlikely( !mccmOpen() )) + return GDERROR_MOBICORE_LIBRARY; + + return GDERROR_OK; +} + +static gderror GDPROVAPI _GDMCProvShutdownLibrary ( void ) +{ + mccmClose(); + return GDERROR_OK; +} + +static gderror GDPROVAPI _GDMCProvBeginProvisioning ( gdhandle *provhandle ) +{ + gdmcinst *inst; + + if (IsBadWritePtr(provhandle,sizeof(gdhandle))) + return GDERROR_PARAMETER; + + inst = (gdmcinst*)malloc(sizeof(gdmcinst)); + + if (NULL==inst) + { + *provhandle = 0; + return GDERROR_INSUFFICIENT_MEMORY; + } + + memset(inst,0,sizeof(gdmcinst)); + + *provhandle = (gdhandle)inst; + + return GDERROR_OK; +} + +static gderror GDPROVAPI _GDMCProvEndProvisioning ( gdhandle provhandle ) +{ + gdmcinst *inst = (gdmcinst*)provhandle; + + if (IsBadWritePtr(inst,sizeof(gdmcinst))) + return GDERROR_PARAMETER; + + free(inst); + + return GDERROR_OK; +} + +static gderror GDPROVAPI _GDMCProvExecuteProvisioningStep ( + gdhandle provhandle, + const _u8 *msgin, + _u32 msgin_size, + _u8 *msgout, + _u32 *msgout_size ) +{ + gderror error = GDERROR_OK; + gdmcinst *inst = (gdmcinst*)provhandle; + gdmc_msgheader *header = NULL; + _u8 *body = NULL; + gdmc_msgtrailer *trailer = NULL; + _u32 initial_msgout_size; + + // 1.) Prolog: Check parameters... + + if (IsBadWritePtr(inst,sizeof(gdmcinst))) + return GDERROR_PARAMETER; + + if ((0!=msgin_size) && (IsBadReadPtr(msgin,msgin_size))) + return GDERROR_PARAMETER; + + if (IsBadWritePtr(msgout_size,sizeof(_u32))) + return GDERROR_PARAMETER; + + initial_msgout_size = *msgout_size; + + if (0!=*msgout_size) + { + if (IsBadWritePtr(msgout,*msgout_size)) + return GDERROR_PARAMETER; + memset(msgout,0,*msgout_size); + } + + *msgout_size = 0; + + // 2.) Evaluate the message that has been received + + error = GDMCValidateProvMessage(msgin,msgin_size,&header,&body,&trailer); + + if (GDERROR_OK!=error) // something is wrong with the received message + return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,ERRMSG_0006); + + // 3.) Check which message has been received + + switch(header->msg_type) + { + case MC_GETSUID_REQ: + return GDMCHandleGetSUID(inst,msgout,msgout_size,initial_msgout_size); + + case MC_GENAUTHTOKEN_REQ: + return GDMCHandleGenAuthToken(inst,(gdmc_actmsg_req*)body,msgout,msgout_size,initial_msgout_size); + + case MC_VALIDATEAUTHTOKEN_REQ: + return GDMCHandleValidateAuthToken(inst,(gdmc_so_authtok*)body,msgout,msgout_size,initial_msgout_size); + + default: + return GDMCComposeErrorMessage(inst,GDERROR_UNKNOWN,msgout,msgout_size,initial_msgout_size,ERRMSG_0007); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Structured Exception Handling (Windows only) +////////////////////////////////////////////////////////////////////////////// + +#if defined(WIN32) && !defined(_NO_STRUCTURED_EXCEPTIONS) + +static DWORD GDPROVAPI HandleStructuredException ( DWORD dwExcepCode ) +{ +#ifndef _DEBUG + return EXCEPTION_EXECUTE_HANDLER; +#else // _DEBUG + switch(dwExcepCode) + { + case EXCEPTION_BREAKPOINT: + case EXCEPTION_SINGLE_STEP: + return EXCEPTION_CONTINUE_SEARCH; + default: + return EXCEPTION_EXECUTE_HANDLER; + } +#endif +} + +#define SE_TRY __try { +#define SE_CATCH } __except(HandleStructuredException(GetExceptionCode())) { return GDERROR_CPU_EXCEPTION; } + +#else // !WIN32 || _NO_STRUCTURED_EXCEPTIONS + +#define SE_TRY +#define SE_CATCH + +#endif // WIN32 + +////////////////////////////////////////////////////////////////////////////// +// API functions (exported) +////////////////////////////////////////////////////////////////////////////// + +extern "C" _u32 GDPROVAPI GDMCProvGetVersion ( void ) +{ + return GDMCPROVLIB_VERSION; +} + +extern "C" gderror GDPROVAPI GDMCProvFormatErrorMessage ( + gdhandle provhandle, + gderror errorcode, + char *msgbuf, + _u32 *size ) +{ + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return _GDMCProvFormatErrorMessage(provhandle,errorcode,msgbuf,size); + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// +} + +extern "C" gderror GDPROVAPI GDMCProvInitializeLibrary ( void ) +{ + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return _GDMCProvInitializeLibrary(); + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// +} + +extern "C" gderror GDPROVAPI GDMCProvShutdownLibrary ( void ) +{ + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return _GDMCProvShutdownLibrary(); + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// +} + +extern "C" gderror GDPROVAPI GDMCProvBeginProvisioning ( gdhandle *provhandle ) +{ + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return _GDMCProvBeginProvisioning(provhandle); + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// +} + +extern "C" gderror GDPROVAPI GDMCProvEndProvisioning ( gdhandle provhandle ) +{ + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return _GDMCProvEndProvisioning(provhandle); + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// +} + +extern "C" gderror GDPROVAPI GDMCProvExecuteProvisioningStep ( + gdhandle provhandle, + const _u8 *msgin, + _u32 msgin_size, + _u8 *msgout, + _u32 *msgout_size ) +{ + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return _GDMCProvExecuteProvisioningStep(provhandle,msgin,msgin_size, + msgout,msgout_size); + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// +} + +extern "C" gderror GDPROVAPI GDMCProvFormatReceipt ( + const _u8 *receipt, + _u32 receipt_size, + _u8 *fmt_receipt, + _u32 *fmt_receipt_size ) +{ + return GDERROR_NOT_IMPLEMENTED; +} + +extern "C" gderror GDPROVAPI GDMCProvGetSUID ( + gdhandle provhandle, + _u8 *suid ) +{ + return GDERROR_NOT_IMPLEMENTED; +} + +extern "C" gderror GDPROVAPI GDMCProvSetAuthTokenCallbacks ( + authtok_writecb writefunc, + authtok_readcb readfunc ) +{ + g_authtok_writecb = writefunc; + g_authtok_readcb = readfunc; + + return GDERROR_OK; +} + +extern "C" gderror GDPROVAPI GDMCProvSetConfigurationString ( + const char *config_string ) +{ +#ifdef ARM + + return GDERROR_NOT_IMPLEMENTED; + +#else + + SE_TRY // MUST BE FIRST INSTRUCTION //////////////////////////////////////// + + return GDERROR_OK; + + SE_CATCH // MUST BE LAST INSTRUCTION /////////////////////////////////////// + +#endif +} + +#ifdef WIN32 + +/// DLL main function required by MS Windows DLLs +/// +/// @param[in] hinstDLL instance handle (module) +/// @param[in] fdwReason reason for calling (attach, detach, ...) +/// @param[in] lpvReserved reserved +/// +/// @return TRUE if DLL loading/unloading successful, FALSE otherwise +BOOL WINAPI DllMain ( HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved ) +{ + switch(fdwReason) + { + case DLL_PROCESS_ATTACH: + // We don't need additional calls with DLL_THREAD_ATTACH. + g_hInstance = (HMODULE)hinstDLL; + DisableThreadLibraryCalls(hinstDLL); + InitCRCTable(); + return TRUE; + case DLL_PROCESS_DETACH: // fall through + case DLL_THREAD_ATTACH: // fall through + case DLL_THREAD_DETACH: + return TRUE; + default: + break; + } + return FALSE; +} + +#else // library initialization and cleanup (Linux/ARM) + +void gdmcprovlib_init ( void ) __attribute__((constructor)); +void gdmcprovlib_fini ( void ) __attribute__((destructor)); + +/// shared object global initialization function; gets automatically +/// called when library is loaded +void gdmcprovlib_init ( void ) +{ + InitCRCTable(); +} + +/// shared object global cleanup function; gets automatically +/// called when library is unloaded +void gdmcprovlib_fini ( void ) +{ + +} + +#endif // WIN32 + + diff --git a/mobicore/provlib/src/mobicore.c b/mobicore/provlib/src/mobicore.c new file mode 100644 index 0000000..2f4e419 --- /dev/null +++ b/mobicore/provlib/src/mobicore.c @@ -0,0 +1,587 @@ +#ifndef _SBL_VERSION // SBL = Secondary Bootloader Version + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <gdmcprovlib.h> +#include <gdmcprovprotocol.h> +#include <gdmcinstance.h> + +typedef struct tagMCCM MCCM; + +struct tagMCCM +{ + cmp_t *cmp; ///< World Shared Memory (WSM) to the TCI buffer + mcSessionHandle_t sess; ///< session handle + mcResult_t lasterror; ///< last MC driver error + cmpReturnCode_t lastcmperr; ///< last Content Management Protocol error + uint32_t lastmccmerr; ///< error code from MCCM (MobiCore Content Management) library +}; + +static MCCM g_mccm; + +// Copied from MCCM library not to have this additional dependency! + +// returns 1 if successful, 0 otherwise +bool mccmOpen ( void ) +{ + const mcUuid_t UUID = TL_CM_UUID; + mcResult_t result; + + memset(&g_mccm,0,sizeof(MCCM)); + + result = mcOpenDevice(MC_DEVICE_ID_DEFAULT); + + if (MC_DRV_OK != result) + return false; + + result = mcMallocWsm(MC_DEVICE_ID_DEFAULT, 0, sizeof(cmp_t), (uint8_t **)&g_mccm.cmp, 0); + if (MC_DRV_OK != result) + { + mcCloseDevice(MC_DEVICE_ID_DEFAULT); + return false; + } + + result = mcOpenSession(&g_mccm.sess,(const mcUuid_t *)&UUID,(uint8_t *)g_mccm.cmp,(uint32_t)sizeof(cmp_t)); + if (MC_DRV_OK != result) + { + mcFreeWsm(MC_DEVICE_ID_DEFAULT,(uint8_t*)g_mccm.cmp); + mcCloseDevice(MC_DEVICE_ID_DEFAULT); + return false; + } + + return true; +} + +void mccmClose ( void ) +{ + mcCloseSession(&g_mccm.sess); + + if (NULL!=g_mccm.cmp) + mcFreeWsm(MC_DEVICE_ID_DEFAULT,(uint8_t*)g_mccm.cmp); + + mcCloseDevice(MC_DEVICE_ID_DEFAULT); + + memset(&g_mccm,0,sizeof(MCCM)); +} + +static bool mccmTransmit ( int32_t timeout ) +{ + // Send CMP message to content management trustlet. + + g_mccm.lasterror = mcNotify(&g_mccm.sess); + + if (unlikely( MC_DRV_OK!=g_mccm.lasterror )) + return false; + + // Wait for trustlet response. + + g_mccm.lasterror = mcWaitNotification(&g_mccm.sess, timeout); + + if (unlikely( MC_DRV_OK!=g_mccm.lasterror )) + return false; + + return true; +} + +static bool mccmGetSuid ( mcSuid_t *suid ) +{ + g_mccm.lastcmperr = SUCCESSFUL; + + memset(g_mccm.cmp,0,sizeof(cmp_t)); + g_mccm.cmp->msg.cmpCmdGetSuid.cmdHeader.commandId = MC_CMP_CMD_GET_SUID; + + if (unlikely( !mccmTransmit(MC_INFINITE_TIMEOUT) )) + return false; + + if (unlikely( (MC_CMP_CMD_GET_SUID|RSP_ID_MASK)!=g_mccm.cmp->msg.cmpRspGetSuid.rspHeader.responseId )) + { + g_mccm.lasterror = MC_DRV_ERR_UNKNOWN; + return false; + } + + g_mccm.lastcmperr = g_mccm.cmp->msg.cmpRspGetSuid.rspHeader.returnCode; + + if (unlikely( SUCCESSFUL!=g_mccm.lastcmperr )) + { + g_mccm.lasterror = MC_DRV_ERR_UNKNOWN; + return false; + } + + memcpy(suid,&g_mccm.cmp->msg.cmpRspGetSuid.suid,sizeof(mcSuid_t)); + + return true; +} + +static bool mccmGenerateAuthToken ( + const cmpCmdGenAuthToken_t *cmd, + cmpRspGenAuthToken_t *rsp ) +{ + g_mccm.lastcmperr = SUCCESSFUL; + + memset(g_mccm.cmp,0,sizeof(cmp_t)); + + memcpy(g_mccm.cmp,cmd,sizeof(*cmd)); + + if (unlikely( !mccmTransmit(MC_INFINITE_TIMEOUT) )) + return false; + + if (unlikely( (cmd->cmd.sdata.cmdHeader.commandId|RSP_ID_MASK)!=g_mccm.cmp->msg.cmpRspGenAuthToken.rsp.rspHeader.responseId )) + { + g_mccm.lasterror = MC_DRV_ERR_UNKNOWN; + return false; + } + + g_mccm.lastcmperr = g_mccm.cmp->msg.cmpRspGenAuthToken.rsp.rspHeader.returnCode; + + if (unlikely( SUCCESSFUL!=g_mccm.lastcmperr )) + { + g_mccm.lasterror = MC_DRV_ERR_UNKNOWN; + return false; + } + + memcpy(rsp,g_mccm.cmp,sizeof(*rsp)); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// Convenience functions +/////////////////////////////////////////////////////////////////////////////////////////// + +gderror MCGetSUID ( _u8 *suid ) +{ + if (unlikely( NULL==suid )) + return GDERROR_PARAMETER; + + memset(suid,0,SUID_LENGTH); + + if (!mccmGetSuid((mcSuid_t*)suid)) + return GDERROR_CANT_GET_SUID; + + return GDERROR_OK; +} + +gderror MCGenerateAuthToken ( gdmcinst *inst, const gdmc_actmsg_req *req, gdmc_so_authtok *authtok ) +{ + cmpRspGenAuthToken_t rsp; + + if (unlikely( NULL==inst || NULL==req || NULL==authtok )) + return GDERROR_PARAMETER; + + memset(authtok,0,sizeof(gdmc_so_authtok)); + + if (MC_CMP_CMD_GENERATE_AUTH_TOKEN!=req->msg_type) + return GDERROR_MESSAGE_FORMAT; + + if (!mccmGenerateAuthToken((const cmpCmdGenAuthToken_t *)req,&rsp)) + return GDERROR_CANT_BUILD_AUTHTOKEN; + + memcpy(authtok,&rsp.soAuthCont,sizeof(*authtok)); + + return GDERROR_OK; +} + +#else // Secondary Bootloader Version + +#define _NO_OPENSSL_INCLUDES + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <gdmcprovlib.h> +#include <gdmcprovprotocol.h> +#include <gdmcinstance.h> + +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) + +typedef unsigned char u_int8_t; /* 1-byte (8-bits) */ +typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */ +typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */ + +typedef unsigned char sha2_byte; /* Exactly 1 byte */ +typedef unsigned int sha2_word32; /* Exactly 4 bytes */ +typedef unsigned long long sha2_word64; /* Exactly 8 bytes */ + +typedef struct _SHA256_CTX { + u_int32_t state[8]; + u_int64_t bitcount; + u_int8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; + +static void SHA256(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]); + +gderror MCGetSUID ( gdmcinst *inst, _u8 suid[SUID_LENGTH] ) +{ + inst->suid[ 0] = 0x11; + inst->suid[ 1] = 0x22; + inst->suid[ 2] = 0x33; + inst->suid[ 3] = 0x44; + inst->suid[ 4] = 0x55; + inst->suid[ 5] = 0x66; + inst->suid[ 6] = 0x77; + inst->suid[ 7] = 0x88; + inst->suid[ 8] = 0x99; + inst->suid[ 9] = 0xAA; + inst->suid[10] = 0xBB; + inst->suid[11] = 0xCC; + inst->suid[12] = 0xDD; + inst->suid[13] = 0xEE; + inst->suid[14] = 0xFF; + inst->suid[15] = 0xFE; + + memcpy(suid,inst->suid,SUID_LENGTH); + + return GDERROR_OK; +} + +gderror MCGenerateAuthToken ( gdmcinst *inst, const gdmc_actmsg_req *req, gdmc_so_authtok *authtok ) +{ + _u8 md[SHA256_DIGEST_LENGTH]; + mcSoAuthTokenCont_t tok; + + memset(&tok,0,sizeof(tok)); + memset(authtok,0,sizeof(gdmc_so_authtok)); + + if (MC_CMP_CMD_GENERATE_AUTH_TOKEN!=req->msg_type) + return GDERROR_MESSAGE_FORMAT; + + SHA256((const unsigned char *)req,offsetof(gdmc_actmsg_req,md),md); // hash it... + + if (memcmp(md,req->md,SHA256_DIGEST_LENGTH)) + return GDERROR_MESSAGE_DIGEST; + + if (memcmp(inst->suid,req->suid,SUID_LENGTH)) + return GDERROR_SUID_MISMATCH; + + // Header: + + tok.soHeader.type = MC_SO_TYPE_REGULAR; + tok.soHeader.version = 1; + tok.soHeader.context = MC_SO_CONTEXT_DEVICE; + tok.soHeader.plainLen = sizeof(tok.coSoc.type)+ + sizeof(tok.coSoc.attribs)+ + sizeof(tok.coSoc.suid); + tok.soHeader.encryptedLen = sizeof(tok.coSoc.co); + + // Plain data: + + tok.coSoc.type = CONT_TYPE_SOC; + tok.coSoc.attribs.state = MC_CONT_STATE_ACTIVATED; + + memcpy(&tok.coSoc.suid,inst->suid,sizeof(tok.coSoc.suid)); + + // Secret: + + memcpy(&tok.coSoc.co.kSocAuth,&inst->kSoCAuth,sizeof(tok.coSoc.co.kSocAuth)); + + SHA256((const unsigned char *)&tok, + offsetof(mcSoAuthTokenCont_t,hashAndPad), + (char *)&tok.hashAndPad); + + tok.hashAndPad[MC_SO_HASH_SIZE] = 0x80; // ISO-padding + + memcpy(authtok,&tok,sizeof(gdmc_so_authtok)); + + return GDERROR_OK; +} + +#undef SHA2_UNROLL_TRANSFORM + +#define LITTLE_ENDIAN 1234 +#define BYTE_ORDER LITTLE_ENDIAN + +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#if BYTE_ORDER == LITTLE_ENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ +} +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +#define R(b,x) ((x) >> (b)) +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +void SHA256_Transform(SHA256_CTX*, const sha2_word32*); + +const static sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +const static sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +static void SHA256_Init(SHA256_CTX* context) +{ + if (context == (SHA256_CTX*)0) + { + return; + } + memcpy(context->state,sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + memset(context->buffer, 0,SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +static void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#define bcopy(s,d,len) memcpy(d,s,len) +#define bzero(d,len) memset(d,0,len) + +static void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + + bcopy(data, &context->buffer[usedspace], freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + bcopy(data, &context->buffer[usedspace], len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context, (const sha2_word32*)data); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + bcopy(data, context->buffer, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +static void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { + sha2_word32 *d = (sha2_word32*)digest; + unsigned int usedspace; + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace < SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + bcopy(context->state, d, SHA256_DIGEST_LENGTH); +#endif + } + + /* Clean up state data: */ + bzero(context, sizeof(context)); + usedspace = 0; +} + +static void SHA256(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) +{ + SHA256_CTX context; + + SHA256_Init(&context); + SHA256_Update(&context, data, len); + SHA256_Final(digest,&context); +} + +#endif \ No newline at end of file